繁体   English   中英

如何将变量标记为最终允许内部类访问它们?

[英]How does marking a variable as final allow inner classes to access them?

在方法内部定义的内部类不能访问方法的局部变量,除非这些局部变量标记为final我已经查看了堆栈溢出和java代码牧场中的其他帖子,但它们似乎都没有完全回答关于如何标记变量final允许内部类访问方法中的局部变量。

class MyOuter {
    private String x = "Outer";

    void fly(final int speed) {
        final int e = 1;
        class FlyingEquation {

            public void seeOuter()
            {
                System.out.println("Outer x is " + x);
            }
            public void display()
            {
                System.out.println(e);// line 1
                System.out.println(speed);// line 2
            }
        }
        FlyingEquation f=new FlyingEquation();
        f.seeOuter();
        f.display();
    }       
    public static void main(String args[])
    {
        MyOuter mo=new MyOuter();
        mo.fly(5);
    }
}

我发现的解释:

局部变量存储在堆栈中,一旦方法调用完成,就会弹出堆栈并且本地变量不可访问,而最终局部变量存储在内存的数据部分中,可能允许JVM在方法调用结束后访问它们。 data section of memorydata section of memory在哪里? 我相信所有局部变量fi​​nal或not都存储在堆栈中。当从堆栈中删除方法时,最终变量将被删除。 最终变量中的值是否与堆中的对象一起存储?

它不支持非final字段,因为它们可以通过方法或类进行更改,但这不受支持,因为实际上有两个不同的字段/变量。

将局部变量标记为final表示编译器保证其值在分配后不会更改。 这使得编译器可以安全地在内部类中创建合成字段,并在构造内部类实例时将局部变量的值复制到此合成字段中。 从内部类代码中读取局部变量实际上编译为合成字段的读取。

这个技巧对于非最终变量不起作用,因为它们可能在实例化内部类之后发生变化,并且合成字段将与原始变量不同步。

重要的是要意识到所有内部类都是编译器的技巧 - 对于运行时JVM,所有类(顶级,嵌套静态和内部)都被视为相同。

在内部类的实例化期间,当方法和类都在范围内时,内部类将复制作为常量的变量,这意味着该方法可能超出范围,因为内部类仅使用变量的副本。 看看这篇文章

是的,最终的局部变量保存在堆栈中,并在方法从堆栈中删除时被销毁。 正如@Ian所建议的,当编译器看到变量的final关键字时,它会在堆上的内部类对象中创建值的副本。

这背后的故事是java的创建者没有足够的时间来完全支持关闭

有几种方法可以使语言支持关闭。 例如,在方案中,函数中的自由参数被绑定到与定义函数的词法范围相对应的环境。 在强制不可变数据(如SML)的语言中,可以通过将闭包所需的局部变量复制到堆来实现闭包。

因此,他们创造了内部阶级,以便有一个穷人的封闭版本,模仿ML的风格。

方法本地内部类不能使用外部方法的局部变量,直到该局部变量未声明为final。 我们需要将局部变量声明为final的主要原因是局部变量存在于堆栈中,直到方法在堆栈上,但可能存在内部类的对象仍然存在于堆上的情况。

结帐这篇文章: http//www.geeksforgeeks.org/inner-class-java/

所以现在考虑一下。该方法的局部变量存在于堆栈中 ,仅存在于方法的生命周期中。 我们已经知道局部变量的范围仅限于声明变量的方法。当方法结束时,堆栈帧被吹走,变量是历史。 但即使在方法完成之后,在其中创建的内部类对象仍可能在堆上存活,例如,如果对它的引用被传递到其他代码中,然后存储在实例变量中。 因为局部变量不保证只要方法本地内部类对象存在,所以内部类对象不能使用它们。 除非局部变量标记为final

最终的局部变量是否存储在堆而不是堆栈中?

说明:现在经过SO的一些研究后发现,当方法执行结束时,所有局部变量( final或not )都存储到堆栈中并超出范围。

但是关于最终变量JVM将这些作为常量,因为它们在启动后不会改变。 当一个内部类试图访问这些编译器创建变量(不是可变它自己)到堆中的副本,并创建内部类中的合成场 ,所以即使在方法执行结束这是因为内访问class有它自己的副本。 提交的合成字段实际上不存在于源代码中,但编译器在某些内部类中创建这些字段以使这些字段可访问。 在简单的单词隐藏领域。

所以最终变量也存储在堆栈中,但是内部类存储在堆中的变量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM