简体   繁体   English

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

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

An inner class defined inside a method cannot access the method's local variables unless these local variables are marked final .I've looked at other posts in stack-overflow and java code ranch but none of them seem to be exactly answering the question as to how marking variables final allows inner class to access local variables in the method. 在方法内部定义的内部类不能访问方法的局部变量,除非这些局部变量标记为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);
    }
}

Explanations I found to this : 我发现的解释:

local variables are stored on stack and as soon as the method call finishes the stack is popped up and local variables are inaccessible whereas final local variables are stored in data section of memory potentially allowing JVM to access them even after the end of the method call. 局部变量存储在堆栈中,一旦方法调用完成,就会弹出堆栈并且本地变量不可访问,而最终局部变量存储在内存的数据部分中,可能允许JVM在方法调用结束后访问它们。 Where is the data section of memory ? data section of memorydata section of memory在哪里? I believe all local variables final or not are stored on the stack.When the method is removed from the stack the final variable will be removed with it. 我相信所有局部变量fi​​nal或not都存储在堆栈中。当从堆栈中删除方法时,最终变量将被删除。 Is it that the value in the final variable is stored with the object in the heap ? 最终变量中的值是否与堆中的对象一起存储?

It does not support non-final fields as they could be changed, either by the method or the class and this is not supported because in reality there are two different fields/variables. 它不支持非final字段,因为它们可以通过方法或类进行更改,但这不受支持,因为实际上有两个不同的字段/变量。

Marking a local variable as final tells the compiler that its value is guaranteed not to change once it has been assigned. 将局部变量标记为final表示编译器保证其值在分配后不会更改。 This makes it safe for the compiler to create a synthetic field inside the inner class and copy the value of the local variable into this synthetic field when the inner class instance is constructed. 这使得编译器可以安全地在内部类中创建合成字段,并在构造内部类实例时将局部变量的值复制到此合成字段中。 All reads of the local variable from inside the inner class code actually compile into reads of the synthetic field instead. 从内部类代码中读取局部变量实际上编译为合成字段的读取。

This trick wouldn't work for non-final variables as they might change after the inner class was instantiated, and the synthetic field would get out of sync with the original variable. 这个技巧对于非最终变量不起作用,因为它们可能在实例化内部类之后发生变化,并且合成字段将与原始变量不同步。

It's important to realise that all inner classes are tricks of the compiler - to the runtime JVM all classes (top-level, nested static, and inner) are treated the same. 重要的是要意识到所有内部类都是编译器的技巧 - 对于运行时JVM,所有类(顶级,嵌套静态和内部)都被视为相同。

During instantiation of the inner class, when both the method and the class are in scope, the inner class will make a copy of the variables which are constants, which means that the method can go out of scope, since the inner class is only using a copy of the variable. 在内部类的实例化期间,当方法和类都在范围内时,内部类将复制作为常量的变量,这意味着该方法可能超出范围,因为内部类仅使用变量的副本。 Check out this article . 看看这篇文章

Yes the final local variables are saved on the stack and is destroyed the moment the method is removed from the stack. 是的,最终的局部变量保存在堆栈中,并在方法从堆栈中删除时被销毁。 As @Ian has suggested ,when the compiler sees the final keyword for the variable, it creates a copy of the value in the inner class object on the heap. 正如@Ian所建议的,当编译器看到变量的final关键字时,它会在堆上的内部类对象中创建值的副本。

The story behind this is that the creators of java didn't have enough time to make full support of closure . 这背后的故事是java的创建者没有足够的时间来完全支持关闭

There are several ways to make the language support closure. 有几种方法可以使语言支持关闭。 For example, in scheme, the free parameters in a function are bound to an environment which corresponds to the lexical scope where the function is defined. 例如,在方案中,函数中的自由参数被绑定到与定义函数的词法范围相对应的环境。 In a language which forces immutable data such as SML, closure can be implemented by copying the local variables which are needed by the closure to the heap. 在强制不可变数据(如SML)的语言中,可以通过将闭包所需的局部变量复制到堆来实现闭包。

So they create inner class to have a poor man's version of closure which mimics the style of ML. 因此,他们创造了内部阶级,以便有一个穷人的封闭版本,模仿ML的风格。

Method Local inner classes can't use local variable of outer method until that local variable is not declared as final. 方法本地内部类不能使用外部方法的局部变量,直到该局部变量未声明为final。 The main reason we need to declare a local variable as a final is that local variable lives on stack till method is on the stack but there might be a case the object of inner class still lives on the heap. 我们需要将局部变量声明为final的主要原因是局部变量存在于堆栈中,直到方法在堆栈上,但可能存在内部类的对象仍然存在于堆上的情况。

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

So now think about it.The local variables of the method live on the stack and exist only for the lifetime of the method. 所以现在考虑一下。该方法的局部变量存在于堆栈中 ,仅存在于方法的生命周期中。 We already know that the scope of a local variable is limited to the method the variable is declared in. When the method ends, the stack frame is blown away and the variable is history. 我们已经知道局部变量的范围仅限于声明变量的方法。当方法结束时,堆栈帧被吹走,变量是历史。 But even after the method completes, the inner class object created within it might still be alive on the heap if, for example, a reference to it was passed into some other code and then stored in an instance variable. 但即使在方法完成之后,在其中创建的内部类对象仍可能在堆上存活,例如,如果对它的引用被传递到其他代码中,然后存储在实例变量中。 Because the local variables aren't guaranteed to be alive as long as the method local inner class object is, the inner class object can't use them. 因为局部变量不保证只要方法本地内部类对象存在,所以内部类对象不能使用它们。 Unless the local variables are marked final . 除非局部变量标记为final

Does final local variables get stored on a heap instead of stack ? 最终的局部变量是否存储在堆而不是堆栈中?

Explanation: Now after some researching in SO i found out that all local variable ( final or not ) stored into the stack and go out of scope when the method execution is over. 说明:现在经过SO的一些研究后发现,当方法执行结束时,所有局部变量( final或not )都存储到堆栈中并超出范围。

But about final variable JVM take these as a constant as they will not change after initiated . 但是关于最终变量JVM将这些作为常量,因为它们在启动后不会改变。 And when a inner class try to access them compiler create a copy of that variable (not that variable it self) into the heap and create a synthetic field inside the inner class, so even when the method execution is over it is accessible because the inner class has it own copy. 当一个内部类试图访问这些编译器创建变量(不是可变它自己)到堆中的副本,并创建内部类中的合成场 ,所以即使在方法执行结束这是因为内访问class有它自己的副本。 Synthetic field are filed which actually doesn't exist in the source code but compiler create those fields in some inner classes to make those field accessible. 提交的合成字段实际上不存在于源代码中,但编译器在某些内部类中创建这些字段以使这些字段可访问。 In simple word hidden field. 在简单的单词隐藏领域。

So final variable also stored in stack but the copy that variable which a inner class have stored in heap. 所以最终变量也存储在堆栈中,但是内部类存储在堆中的变量。

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

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