ラッパークラスとは何かをざっくりつかむ
Java の「ラッパークラス」は、int や double のような プリミティブ型(基本型)を “オブジェクトとして包んだクラス” です。
対応はこうなっています。
boolean→Booleanbyte→Byteshort→Shortint→Integerlong→Longfloat→Floatdouble→Doublechar→Character
名前の通り「包んでいる(wrap)」のでラッパークラス。
「値そのもの(基本型)」と「オブジェクトとしての箱(ラッパークラス)」がペアになっているイメージです。
そもそも、なぜラッパークラスが必要なのか(目的)
コレクションやジェネリクスは「オブジェクトしか扱えない」
Java のコレクション(List, Map など)やジェネリクスは、基本型を直接扱えません。
例えば、これはコンパイルエラーです。
List<int> list; // ダメ
Java正しくはラッパークラスを使います。
List<Integer> list; // OK
list = new ArrayList<>();
list.add(10); // 実は「10」が Integer に自動変換されている(後述)
JavaList の中には「オブジェクト」しか入れられないので、
基本型の値を オブジェクトに変換して入れるための箱 が必要になる。
それがラッパークラスの一番分かりやすい役割です。
「null を入れたい」場面で必要になる
基本型には null を入れられません。
int x = null; // コンパイルエラー
Javaですが、「値がない」という状態を表したいときに、null を使いたくなることがあります。
Integer x = null; // これは OK(ラッパークラス)
Java例えば「まだ設定されていない」「DB から値が来ていない」など、
「0 とは違う“未設定”」を表したいときに、ラッパークラスの null が役立ちます。
- 基本型…常に何かしらの値(
intなら 0 など)が入る - ラッパークラス…「値あり」か「null(値なし)」の2状態を持てる
この「null を持てるかどうか」の違いも重要です。
オートボクシング / アンボクシング:自動で変換される仕組み(重要)
自分で new しなくても勝手に変換される
昔の Java では、基本型とラッパークラスを自分で変換していました。
int x = 10;
Integer obj = Integer.valueOf(x); // 包む(ボクシング)
int y = obj.intValue(); // 取り出す(アンボクシング)
Java今(Java 5 以降)は、コンパイラが自動でやってくれます。
これを オートボクシング / アンボクシング と呼びます。
int x = 10;
Integer obj = x; // 自動で Integer.valueOf(x) してくれる
int y = obj; // 自動で obj.intValue() してくれる
Java見た目は代入しているだけですが、
裏では「オブジェクトへの変換」「中身の取り出し」が行われています。
コレクションに入れるときも自動でラップされる
List<Integer> list = new ArrayList<>();
list.add(10); // int → Integer に自動変換(オートボクシング)
int v = list.get(0); // Integer → int に自動変換(アンボクシング)
Javaこういうコードがコンパイルできるのは、
オートボクシング/アンボクシングのおかげです。
ただし「null アンボクシング」は危険(よくあるバグ)
ラッパークラスが null のときに、アンボクシングが走ると NPE(NullPointerException)になります。
Integer obj = null;
int x = obj; // ここで NullPointerException
Java内部的には obj.intValue() を呼んでいるのと同じなので、obj が null だと当然落ちます。
ラッパークラスを使うときは、
「この変数、null になり得るか?」
「基本型にアンボクシングするときに大丈夫か?」
を意識しておかないと、気づきにくい NPE を食らいやすくなります。
ラッパークラスが持っている便利メソッドたち
文字列 ←→ 数値の変換(parse 系 / valueOf)
ラッパークラスは、「文字列と数値の変換」をするメソッドを持っています。
int i = Integer.parseInt("123"); // "123" → 123
double d = Double.parseDouble("3.14");
boolean b = Boolean.parseBoolean("true");
Java逆に、「数値 → 文字列」は基本型でも String.valueOf(...) でできますが、
ラッパークラスの toString() でも同じようなことができます。
Integer n = 123;
String s = n.toString(); // "123"
Javaまた、valueOf は「ラッパークラスを返す」バージョンです。
Integer obj = Integer.valueOf("123"); // String → Integer
Integer obj2 = Integer.valueOf(123); // int → Integer
JavaparseXxx は基本型を返し、valueOf はラッパークラスを返す、
という違いを覚えておくと整理しやすいです。
定数(MAX_VALUE / MIN_VALUE 等)
ラッパークラスは、その型の最大・最小値を表す定数も持っています。
int max = Integer.MAX_VALUE;
int min = Integer.MIN_VALUE;
long lmax = Long.MAX_VALUE;
Java範囲チェックをするときや、
オーバーフローを意識するときに使われます。
ラッパークラスと equals / == の違い(ここもよくハマる)
== は「参照比較」、equals は「値比較」
ラッパークラスはクラス(オブジェクト)なので、== は「同じインスタンスかどうか」を比較します。
Integer a = new Integer(100);
Integer b = new Integer(100);
System.out.println(a == b); // ほぼ確実に false
System.out.println(a.equals(b)); // true(中身の値が同じ)
Java「値が同じかどうか」を見たいなら、ラッパークラスでも equals を使う必要があります。
小さい整数の「キャッシュ」による罠
実は、Integer など一部のラッパークラスは、
小さい値(-128〜127 の範囲)をキャッシュしています。
Integer x = 100;
Integer y = 100;
System.out.println(x == y); // true になることが多い
Integer p = 200;
Integer q = 200;
System.out.println(p == q); // false になることが多い
Javaこれがややこしいポイントです。
- たまたま小さい値だと
==が true になることがある - でも大きくなると false になる
こんな不安定なものに頼るべきではありません。
ラッパークラス同士の比較は、必ず equals を使う
(またはアンボクシングして基本型同士 == 比較)
と決めておくのが安全です。
「ラッパークラスをいつ使うか」をまとめて整理する
典型的な使いどころ
ラッパークラスを自然に使う場面はだいたい決まっています。
コレクションやジェネリクスの中で数値を扱いたいとき
List<Integer> ages = new ArrayList<>();
Map<String, Long> accessCount = new HashMap<>();
Javaここはもう「そういうもの」として使うしかありません。
null を使って「値なし」を表したいとき
Integer score = null; // まだ採点されていない
Javaここから、
- 「本当に null で良いのか?」
- 「Optional<Integer> の方が安全では?」
といった設計の議論につながっていきますが、
ひとまず「基本型には null が入らない」の対策としてラッパークラスがあります。
文字列との変換をするとき
int value = Integer.parseInt(inputText);
Integer obj = Integer.valueOf(value);
Java値がフォームなどから String として来る場合は、
ラッパークラスの静的メソッドによくお世話になります。
ラッパークラスの注意点と、初心者としての意識ポイント
パフォーマンス面:ボクシングしすぎに注意
ラッパークラスはオブジェクトなので、
基本型よりメモリ・速度の面で重くなります。
特にループで大量にボクシング・アンボクシングを繰り返すと、
無駄なオブジェクト生成が増えてパフォーマンスに影響することがあります。
long sum = 0;
for (int i = 0; i < 1_000_000; i++) {
Integer x = i; // 毎回ボクシング
sum += x; // 毎回アンボクシング
}
Java初心者のうちはそこまで気にしなくてもいいですが、
- 算術計算はなるべく基本型でやる
- コレクションに入れる必要があるところだけラッパークラス
くらいを意識しておくとバランスが良いです。
null アンボクシングによる NPE に特に注意(重要)
もう一度あえて強調すると、
Integer n = null;
int x = n; // ここで NPE
Javaこのパターンは本当によくやらかされます。
「ラッパークラスから基本型に代入している」ときは、
「このラッパー、null になる可能性は?」と必ず自問してください。
必要なら、
int x = (n != null) ? n : 0;
Javaや、
int x = Optional.ofNullable(n).orElse(0);
Javaのように「null のときどうするか」を明示しておくのが安全です。
まとめ:ラッパークラス全体像を頭の中に描く
ここまでを、初心者向けにぎゅっとまとめるとこうです。
- ラッパークラスは「基本型をオブジェクトとして包むクラス」
- コレクションやジェネリクスで数値を扱うときに必須
- ラッパークラスは null を持てるので「値なし」を表現できる
- オートボクシング/アンボクシングのおかげで、int と Integer の代入が自然に書ける
- ただし、null のアンボクシング(Integer → int)で NPE に注意
- ラッパークラス同士の比較で
==を使わず、equalsかアンボクシングして基本型比較を使う
