现在使用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之前的版本中显示完全相同的行为。

09-05 21:42
查看更多