NullPointerException の原因と直し方
nullに対する操作で発生します。発生箇所の特定方法と、そもそもnullを持ち回さない設計を扱います。
エラーメッセージの読み方
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 String s = null; ^ 4 System.out.println(s.length()); 5 } 6 }
Exception in thread "main" java.lang.NullPointerException:
Cannot invoke "String.length()" because "s" is nullexited with code 1
nullは実体がない状態です。空文字""は長さ0のStringという実体なので、メソッドを呼べます。
直し方: null を "" にします。
広告
広告スロット(未設定)
パターン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("x") ; ^ 8 System.out.println(v); 9 } 10 }
Exception in thread "main" java.lang.NullPointerExceptionexited with code 1
存在しないキーのgetはnullを返します。intへの代入時に自動開封が起きてNullPointerExceptionになります。
直し方: get("x") を getOrDefault("x", 0) にします。
パターン3
1 public class Main { 2 static String find(int n) { 3 if (n > 0) return "found"; 4 return null; ^ 5 } 6 public static void main(String[] args) { 7 System.out.println(find(-1).length()); 8 } 9 }
Exception in thread "main" java.lang.NullPointerExceptionexited with code 1
nullを返すメソッドは呼び出し側にnullチェックを強制します。空の値を返すほうが安全です。
直し方: null を "" にします。
よくある誤解
nullを代入した行では落ちません。使った行で落ちます。スタックトレースの先頭が示すのは「使った場所」です。
まとめ
NullPointerExceptionは中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。