现在使用java-8,我将一些显式声明转换为lambda表达式,并遇到了编译器错误。因此,请怀疑它是当前Java-8发行版(b105)的“错误”。
该示例代码定义了两个Function对象,分别使用和不使用lambda表达式。两者都基于这些功能使用的谓词。尽管传统实现有效,但lambda版本报告错误:
java:变量fileExists可能尚未初始化
这不是完全错误,但是如果使用Function而不创建函数本身(因为显式版本运行良好),则谓词是相关的。
我应该报告错误(有人链接了吗?)还是错过了什么?
public class FileOpener {
public FileOpener(Predicate<File> fileExists) {
this.fileExists = fileExists;
}
final Predicate<File> fileExists;
final Function<File, FileInputStream> openLambda = file -> {
try {
return fileExists.test(file) ? new FileInputStream(file) : null;
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
};
// this version compiles
final Function<File, FileInputStream> openFunction = new Function<File, FileInputStream>() {
@Override
public FileInputStream apply(File file) {
try {
return fileExists.test(file) ? new FileInputStream(file) : null;
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
};
}
最佳答案
错误消息是正确的,正如Edwin Dalorzo指出的那样。初始化顺序在这里很重要。首先,字段初始化程序按照在源文件中出现的顺序执行,然后按构造函数执行。 Lambda引用变量捕获变量,在最终变量(和所有局部变量)的情况下,它们捕获变量的实际值,这需要初始化变量。这符合Java语言规范并且在Java 8中未更改:
class SimpleTest
{
SimpleTest()
{
first="a string";
}
final String first;
String second=first;
}
在Java 8之前的版本中显示完全相同的行为。