14

フォローアップ コードで、以前は知らなかった動作に遭遇しました。

最初のケースを考えてみましょう:

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

予想通り、コンパイラはnullstrであることに関する次の警告を表示します- Null ポインター アクセス:変数 str は、この場所でのみ null にすることができます。

ここで、その変数を移動すると、nullに初期化されたstatic final フィールド:

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後で結果をもたらします。

ただし、コンパイラは最初のケースでこれを正常に警告しますが、2番目のケースでこれを識別できないのはなぜですか。この行動の変化はなぜですか?staticフィールドをinstanceフィールドに変更し、のインスタンスを使用してアクセスする場合、動作は同じですDemo

この動作は JLS で指定されている可能性があると考えたので、Definite Assignmentのトピックを調べましたが、この問題に関連するものは見つかりませんでした。行動の変化を説明できる人はいますか?可能であれば、JLSへのリンクを備えた強みを探していますか?

それとは別に、コンパイラが最初に警告のみを表示するのはなぜですか。上記と同じ理由で、フィールドを変更できないため、メソッド呼び出しは実行時にNPEを確実にスローしますか? コンパイラエラーが表示されなかったのはなぜですか? のランタイム結果str.length()NPE.


以前のことを逃して申し訳ありません:

OpenJDK 7を搭載したUbuntu 12.04Eclipse Junoを使用しています。

4

3 に答える 3

2

わお!それはEclipse固有の問題であることが判明しました。次を使用してコードをコンパイルしたとき:

javac -Xlint:all Demo.java

どのような場合でも警告は表示されませんでした。そこで、Eclipse に戻って、このケースで有効になっている設定を確認し、見つけました。

Windows -> Preferences -> Java -> Compiler -> Errors/WarningsNull Analysisで、Eclipse Compiler がNull Pointer Accessを処理する方法を変更できます。IgnoreError、またはWarningに設定できます。

そして今、それは完全にばかげた質問のように思えます。私を恥じてください。:(

于 2013-08-02T16:27:04.970 に答える
2

私は100%確信が持てませんが、ローカル変数に対して最終フィールドがある2番目のケースでは、この最終フィールドに静的(または変数が静的かどうかに応じてインスタンスブロック)初期化ブロックに直接値を割り当てる可能性があります。

class Demo {
...
static {
 str = "some text";
}
...
}

そのため、コンパイラは警告しません。

于 2013-08-02T13:25:49.320 に答える