読者です 読者をやめる 読者になる 読者になる

覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。 twitter: @yyoshikaw

Lombok - @NonNull

Lombokの@NonNull(lombok.NonNull)アノテーションの利用サンプルです。

@NonNullアノテーションをクラスのメンバやメソッドの引数に付与することでnullチェックが自動で挿入されます。
@NonNullが付与されたメンバや引数にnullを渡そうとするとNullPointerExceptionがスローされます。


@Value + @NonNull

@Valueアノテーションを付与したクラスのメンバに@NonNullを付与してみます。
こうすることで、インスタンスを生成する際にコンストラクタの引数にnullを渡すことはできなくなります。

■@NonNullを付与したクラス

import lombok.NonNull;
import lombok.Value;

@Value
public class Person1 {

    private long id;

    @NonNull
    private String name;

    @NonNull
    private String[] notes;
}

■利用側のコード

package sample.nonnull;

public final class Person1Client {

    public static void main(String[] args) {
        long id = 50;
        String name = "Lombok Kentaro";
        String[] notes = new String[] { "note1", "note2", "note3"};

        Person1 p1 = new Person1(id, name, notes);

        System.out.println("Person1#toString: " + p1);

        System.out.println("-----------------");

        // nullをコンストラクタに渡すとNullPointerExceptionがスローされる
        try {
            Person1 p2 = new Person1(id, null, notes);
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

        try {
            Person1 p3 = new Person1(id, name, null);
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }
}

■実行結果

@NonNullを付与したメンバに対応する引数にnullを渡すとNullPointerExceptionがスローされます

Person1#toString: Person1(id=50, name=Lombok Kentaro, notes=[note1, note2, note3])
-----------------
java.lang.NullPointerException: name
    at sample.nonnull.Person1.<init>(Person1.java:6)
    at sample.nonnull.Person1Client.main(Person1Client.java:18)
java.lang.NullPointerException: notes
    at sample.nonnull.Person1.<init>(Person1.java:6)
    at sample.nonnull.Person1Client.main(Person1Client.java:24)


setterの引数に@NonNull

setterの引数に@NonNullアノテーションを付与してnullチェックが行われることを確認します

■@NonNullを付与したクラス

import java.util.List;

import lombok.Data;
import lombok.NonNull;

@Data
public class Person2 {

    private long id;

    private String name;

    private String[] notes;

    public void setName(@NonNull String name) {
        this.name = name;
    }

    public void setNotes(@NonNull String[] notes) {
        this.notes = notes;
    }
}

■利用側のコード

public final class Person2Client {

    public static void main(String[] args) {
        long id = 50;
        String name = "Lombok Kentaro";

        Person2 p1 = new Person2();

        p1.setId(id);
        p1.setName(name);
        p1.setNotes(new String[] {"note1", "note2", "note3" });

        System.out.println("Person2#toString: " + p1);

        System.out.println("-----------------");

        Person2 p2 = new Person2();

        // setterでnullを渡すとNullPointerExceptionがスローされる
        try {
            p2.setName(null);
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        try {
            p2.setNotes(null);
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

        System.out.println("-----------------");

        // setterにだけ@NonNullが付いている場合は、メンバがnullになっている可能性はある
        // そのためメンバに値未設定ならgetterはnullを返す。
        System.out.println("Person2.getName(): " + p2.getName());
        System.out.println("Person2.getNotes(): " + p2.getNotes());
    }
}

■実行結果

Person2#toString: Person2(id=50, name=Lombok Kentaro, notes=[note1, note2, note3])
-----------------
java.lang.NullPointerException: name
    at sample.nonnull.Person2.setName(Person2.java:14)
    at sample.nonnull.Person2Client.main(Person2Client.java:23)
java.lang.NullPointerException: notes
    at sample.nonnull.Person2.setNotes(Person2.java:18)
    at sample.nonnull.Person2Client.main(Person2Client.java:28)
-----------------
Person2.getName(): null
Person2.getNotes(): nul

上に書いていますが、本例のような場合は、デフォルトコンストラクタを呼び出したタイミングではメンバはnullになっています。
そのためインスタンス生成直後にgetterをそのタイミングで呼び出すと戻り値はnullになっています。


コンストラクタの引数に@NonNull

コンストラクタの引数に@NonNullアノテーションを付与してnullチェックが行われることを確認します

■@NonNullを付与したクラス

import lombok.Data;
import lombok.NonNull;

@Data
public class Person3 {

    private final long id;

    private final String name;

    private String[] notes;

    public Person3(long id, @NonNull String name) {
        this.id = id;
        this.name = name;
    }
}

■利用側のコード

public final class Person3Client {

    public static void main(String[] args) {
        long id = 50;
        String name = "Lombok Kentaro";

        Person3 p1 = new Person3(id, name);

        p1.setNotes(new String[] {"note1", "note2", "note3"});

        System.out.println("Person3#toString: " + p1);

        System.out.println("-----------------");


        // コンストラクタでnullを渡すとNullPointerExceptionがスローされる
        try {
            Person3 p2 = new Person3(id, null);
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }
}

■実行結果

Person3#toString: Person3(id=50, name=Lombok Kentaro, notes=[note1, note2, note3])
-----------------
java.lang.NullPointerException: name
    at sample.nonnull.Person3.<init>(Person3.java:14)
    at sample.nonnull.Person3Client.main(Person3Client.java:20)



関連エントリ