プリミティブ型とラッパークラスのコードトレース

値の取り出しが起きる場所を、代入・比較・増分・コレクションから探します。nullを安全に比較できる場合と例外になる場合、数値の型を揃える必要がある場合を具体的なコードで解きます。

この単元で学ぶこと

  • ボクシングとアンボクシングを説明する
  • ==とequalsの条件に応じた結果を求める
  • 数値変換とnullによる例外を判定する

本文解説

同じ表示でも型が違う Integer i=7;Long l=7L;は両方printで7になりますが、i.equals(l)はfalseです。i.intValue()==l.longValue()なら数値の昇格後に比較できtrueになります。目的が数値比較かオブジェクト比較かを先に決め、必要な変換を明示します。

欠損値を安全に比べる Integer x=null;Integer y=null;のx==yはtrueで、どちらも同じnull参照を比較します。一方x.equals(y)は受け手がnullなので例外です。java.util.Objects.equals(x,y)ならnullも扱いtrueになります。APIが何を受け取り、どこでメソッドが呼ばれるかを追います。

数値との比較の途中 Integer x=null;System.out.print(x==0);ではxをintへ変換するため例外です。Integer x=null;System.out.print(x==null);では参照として比較するためtrue。記号==だけで判断せず、左右が数値型か参照型かを書き出すと変換を特定できます。

配列の初期値にも差がある new int[1]の要素初期値は0、new Integer[1]の要素初期値はnullです。後者のa[0]+1はアンボクシングで失敗します。ラッパー配列を作っただけでは、各要素に数値0のIntegerが自動で作られるわけではありません。

増分と連結の順序 Integer a=2;Integer b=a;System.out.print(a+++":"+a+":"+b);は2:3:2です。a++は古い値を式の結果に使ってaを更新し、bは元の値を参照したままです。読みやすさのため実務では一行に副作用を詰め込まず、更新と表示を分けることも検討します。

文字の解析条件 Integer.parseInt(" 8 ")は自動で前後空白を無視しません。明示的にtrim()してから解析すれば8です。Integer.parseInt("ff",16)は255になります。数字の文字列が持つ表記の基数と、得られる整数値を区別します。

ラッパー間の変換を飛ばさない Long x=1;はintからLongへ直接ボックス化できずコンパイルエラーです。Long x=1L;やLong.valueOf(1)なら可能です。一方long x=Integer.valueOf(1);はIntegerからintへ取り出した後、longへ拡大できます。許される変換の並びが異なります。

コレクションでも型が働く ArrayList<Integer>へ数値を追加する際はボクシング、getした値をintへ代入する際はアンボクシングが入ります。nullも要素にできるのでgetの結果を加算すると例外になることがあります。またlist.remove(1)はint添字、remove(Integer.valueOf(1))は値に一致する要素の削除となり、オーバーロードの違いにも型が影響します。

図解

プリミティブとラッパーの往復
参照型には値なしのnullがあり、数値に取り出す時点を追う。

重要ポイント

  • intとIntegerは同じ型ではない。
  • nullのラッパーをアンボクシングすると例外になる。
  • Integer.equalsは相手の型とint値を比較する。
  • ラッパーは不変で、++は共有オブジェクトの値を変更しない。

間違えやすい点

  • Integer同士の==を一般的な数値比較として使わない。
  • parseIntはint、valueOfはIntegerを返す。
  • 大きい値のキャッシュ範囲を実装共通と決めつけない。

用語解説

ボクシング
int等の値を対応するInteger等の参照型へ変換すること。
アンボクシング
ラッパーから対応するプリミティブ値を取り出す変換。
値の比較
同一参照かどうかとは別に、保持する値を比較すること。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。