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

Aay*_*ush 17 java

在方法内部定义的内部类不能访问方法的局部变量,除非标记了这些局部变量.我已经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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我发现的解释:

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

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

Ian*_*rts 13

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

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

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


Anu*_*u11 12

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