行为差异:'null'初始化最终静态成员,'null'初始化最终局部变量
我在后续代码中遇到了一个我之前不知道的行为。
考虑第一种情况:
public static void main(String[] args) {
final String str = null;
System.out.println(str.length()); // Compiler Warning: NullPointerAccess
}
正如预期的那样,编译器在为 null 时向我显示以下警告 - Null 指针访问:变量 str 在此位置只能为 null。str
现在,当我移动该变量时,静态最终字段初始化为 null:
class Demo {
static final String str = null;
public static void main(String[] args) {
System.out.println(str.length()); // No Compiler Warning
}
}
现在,编译器不显示任何警告。AFAIK,编译器应该知道,作为最终的,不会改变其值,在代码的任何时候。鉴于它是 ,肯定会在以后导致,它确实如此。str
null
NullPointerException
虽然编译器在第一种情况下成功地警告了我这一点,但为什么它在第二种情况下无法识别这一点。为什么会发生这种行为改变?如果我将字段更改为字段,并使用 的实例访问它,则行为是相同的。static
instance
Demo
我认为此行为可能已在 JLS 中指定,因此我浏览了主题“确定分配”,但没有找到与此问题相关的任何内容。谁能解释一下行为的变化?如果可能的话,我正在寻找一些与JLS链接的强项?
除此之外,为什么编译器首先只向我显示警告,因为我认为出于我上面提到的相同原因,方法调用肯定会在运行时抛出NPE,因为字段无法更改?为什么它没有向我显示编译器错误?我是否对编译器期望过高,因为似乎很明显,运行时结果不能是任何东西?str.length()
NPE
很抱歉之前错过了:
我正在使用Eclipse Juno,在Ubuntu 12.04和OpenJDK 7上。