简体   繁体   中英

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.

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. Where is the data 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. 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.

Marking a local variable as final tells the compiler that its value is guaranteed not to change once it has been assigned. 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.

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.

The story behind this is that the creators of java didn't have enough time to make full support of closure .

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.

So they create inner class to have a poor man's version of closure which mimics the style of ML.

Method Local inner classes can't use local variable of outer method until that local variable is not declared as 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.

checkout this article: 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 .

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.

But about final variable JVM take these as a constant as they will not change after initiated . 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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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