【发布时间】:2015-05-20 21:35:55
【问题描述】:
我最近遇到了错误消息“空白的最终字段 obj 可能尚未初始化”。
如果您尝试引用可能尚未分配值的字段,通常会出现这种情况。示例类:
public class Foo {
private final Object obj;
public Foo() {
obj.toString(); // error (1)
obj = new Object();
obj.toString(); // just fine (2)
}
}
我使用 Eclipse。在(1) 行中我收到错误,在(2) 行中一切正常。 到目前为止,这是有道理的。
接下来我尝试在构造函数中创建的匿名接口中访问obj。
public class Foo {
private Object obj;
public Foo() {
Runnable run = new Runnable() {
public void run() {
obj.toString(); // works fine
}
};
obj = new Object();
obj.toString(); // works too
}
}
这也有效,因为我在创建界面的那一刻没有访问obj。我也可以将我的实例传递到其他地方,然后初始化对象obj,然后运行我的界面。 (但是在使用之前检查null 是合适的)。 还是有道理的。
但现在我使用 lambda 表达式将Runnable 实例的创建时间缩短为汉堡箭头版本:
public class Foo {
private final Object obj;
public Foo() {
Runnable run = () -> {
obj.toString(); // error
};
obj = new Object();
obj.toString(); // works again
}
}
这是我无法再关注的地方。在这里,我再次收到警告。我知道编译器不会像通常的初始化那样处理 lambda 表达式,它不会“用长版本替换它”。但是,为什么这会影响我在创建Runnable 对象时不运行run() 方法中的代码部分?我仍然能够在调用run() 之前进行初始化。所以从技术上讲,这里可能不会遇到NullPointerException。 (虽然最好也在这里检查null。但这个约定是另一个话题。)
我犯了什么错误? lambda 的处理方式有何不同,以至于它会影响我的对象使用方式?
感谢您提供任何进一步的解释。
【问题讨论】:
-
最终版本有什么警告/错误?您使用的是什么版本的 Java?
-
@SotiriosDelimanolis 我得到了标题中提到的确切错误。而且我使用 Java 8。我想否则我什至无法使用 lambda,对吧?
-
对不起,我指的是编译器版本。它是 java 8,但是是哪个发行版本。
标签: java constructor lambda compiler-construction java-8