将局部变量声明为 final,而不带初始值设定项,并在 if 语句中赋值

2022-09-04 01:23:53

我刚刚做了一个小的代码更改,以沉默FindBugs警告,这需要将一些代码移动到匿名的内部类。为了访问某些变量,我必须将它们声明为 .所以这是更改后的代码片段:final

final File[] libPath; // libPath is final but assignment takes place later
if (libraryPath != null) {
    libPath = pathToFiles(libraryPath);
} else {
    libPath = new File[0];
}

这在当前 Eclipse(版本 3.7.1)中设置为 Java 6 的语言下编译得很好。但是,我很确定这在以前的版本中曾经给出错误。似乎编译器在可以确定将存在此构造时接受此构造。

我的问题是:这在Java 6中是合法的,还是由于Java 7支持的副作用被添加到eclipse 3.7.1中而起作用?我们已经在3.7.1中工作但在3.7.0中编译的泛型的某些用法中看到了这种副作用。


答案 1

这没关系。它被称为空白最终

引用自维基:

最终变量只能通过初始值设定项或赋值语句初始化一次。它不需要在声明时初始化:这被称为“空白最终”变量。类的空白最终实例变量必须在声明它的类的每个构造函数的末尾明确赋值;类似地,必须在声明它的类的静态初始值设定项中明确分配空白的最终静态变量:否则,在这两种情况下都会发生编译时错误。[4] (注意:如果变量是引用,这意味着该变量不能被重新绑定以引用另一个对象。但是它引用的对象仍然是可变的,如果它最初是可变的。

空白决赛

在 Java 1.1 中引入的空白 final 是一个最终变量,其声明缺少初始值设定项。[5][6] 空白决赛只能分配一次,并且在分配发生时必须取消分配。为此,Java编译器运行流分析,以确保对于每个赋值到空白最终变量的赋值,该变量在赋值之前肯定是未赋值的;否则会发生编译时错误。[7]

通常,Java 编译器将确保在为空白 final 赋值之前不会使用它,并且一旦赋值,现在的最后一个变量就不能被重新赋值。[8]

链接: http://en.wikipedia.org/wiki/Final_%28Java%29


答案 2

这是允许的,并且自Java 1.1以来工作正常,并且不会给您带来其他编译器或IDE的麻烦。

它是Java中的标准行为,并首先在Java语言规范第2版中正式指定。