Java 8 (and Lambdas) introduce the effectively final term: even though you didn't delcare it final with the final
keyword, if it is not modified, it is as good as final.
Quoting from Oracle Tutorial: Local Classes:
However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final.
Your message is effectively final so it is valid to refer to it from anonymous inner classes and lambdas.
If you change the value of the message, it will not be effectively final anymore:
String message = "Hello world";
new Runnable() {
@Override
public void run() {
System.out.println(message);
}
}.run();
message = "modified";
And therefore you get the following error (from Eclipse):
Local variable message defined in an enclosing scope must be final or effectively final
Or form javac
:
error: local variables referenced from an inner class must be final or effectively final