An unexpected error occurred while using Lambdas in Java 8
I use Java 8 update 20 32-bit, Maven 3.2 3. Eclipse Luna build ID: 20140612-0600 32 bits
After I started using Lambdas, some classes in my project started reporting MVN compile errors in Maven
These errors only occur when I use Lambdas If I switch back to the anonymous class, the error disappears
I can reproduce the error through a simple test case:
package br; import java.awt.Button; import java.awt.Panel; public class Test { private final Button button; private final Panel panel; public test() { button = new Button(); button.addActionListener(event -> { System.out.println(panel); }); panel = new Panel(); } }
I compile this:
mvn clean;mvn compile
I received this error:
[ERROR] /C:/Users/fabiano/workspace-luna/Test/src/main/java/br/Test.java:[14,44] variable panel might not have been initialized
Although the error message is very clear about what is happening (the compiler thinks that the final variable panel will be called before instantiation), the variable will not be called before the button generates the action, and we can't say that the action will happen. The code should be compiled In fact, if I don't use lambda, it will compile as it should:
package br; import java.awt.Button; import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Test { private final Button button; private final Panel panel; public test() { button = new Button(); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println(panel); } }); panel = new Panel(); } }
I noticed two other strange things related to this problem:
>Eclipse does not report this error when automatically compiling classes Eclipse uses the same JDK as Maven to compile classes. > If I use Maven to compile a class using anonymous classes, I change the class to use Lambdas and compile it again using maven, which will not report errors In this case, if I use MVN clean and then MVN compile, it will only report the error again
Can someone help me solve this problem? Or try to reproduce the problem?
Solution
You should consider that the compiler follows formal rules and does not know your facts In particular, the compiler cannot know that the method addactionlistener will not call the actionperformed method immediately It also doesn't know the visibility of the button, and it determines when actionperformed can be called
Formal behavior has a specification There you will find the following:
Chapter 16. Definite Assignment
and
15.27. 2. Lambda Body
In your code, the meaning of lambda body name, panel reading, is the same as the context around the constructor In this context, the rule "each blank final field must have an explicit assignment when any access to its value occurs" applies
And, yes, this is different from the internal class definition The specification clearly points out this point