我在后续代码中遇到了一个我之前不知道的行为。
考虑第一个st案例:
public static void main(String[] args) {
final String str = null;
System.out.println(str.length()); // Compiler Warning: NullPointerAccess
}
正如预期的那样,编译器在 str
为 null 时向我显示以下警告 - Null pointer access: The variable str can only be null at这个位置。
现在,当我移动该变量时,static final 字段 初始化为 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
?
很抱歉之前错过了:
我在 Ubuntu 12.04 和 OpenJDK 7 上使用 Eclipse Juno。
最佳答案
我不确定 100%,但在第二种情况下,你有针对局部变量的 final 字段,有可能直接在静态中为这个 final 字段分配一些值(或实例 block ,取决于变量是否是静态的)初始化 block :
class Demo {
...
static {
str = "some text";
}
...
}
所以编译器不会给你警告。
关于java - 行为差异 : 'null' initialized final static member, 和 'null' 初始化最终局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18017786/