Java “空白的最终字段可能尚未初始化” 匿名接口 vs Lambda 表达式
我最近遇到了错误消息“空白的最终字段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
实例的创建缩短为 burger-arrow 版本:
public class Foo {
private final Object obj;
public Foo() {
Runnable run = () -> {
obj.toString(); // error
};
obj = new Object();
obj.toString(); // works again
}
}
这就是我不能再跟随的地方。在这里,我再次收到警告。我知道编译器不会像通常的初始化那样处理lambda表达式,它不会“用长版本替换它”。但是,为什么这会影响我在创建对象时不在我的方法中运行代码部分的事实?我仍然能够在调用之前进行初始化。所以从技术上讲,在这里有可能不遇到。(虽然最好也在这里检查一下。但这个约定是另一个主题。run()
Runnable
run()
NullPointerException
null
我犯了什么错误?lambda 的处理方式如此不同,以至于它影响了我的对象使用方式?
我感谢你所作的进一步解释。