Spring Null-Safetyアノテーション

Spring Null-Safetyアノテーション

1. 概要

Spring 5から、より安全なコードを書くのに役立つ興味深い機能にアクセスできるようになりました。 この機能はnull-safetyと呼ばれ、潜在的なnull参照を監視するセーフガードのように機能する注釈のグループです。

安全でないコードを回避するのではなく、the null-safety feature produces warnings at compile time.このような警告は、実行時に壊滅的なnullポインター例外(NPE)を防ぐ可能性があります。

2. @NonNull注釈

@NonNullアノテーションは、null-safety機能のすべてのアノテーションの中で最も重要です。 We can use this annotation t0 declare non-null constraint anywhere an object reference is expected:は、フィールド、メソッドパラメータ、またはメソッドの戻り値です。

Personという名前のクラスがあるとします。

public class Person {
    private String fullName;

    void setFullName(String fullName) {
        if (fullName != null && fullName.isEmpty()) {
            fullName = null;
        }
        this.fullName = fullName;
    }

    // getter
}

このクラス定義は有効ですが、欠陥があります。fullNameフィールドがnullに設定されている可能性があります。 これが発生した場合、fullNameを操作するときにNPEが発生する可能性があります。

Springのnull安全機能により、ツールはこのような危険を報告できます。 たとえば、IntelliJ IDEAでコードを記述し、fullNameフィールドを@NonNullアノテーションで装飾すると、次の警告が表示されます。

image

この表示のおかげで、問題を事前に認識し、実行時の障害を回避するために適切なアクションを実行できます。

3. @NonNullFields注釈

@NonNullアノテーションは、nullの安全性を保証するのに役立ちます。 ただし、この注釈ですべての非nullフィールドを装飾すると、コードベース全体が汚染されます。

別のアノテーション–@NonNullFields@NonNullの乱用を回避できます。 This annotation is applicable at the package level, notifying our development tools that all fields in the annotated package are, by default, non-null.

@NonNullFieldsアノテーションを開始するには、パッケージのルートディレクトリにpackage-info.javaという名前のファイルを作成し、パッケージに@NonNullFieldsアノテーションを付ける必要があります。

@NonNullFields
package org.example.nullibility;

nickNameと呼ばれるPersonクラスの別のプロパティを宣言しましょう。

package org.example.nullibility;

// import statements

public class Person {
    private String nickName;

    void setNickName(@Nullable String nickName) {
        if (nickName != null && nickName.isEmpty()) {
            nickName = null;
        }
        this.nickName = nickName;
    }

    // other declarations
}

今回は、nickNameフィールドを@NonNullで装飾しませんが、同様の警告が表示されます。

image

@NonNullFieldsアノテーションは、@NonNullが提供するのと同じレベルの安全性を確保しながら、コードの冗長性を減らします。

4. @Nullable注釈

@NonNullFieldsアノテーションは、定型文を減らすのに役立つため、一般的に@NonNullよりも推奨されます。 パッケージレベルで指定されたnull以外の制約から一部のフィールドを除外したい場合があります。

nickNameフィールドに戻り、@Nullableアノテーションで装飾してみましょう。

@Nullable
private String nickName;

以前見た警告は消えました。

image

この状況では、we used the @Nullable annotation to override the semantics of @NonNullFields on a field.

5. @NonNullApiアノテーション

@NonNullFieldsアノテーションは、その名前が示すように、フィールドにのみ適用されます。 If we want to have the same impact on the methods' parameters and return values, we’ll need @NonNullApi.

@NonNullFieldsと同様に、package-info.javaファイルで@NonNullApiアノテーションを指定する必要があります。

@NonNullApi
package org.example.nullibility;

nickNameフィールドのゲッターを定義しましょう。

package org.example.nullibility;

// import statements

public class Person {
    @Nullable
    private String nickName;

    String getNickName() {
        return nickName;
    }

    // other declarations
}

@NonNullApiアノテーションが有効な場合、getNickNameメソッドによって生成される可能性のあるnull値について警告が発行されます。

image

@NonNullFieldsアノテーションと同様に、メソッドレベルで@NonNullApi@Nullableアノテーションでオーバーライドできることに注意してください。

6. 結論

Spring null-safetyは、NPEの可能性を減らすのに役立つ優れた機能です。 ただし、この機能を使用する際に注意する必要がある2つの重要なポイントがあります。

  • IntelliJIDEAなどのサポート開発ツールでのみ使用できます

  • 実行時にnullチェックを強制しません。それでも、NPEを回避するために自分でコードを作成する必要があります。

このチュートリアルのソースコードは、over on GitHubにあります。