オーバーロードのコードトレース

候補となる宣言を並べ、実引数の静的な型と変換を照合します。型が違えば同じ値でも呼出し先が変わることを、具体的な出力で確認します。

この単元で学ぶこと

  • 同名宣言の合法性を判定する
  • 引数の型と個数から選択されるメソッドを求める
  • 曖昧な呼出しを識別する

本文解説

キャストで型を変える f(int)とf(long)があるとき、f((long)2)はlong版です。値は2のままでも式の型が変わっています。f((int)2L)はint版になります。キャストが値の丸めを伴う場合は、その計算と呼出し先の判定を分けます。

charの数値変換 f(int)とf(long)へcharの'A'を渡すとint版が選ばれます。charは整数型として拡大変換でき、ASCIIに相当するAのコード値は65です。Stringの"A"とは違い、charをStringへ暗黙に変えるメソッド呼出し変換はありません。

ボクシングとアンボクシング Integerはintに対応するラッパークラスです。intからIntegerへの変換がボクシング、逆の変換がアンボクシングです。f(Integer)とf(int)にInteger x=1を渡すと、参照型のまま適用できるInteger版が選ばれます。intしかなければアンボクシングして呼べますが、Integer x=nullならその変換でNullPointerExceptionになります。選択と値の安全性は別です。

Objectへ拡大する場合 f(Object)とf(int)へInteger変数を渡すとObject版が先の適用段階で見つかります。参照の拡大は厳密な呼出し変換に含まれ、アンボクシングを必要とするint版より先です。名前が似ているIntegerとintが常に優先になるわけではありません。

二引数の交差 f(int,long)とf(long,int)へf(1,1)と渡すと両方が適用可能で、どちらも全引数について一方より限定的にはならず曖昧です。f(1,1L)なら前者だけを選べます。各引数の列を一つずつ確認します。

配列型の違い f(int[])とf(long[])は別の引数型です。int[]をlong[]へ要素ごとに暗黙変換して渡すことはできません。intからlongへの拡大変換ができることを、配列型全体へそのまま当てはめないようにします。

戻り値を使う側 オーバーロードを選んだ結果がlongなら、int変数へ受け取る代入は別途不正になりえます。受取型を満たす別候補へ自動で選び直すわけではありません。候補選択と戻り値代入を順に判定します。

検証の仕方 本体の戻り値にI、L、Oなど異なる目印を付け、数値計算の複雑さを排除して選択先だけを確認します。曖昧な呼出し、引数が不適用な呼出し、重複宣言は別ファイルでコンパイルし、診断理由の違いを記録します。

図解

呼出し先を決める順序
戻り値だけが異なる重複宣言は、呼出しを考える前に不正。

重要ポイント

  • 型・個数・型の順序で同名宣言を区別する。
  • 戻り値型や仮引数名だけでは区別できない。
  • 選択は実引数式の静的な型を使う。
  • 複数候補で一意に決まらなければコンパイルエラー。

間違えやすい点

  • 戻り値を受ける変数の型で宣言重複を解決できると思わない。
  • nullがどんな同名宣言でも一意に決まると考えない。
  • オーバーロードとオーバーライドを混同しない。

用語解説

オーバーロード
引数の型などが異なる同名メソッドを用意すること。
シグネチャ
ここでは名前と仮引数の型の列など、宣言を区別する情報。
静的な型
コンパイル時に式に与えられる型。
曖昧な呼出し
適用できる候補から一つを選べない呼出し。

関連教材

参考資料

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

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