163

@Nullableおよび@Nonnull注釈は sを防ぐのに役立つ可能性があることがわかりますNullPointerExceptionが、それらはあまり伝播しません。

  • これらのアノテーションの有効性は、1 レベルの間接化の後で完全に低下するため、いくつか追加しただけでは、遠くまで伝播しません。
  • これらの注釈は十分に実施されていないため、 でマークされた値が@Nonnullnull ではないと想定し、結果として null チェックを実行しない危険性があります。

以下のコードは、 でマークされたパラメーターを問題なく使用@Nonnullできるようにしますnull。実行時にa をスローしNullPointerExceptionます。

public class Clazz {
    public static void main(String[] args){
        Clazz clazz = new Clazz();

        // this line raises a complaint with the IDE (IntelliJ 11)
        clazz.directPathToA(null);

        // this line does not
        clazz.indirectPathToA(null); 
    }

    public void indirectPathToA(Integer y){
        directPathToA(y);
    }

    public void directPathToA(@Nonnull Integer x){
        x.toString(); // do stuff to x        
    }
}

これらの注釈をより厳密に適用したり、さらに伝播したりする方法はありますか?

4

9 に答える 9

77

簡単な答え:これらのアノテーションは、IDEがnullポインタエラーの可能性を警告する場合にのみ役立つと思います。

「クリーンコード」の本で述べられているように、パブリックメソッドのパラメータをチェックし、不変条件もチェックしないようにする必要があります。

もう1つの良いヒントは、null値を返すことはなく、代わりにNullObjectPatternを使用することです。

于 2012-11-21T01:34:42.220 に答える
38

null引数がnullでないことを期待するメソッドに渡すときにIDEがヒントを提供する以外に、さらに利点があります。

これにより、コードの保守性が向上し (チェックが不要になるためnull)、エラーが発生しにくくなります。

于 2012-11-21T08:57:28.723 に答える
13

コンプライアンス 1.8 で Eclipse の元の例をコンパイルし、注釈ベースの null 分析を有効にすると、次の警告が表示されます。

    directPathToA(y);
                  ^
Null type safety (type annotations): The expression of type 'Integer' needs unchecked conversion to conform to '@NonNull Integer'

この警告は、未加工の型を使用して生成されたコードとレガシー コードを混在させた場合 (「チェックされていない変換」) に発生する警告に類似して表現されています。ここでもまったく同じ状況があります。メソッドindirectPathToA()には、null コントラクトが指定されていないという点で「レガシー」署名があります。ツールはこれを簡単に報告できるため、null アノテーションを伝播する必要があるがまだ伝播されていないすべての路地を追跡します。

クレバー@NonNullByDefaultを使用する場合、毎回これを言う必要さえありません。

つまり、null 注釈が「非常に遠くまで伝播する」かどうかは、使用するツールと、ツールによって発行されるすべての警告にどれほど厳密に注意を払うかによって異なります。TYPE_USE null 注釈を使用すると、最終的に、プログラム内で発生する可能性のあるすべての NPEについてツールに警告させるオプションが得られます。これは、null 性が型システムの組み込みプロパティになったためです。

于 2015-09-18T22:06:11.820 に答える
8

私が自分のプロジェクトで行っていることは、「定数条件と例外」コード インスペクションで次のオプションを有効にすることです
検査

有効にすると、注釈が付けられていないすべてのパラメーターが null 以外として扱われるため、間接呼び出しに関する警告も表示されます。

clazz.indirectPathToA(null); 

さらに強力なチェックを行うには、Checker Framework が適している可能性があります (この素晴らしいチュートリアルを参照してください。
: まだ使用していないため、Jack コンパイラに問題がある可能性があります。このバグレポートを参照してください)。

于 2017-01-16T15:25:45.083 に答える
7

注釈が「あまり広まらない」ことに同意します。ただし、プログラマー側の間違いが見られます。

Nonnull注釈はドキュメントとして理解しています。次のメソッドは、(前提条件として) null 以外の引数が必要であることを表しますx

    public void directPathToA(@Nonnull Integer x){
        x.toString(); // do stuff to x        
    }

次のコード スニペットにはバグが含まれています。メソッドは、null 以外directPathToA()であることを強制せずに呼び出しyます (つまり、呼び出されたメソッドの前提条件は保証されません)。1 つの可能性は、 (前提条件の伝播)Nonnullに注釈を追加することです。可能性 2 は、 inの nullindirectPathToA()性をチェックし、when is nullの呼び出しを回避することです。yindirectPathToA()directPathToA()y

    public void indirectPathToA(Integer y){
        directPathToA(y);
    }
于 2015-09-01T06:33:24.563 に答える
3

Javaでは、Guavaのオプション型を使用します。実際の型であるため、コンパイラはその使用について保証します。それをバイパスして取得するのは簡単NullPointerExceptionですが、少なくともメソッドのシグニチャは、引数として期待するもの、または返す可能性のあるものを明確に伝えます。

于 2012-11-21T01:38:08.170 に答える