gpt4 book ai didi

java - 在 Java 8 中使用 lambda 出现意外错误

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:17:45 24 4
gpt4 key购买 nike

我正在使用 Java 8 Update 20 32 位、Maven 3.2.3、Eclipse Luna Build id:20140612-0600 32 位。

开始使用lambdas后,我项目中的一些类在maven(mvn compile)中开始报编译错误。

这些错误仅在我使用 lambda 时出现。如果我切换回匿名类,错误就消失了。

我可以用一个简单的测试用例重现错误:

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();
}
}

我是这样编译的:

mvn clean;mvn compile

我得到这个错误:

[ERROR] /C:/Users/fabiano/workspace-luna/Test/src/main/java/br/Test.java:[14,44] variable panel might not have been initialized

虽然错误消息非常清楚发生了什么(编译器认为最终变量 panel 在实例化之前被调用),但直到按钮生成 Action 时才会调用该变量,以及我们如何不能说操作何时发生,代码应该编译。事实上,如果我不使用 lambda,它会按预期编译:

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();
}
}

我注意到另外两件与此问题相关的奇怪事情:

  1. Eclipse 在自动编译类时不会报告此错误。 Eclipse 使用与 Maven 相同的 JDK 来编译该类。
  2. 如果我使用maven 编译使用匿名类的类,然后我将类更改为使用lambdas 并再次使用maven 编译它,它不会报错。在这种情况下,如果我使用 mvn clean 然后使用 mvn compile,它只会再次报告错误。

有人可以帮我解决这个问题吗?或者尝试重现这个问题?

最佳答案

Although the error message is pretty clear about what is happening (the compiler thinks the final variable "panel" is being called before it is instantiated), the variable will not be called until the button generates an action, and how we can´t say when the action will happen, the code should compile.

您应该考虑这样一个事实,即编译器遵循正式规则并且不知道您的知识。特别是,编译器无法知道 addActionListener 方法不会立即调用 actionPerformed 方法。它也不知道决定何时调用 actionPerformed 的按钮的可见性。

正式行为has a specification .在那里你会发现以下几点:

Chapter 16. Definite Assignment

Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs.

An access to its value consists of the simple name of the variable (or, for a field, the simple name of the field qualified by this) occurring anywhere in an expression except as the left-hand operand of the simple assignment operator = (§15.26.1).

15.27.2. Lambda Body

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

在您的代码中,lambda 主体中名称的含义,即 panel 的读取,与作为构造函数的周围上下文中的名称含义相同。在这种情况下,适用“每个空白 final 字段在对其值进行任何访问时都必须有一个明确分配值”的规则。

是的,这与内部类定义不同。规范明确指出。

关于java - 在 Java 8 中使用 lambda 出现意外错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25787127/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com