java – Final variable for anonymous class

Question:

There is a sample code:

public static void main(String[] args){
    int a=5;
    new Thread(new Runnable(){
        @Override
        public void run() {
            System.out.println(a);
        }
    }).start();
}

You need to use the variable a in an anonymous class, the compiler says to declare it as final .

Why should it be final ?

Answer:

This is a limitation introduced by the developers of the specification: when creating an anonymous class, objects are captured by value, not by reference. Private fields are created in the anonymous class, into which the values ​​of the passed variables are copied. That is, in fact, emulation of closures is implemented.

Adding the final modifier, as it were, tells the programmer that when using this kind of closures, there will be no side effects (imagine that you passed a variable to the created object of an anonymous class, and then changed it "outside" – you can reasonably expect that this change will be reflected inside the closure as well, but this is not so due to the notorious emulation; however, the change in the internal state of mutable objects will be visible both there and there).

To implement full-fledged closures, it is necessary to extend the life cycle of captured objects (this applies to objects located on the stack, which are destroyed when they leave the scope in which they are declared).

Why hasn't it been implemented so far? This kind of implementation requires a major change in the JVM architecture itself. These kinds of changes are quite difficult to implement for certain reasons:

  • it will take a lot of effort to make changes not only from Oracle, but also from third-party developers (debuggers, obfuscators, IDEs, compilers, etc.).
  • Making such a change can lead to a loss of backward compatibility, affecting many existing applications.
  • The change may affect other JVM-specific languages ​​/ platforms.

Java 8 introduced the concept of effectively final – these are variables that do not have the final modifier, but can be used in anonymous classes and lambda expressions. A variable will be effectively final if, after its definition, it does not change. Accordingly, in Java 8, your code will be compiled.


Additional links for more details:

Scroll to Top