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

argius note

プログラミング関連

開発しています



NullPointerExceptionを見たらバグと思え

Java

どこかで散々議論された話かも知れませんが。
そもそも、"String==null"の状態は、バグの一種だと思います。
JDBCで、ResultSet.getString(int)の結果がnullの場合などの例外はあるとしても、nullの場合は文字列としての機能を果たさないわけだから、誰かが責任を持ってnullの状態を排除すべきと考えます。
内部ルールとして、Stringのnullに明確な意味づけをすればまだ良いですが、それが無ければ、「なんとなくnull」の状態ができてしまいます。
Stringのnull初期化はもってのほかで、

String s;
if (args.length > 0) {
    s = args[0];
}
System.out.println(s);

はコンパイルエラーになりますが、これを

String s = null; // nullで初期化
if (args.length > 0) {
    s = args[0];
}
System.out.println(s);

こうやって回避するのは、コンパイルエラーの意味を完全に無視してしまっています。初期化しないsを最後の行まで到達しないようにすれば良いので、

String s;
if (args.length > 0) {
    s = args[0];
} else {
    throw new IllegalArgumentException("args.length=" + args.length);
    // または、return
}
System.out.println(s);

のようにすべきです。
フィールドの場合は、初期値はnullになっているので、

class Person {
    private String name;
    public Person() {
        this("");
    }
    public Person(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

のように、どのコンストラクタが呼ばれてもnullでない状態になるようにすれば良いのです。

これは、String以外のオブジェクトについても言えることだと思います。

追記:フィールドをfinalにすれば、初期化忘れと再代入をコンパイラでチェックできます。

class Person {
    private final String name;
    public Person() {
        // 初期化忘れ でエラー
    }
    public void setName(String name) {
        this.name = name; // 再代入 でエラー
    }
}