LoginSignup
1
0

More than 3 years have passed since last update.

n == 0がNullPointerExceptionをスローする。

Last updated at Posted at 2019-11-11

問題

突然ですが、次のコードはNullPointerExceptionになる可能性があります。どのような場合でしょうか?

boolean iszero = n == 0;

答え

答えは、変数nの型がIntegerで、値がnullの場合にNullPointerExceptionが発生します。たとえば以下のようなMain.javaがあるとします。

Main.java
public class Main {
    public static void main(String[] args) throws Exception {
        Integer n = null;
        boolean iszero = n == 0;
    }
}

これをコンパイルし、実行すると、確かにNullPointerExceptionが発生することが確認できます。

$ javac Main.java
$ java Main
Exception in thread "main" java.lang.NullPointerException
    at Main.main(Main.java:4)

解説

Java Language Specification の 4.2.2. Integer Operations には次の通りに記述されています。

Any integer operator can throw a NullPointerException if unboxing conversion (§5.1.8) of a null reference is required.

要するにJava言語の仕様というわけで、Javaプログラマは粛々と従うほかないわけですが、それではさみしいので、一応自分なりの解釈を述べておくと -- 上記のコードの右辺はリテラルで宣言された0、すなわちint型です。そのため左辺はunboxingされ、Integerからintにキャストされます。ですが左辺nnullint型はnullを許容しないので、NullPointerExceptionになるわけです。 (2019/11/11 コメントをもとに修正)

愚痴

  • こういう場合は「nullによるUnboxingの失敗」を示す専用例外を投げてほしいという気持ちもあったりなかったり。NullPointerExceptionだと「キャストに失敗した」という成分がすっぽり抜けてしまうので(´・ω・`) (2019/11/11 コメントをもとに修正)
  • Javaプログラマの間ではこの性質はよく知られており、自分も知っていたのですが、それに気づかず、1時間近くを溶かしたというのが、この記事を書いたきっかけになります……。言い訳すると、上記のサンプルコード程度であればすぐ気がついたと思うのですが、実際は以下のようなコードでした。これじゃわかるもんもわからん(´・ω・`)
List<Integer> digits = new ArrayList<>();

//
// すごいスパゲッティコード
//

digits.add(null); // ここでまぎれこんだ

//
// すごいスパゲッティコード
//

for (int i = 0; i < digits.size(); i++) {

    //
    // すごいスパゲッティコード
    // 

    if (digits.get(i) == 0) { // ここでNullPointerException

        //
        // すごいスパゲッティコード
        // 

    }

    //
    // すごいスパゲッティコード
    // 

}
1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0