はじめに
未経験からエンジニアになり、実務でコードに触れていく中で「基本的なエラーなのに理解があいまいだった」と感じることが何度もありました。
今回紹介するのは、その中でも特にハマりやすい NullPointerException(null参照例外) の一例です。
一度理解したつもりでも、時間が経つと忘れてしまうことがあります。
同じように悩む方のために、できるだけシンプルに整理しました。
🌱 起きていたエラー
NullPointerException
調査すると、
obj.getCode() が null のまま数値変換されている
という状態でした。
背景(DBの状態)
今回のデータ取得は、AテーブルとBテーブルを組み合わせたものでした。
- Aテーブルの値とBテーブルの値に対応関係がある前提
- しかし実際には対応するデータが存在しないケースがあった
その結果:👉 Bテーブル側の値(code)が null で取得される
問題のコード
Integer.toString(obj.getCode())
なぜ落ちるのか?
getCode() の戻り値は Integer 型(オブジェクト)です。
Integer value = obj.getCode();
この value が null のとき、
Integer.toString(value);
を実行すると、Javaの内部ではこうなります:👉 int型に変換(アンボクシング)しようとする
⚠️ アンボクシングとは
Integer i = 10; int x = i; // 自動変換
このように、Integer → int に変換される仕組みです。
※ただし内部的にはi.intValue()が呼ばれています。
ここが重要
Integer i = null;
int x = i; // ← ここで例外
👉 null に対して intValue() が呼ばれるため
👉 NullPointerException が発生
なぜ文字列変換なのに落ちるのか?
Integer.toString(obj.getCode())
この処理は
- Integer を受け取る
- 内部で int に変換する
- 文字列にする
という流れです。
👉 変換の途中(int化)で落ちている
✅ 対策方法
① nullチェックする(基本)
Integer code = obj.getCode();
if (code != null) {
String str = Integer.toString(code);
}
② Optionalを使う(少しモダン)
String str = Optional.ofNullable(obj.getCode())
.map(String::valueOf)
.orElse("");
③ デフォルト値を決める
int code = obj.getCode() != null ? obj.getCode() : 0;
ポイントまとめ
- Integer / Long は nullになり得るオブジェクト
- primitive型(int / long)に変換する時にアンボクシングが発生
- nullのまま変換すると
intValue()/longValue()が呼ばれて落ちる - 文字列変換でも内部で数値変換が走る
- DBのnullは必ず疑う
さいごに
今回のようなエラーは、「知っているかどうか」で対応スピードが大きく変わります。
特に
- DBのデータ不整合
- 想定外のnull
- ラッパークラスとプリミティブ型の違い
が組み合わさり、エラーの原因が見えづらくなります。
エラーをただ直すだけでなく、
「なぜこのタイミングで落ちたのか」
まで理解できると、同じミスを防げるようになります。
今回の内容が一助となれば幸いです。