行为差异:'null'初始化最终静态成员,'null'初始化最终局部变量

Roh*_*ain 14 java final local-variables static-members compiler-warnings

在后续代码中,我遇到了一个我以前不知道的行为.

考虑一种情况:

public static void main(String[] args) {    
    final String str = null;
    System.out.println(str.length());  // Compiler Warning: NullPointerAccess
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,编译器显示我对下面的警告str - 空指针访问:变量str只能是空在这个位置.

现在,当我将该变量移动一个初始化为null静态final字段时:

class Demo {
    static final String str = null;

    public static void main(String[] args) {
        System.out.println(str.length());  // No Compiler Warning
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,编译器没有显示任何警告.AFAIK,编译器应该知道,str在代码的任何一点,它都是最终的,不会改变它的值.鉴于它确实如此null,肯定会在NullPointerException以后产生,它确实会产生.

虽然编译器在第一种情况下成功警告我,为什么它在第二种情况下无法识别.为什么这种行为改变?行为是相同的,如果我将static字段更改为instance字段,并使用实例访问它Demo.

我认为这种行为可能已在JLS中指定,因此我浏览了主题定义分配,但没有找到与此问题相关的任何内容.任何人都可以解释行为的变化吗?如果可能的话,我正在寻找一些与JLS有关的强点吗?

除此之外,为什么编译器首先只向我显示警告,因为我认为出于与上述相同的原因,方法调用肯定会在运行时抛出NPE,因为字段无法更改?为什么不向我显示编译器错误?我是否期望编译器太多,因为它似乎很明显,运行时结果str.length()不能超过NPE


很抱歉错过了之前:

我正在使用Eclipse Juno,在Ubuntu 12.04上使用OpenJDK 7.

Roh*_*ain 2

哇!事实证明,这是 eclipse 特定的问题。当我使用以下方式编译代码时:

javac -Xlint:all Demo.java
Run Code Online (Sandbox Code Playgroud)

在任何情况下它都没有显示任何警告。因此,我返回 eclipse 检查针对这种情况启用的任何设置,并找到了一个。

Windows -> Preferences -> Java -> Compiler -> Errors/Warnings中,在Null Analysis下,我可以更改Eclipse Compiler 处理空指针访问的方式。我可以将其设置为 -忽略错误警告

现在看来这是一个完全愚蠢的问题。我真丢脸。:(