我只是做了一个小代码更改来沉默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中编译。
答案 0 :(得分:14)
这没关系。它被称为空白最终
引自wiki:
最终变量只能通过一次初始化一次 初始化程序或赋值语句。它不需要初始化 声明点:这被称为"空白决赛"变量。一个 必须明确赋值类的空白最终实例变量 在声明它的类的每个构造函数的末尾; 同样,必须明确指定空白的最终静态变量 在声明它的类的静态初始值设定项中: 否则,在两种情况下都会发生编译时错误。 [4](注:如果 变量是一个引用,这意味着变量不能 重新绑定引用另一个对象。但它的对象 如果引用最初是可变的,那么引用仍然是可变的。)
空白最终
在Java 1.1中引入的空白final是一个最终变量 其声明缺少初始化程序。 [5] [6]空白决赛只能 分配一次,并且在分配发生时必须取消分配。在 为了做到这一点,Java编译器运行流分析以确保, 对于空白最终变量的每个赋值,变量是 在任务之前绝对未分配;否则编译时 发生错误。[7]
通常,Java编译器将确保空白final不是 使用,直到它被分配一个值,并且一旦分配了值, 现在最终变量不能重新分配另一个值。[8]
答案 1 :(得分:8)
自Java 1.1以来,这是允许并且工作正常,并且不会让您遇到其他编译器或IDE的麻烦。
它是Java中的标准行为,并且首先在Java Language Specification 2nd Edition中正式指定。
答案 2 :(得分:1)
Java语言规范包含专门针对此行为的整章(Chapter 16 Definite Assignment)。
这种行为是彻底定义的,所以当你说在以前的版本中曾经产生错误时,我认为你误解了一些东西。
答案 3 :(得分:0)
没关系。变量没有值,只分配一次。如果你最初给它一个null
值,它将会失败。
答案 4 :(得分:0)
我强烈建议改用此代码:
final File[] libPath = ibraryPath == null ? new File[0] : pathToFiles(libraryPath);
这不依赖于任何编译器版本,但是100%支持具有明确含义的Java。
答案 5 :(得分:0)
是的,这将起作用,并且在我见过的所有java版本中都可以安全使用(1.3 +)。
final 意味着一旦初始化对象就无法更改对象的值,如果在声明它已经破坏时放置了null。