Why is the Elvis elvis definition has to be final to be used inside the Thread run() method?
Elvis elvis = Elvis.INSTANCE; // ----> should be final Elvis elvis = Elvis.INSTANCE
elvis.sing(4);
Thread t1 = new Thread(
new Runnable() {
@Override
public void run() {
elvis.sing(6); // --------> elvis has to be final to compile
}
}
);
public enum Elvis {
INSTANCE(2);
Elvis() {
this.x = new AtomicInteger(0);
}
Elvis(int x){
this.x = new AtomicInteger(x);
}
private AtomicInteger x = new AtomicInteger(0);
public int getX() { return x.get(); }
public void setX(int x) {this.x = new AtomicInteger(x);}
public void sing(int x) {
this.x = new AtomicInteger(x);
System.out.println("Elvis singing.." + x);
}
}
The value of the
elvisvariable is being captured by the anonymous inner class.Java only (currently) captures variables by value. The compiler requires that the variable is final so that there can be no confusion about what will actually be used when the
runmethod is called in the new thread: if you changed the value ofelvisafter creating the new thread but before starting it, what would you expect it to do?This is a difference between the way that closures are effectively available in C# and Java. See my closures article for more details of this. Java 7 will make closures more concise – I haven’t been following along to know whether there will be any way of capturing the variable itself rather than a particular value.