オートボクシングで起きる NullPointerException
Integerはnullを持てますが、演算時にintへ開封されます。Map.getの戻り値の受け方を扱います。
エラーメッセージの読み方
Exception in thread "main" java.lang.NullPointerException
main- スレッド名 — mainなら起動直後の処理で発生しています
java.lang- パッケージ — java.lang なら標準の基本例外です
NullPointerException- 例外クラス — 何が起きたか。ここを検索するのが最短です
このエラーが出る典型パターン
パターン1
1 public class Main { 2 public static void main(String[] args) { 3 Integer n = null; ^ 4 System.out.println(n + 1); 5 } 6 }
Exception in thread "main" java.lang.NullPointerExceptionexited with code 1
Integerはnullを持てますが、演算時にintへ自動開封されます。nullの開封はNullPointerExceptionです。
直し方: Integer を Integer にします。
広告
広告スロット(未設定)
パターン2
1 import java.util.HashMap; 2 import java.util.Map; 3 4 public class Main { 5 public static void main(String[] args) { 6 Map<String, Integer> m = new HashMap<>(); 7 int v = m.get("missing"); ^ 8 System.out.println(v); 9 } 10 }
Exception in thread "main" java.lang.NullPointerExceptionexited with code 1
getはキーがなければnullを返します。intで受けると開封が走って落ちるため、Integerで受けるか既定値を使います。
直し方: int を Integer にします。
パターン3
1 import java.util.List; 2 3 public class Main { 4 public static void main(String[] args) { 5 List<Integer> list = List.of(10, 20, 30); 6 list.remove(Integer.valueOf(1)); ^ 7 System.out.println(list); 8 } 9 }
remove(1) は添字1の要素を消し、remove(Integer.valueOf(1)) は値1を探して消す(どちらもコンパイルは通ります)
Listのremoveはintとオブジェクトで意味が変わる数少ない例です。意図をキャストで明示します。
直し方: Integer.valueOf(1) を Integer.valueOf(1) にします。
よくある誤解
NullPointerExceptionなのにnullを書いた記憶がない場合、自動開封を疑ってください。ラッパー型がintに変換される瞬間に起きます。
まとめ
オートボクシングで起きる NullPointerExceptionは上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。