简体   繁体   中英

Effectively final - Inner classes access

Inner classes only have access to final or effectively final variables. I don't understand though, why an instance variable can be accessed no matter what, but local variables and method parameters need to be at minimum effectively final?

Consider the following code:

public class BookStore {   

    private static final int taxId = 300000;   
    public String name;   

    public String searchBook(final String criteria) {      
        int count = 0;      
        int sum = 0;      
//      name = "";      I can uncomment this -> no compile error
        class Enumerator {         
            String interate(int k) {    
                System.out.println(name);
                System.out.println(sum);
                return "";         
            }             
        }            
//      sum++;      If I uncomment this, a compile error will be thrown.
        return "";
    }

}

Why is it necessary that local variables + method arguments need to be effectively final?

It's because of the scope of the local variables. Their scope is the method in which they are declared. Once execution has left the method, they are no longer valid. However, an inner class such as your Enumerator class can live on past the method execution, eg by returning a reference to a class instance.

Thus, the Enumerator class and its methods can be accessed outside of the method in which it is declared. At that point, it needs to assume that the local variables it referenced have the same value they had when execution instantiated the class.

For instance variables, the scope of these and of the inner class is the same - they are both available as long as the parent class instance exists.

It's all about the value which is captured when the instance is created. Inner classes in an instance context always capture the immutable outer this reference¹, through which the instance fields can be accessed, mutable or not. In contrast, local variables can only be captured by their value, hence, the variable must not change, to be consistent with the captured value.

This is a design decision. Technically, it would be no problem to a) allow subsequent mutations that are not reflected by the inner class' state or b) wrap every shared local variable into an object to allow mutations like with instance fields of the outer class, but neither, allowed inconsistency nor local variables that aren't actually local, were deemed acceptable by the language designers.

¹ This differs from lambda expressions which only capture this when actually accessing instance variables

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