Unexpected error using lambdas in Java 8

I am using Java 8 Update 20 32 bit, Maven 3.2.3, Eclipse Luna Build id: 20140612-0600 32 bit.

After running lambdas, some classes in my projects started reporting compilation errors in maven ( mvn compile ).

These errors only appear when I use lambdas. If I go back to anonymous classes, the errors go away.

I can reproduce the error with 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 will compile it as follows:

 mvn clean;mvn compile 

And I get 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 pretty clear about what is happening (the compiler believes that the final panel variable is called before it has been created), the variable will not be called until the button issues an action, and how can we When you start to act, the code must compile. In fact, it compiles as if I were not using lambdas:

 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 more strange things related to this problem:

  • Eclipse does not report this error when automatically compiling a class. Eclipse uses the same JDK as maven to compile the class.
  • If I use maven to compile the class using anonymous classes, I change the class to use lambdas and compile it using maven again, it does not report an error. In this case, it again reports an error if I use mvn clean and then mvn compile .

Can someone help me solve this problem? Or try to reproduce this problem?

+6
source share
1 answer

Although the error message is pretty clear about what is happening (the compiler thinks that the final panel variable is called before it is created), the variable will not be called until the button produces an action, and as we can " When the action happens, the code should compile.

You must consider the fact that compilers follow formal rules and do not have your knowledge. In particular, the compiler does not know that the addActionListener method addActionListener not call the actionPerformed method. He also has no idea about the visibility of a button that determines when actionPerformed could be called.

Formal behavior has a specification . Here you will find the following items:

Chapter 16. Defined Assignment

Each local variable (ยง14.4) and each empty final field (ยง4.12.4, ยง8.3.1.2) must have a specifically assigned value when any access to its value takes place.

Access to its value consists of a simple variable name (or for a field, a simple field name corresponding to this ) that appears anywhere in the expression, except for the left operand of the simple assignment operator = (ยง15.26.1).

and

15.27.2. Lambda body

...

Unlike code appearing in anonymous class declarations, the meaning of the this and super names and keywords appearing in the lambda body, along with the availability of link declarations, are the same as in the surrounding context (except that the lambda parameters introduce new names) .

In your code, the meaning of the names inside the lambda body read by panel is the same as in the surrounding context, which is the constructor. In this context, a rule is applied in which "every empty final field must have a specifically assigned value when any access to its value takes place."

And yes, this is different from the definition of an inner class. The specification explicitly states that.

+8
source

Source: https://habr.com/ru/post/975127/


All Articles