オートボックスはJavaのプリミティブ型(、)と(、)の自動変換です。便利ですが、微妙な落とし穴があります。パフォーマンスオーバーヘッド、驚くべきの動作、のリスクです。
intdoubleIntegerDouble==NullPointerExceptionInteger boxed = 42; // autoboxing: int → Integer (Integer.valueOf(42))
int unboxed = boxed; // auto-unboxing: Integer → int (boxed.intValue())
List<Integer> nums = new ArrayList<>();
nums.add(5); // autoboxes int 5 → Integer (collections need objects)
int x = nums.get(0); // auto-unboxes Integer → int
コレクションとジェネリクスはオブジェクトが必要なため(List<int>は使えません)、Javaはプリミティブ型を透過的にボックス化します。
==は参照を比較し、値ではないInteger a = 1000;
Integer b = 1000;
a == b; // ❌ FALSE — different Integer OBJECTS (reference comparison)
a.equals(b); // ✅ true — value comparison
// the WORSE trap — the Integer cache makes small values seem to work:
Integer c = 100, d = 100;
c == d; // TRUE — Java CACHES Integers from -128 to 127 (same object)
Integer e = 200, f = 200;
e == f; // FALSE — outside the cache range → different objects
これは危険です。Integerの==は小さい値(キャッシュされている)では動作しますが、大きい値では失敗します。テストでは正しく見えるコードが本番環境で壊れます。ラッパーの値の比較には常に.equals()を使用するか、またはプリミティブ型にアンボックスしてください。
Integer value = null; // a wrapper can be null
int x = value; // 💥 NullPointerException — unboxing null calls null.intValue()
Map<String, Integer> map = new HashMap<>();
int count = map.get("missing"); // 💥 NPE — get() returns null, then unboxing fails
nullラッパーをアンボックスするとNPEがスローされます。特にマップの検索がnullを返す場合など、一般的で驚くべきクラッシュです。
// ❌ autoboxing in a hot loop — creates millions of Integer objects (GC pressure, slow)
Long sum = 0L; // WRONG type — wrapper
for (long i = 0; i < 1_000_000; i++) {
sum += i; // unbox, add, re-box → new Long each iteration!
}
// ✅ use primitives in hot paths
long sum = 0L; // primitive — no boxing
繰り返されるボックス化/アンボックスは過剰なオブジェクトを作成し、タイトなループでパフォーマンスを悪化させます。
オートボックスは便利で広く使用されています(コレクション、ジェネリクスはすべてそれに依存しています)。しかし、その落とし穴は実際の、診断が難しいバグを引き起こします。
==トラップは特に危険です。Integerを==で比較するのはキャッシュされた小さい値(-128から127)では動作しますが、より大きい値では無音で失敗します。テストを通過しながら本番環境で壊れるバグです。そのため、ラッパーの比較には.equals()(またはアンボックス)が必須です。nullラッパーのアンボックスからのNullPointerException(マップの検索では一般的)はもう1つの頻繁なクラッシュです。
ホットループでのボックス化は不要なオブジェクトを作成し、パフォーマンスを悪化させます。
ボックス化がいつ発生するのか、値対参照の比較の問題、null アンボックスのリスク、パフォーマンスクリティカルなコードでプリミティブ型を使用することを理解することは、正しく、効率的なJavaを書くために重要です。そして、Integer キャッシュの==の動作は、深い理解を示す古典的なインタビュー質問です。