タイトル: オーバーロード
本稿は Java のオーバーロードに関する記事です。
オーバーロードとは?
オーバーロード (Overload) とは、同一クラス内でメソッド名は同じでも、引数の数・型・順序が異なるメソッドを複数定義する仕組みです。呼び出し側は引数の形に応じて自動的に適切なメソッドが選択される (静的ディスパッチ) ため、似た用途のメソッドを統一的な名前で扱えます。
例えば、同じ「合計を計算する」処理を、整数 2 つ・整数 3 つ・配列で受け取りたいといった場合に、いずれも sum(...) という名前で呼び出せるようにできます。メソッドだけでなくコンストラクタもオーバーロード可能です。
オーバーロードの実装例
以下はいずれも異なるオーバーロードとして扱われます。
|
void testMethod(int val1) { ... } |
オーバーロードの条件
| 判別される | 判別されない (コンパイルエラーになる) |
|---|---|
| 引数の数が違う | 引数名だけ違う |
| 引数の型が違う | 戻り値の型だけ違う |
| 引数の順序が違う (型が変わるため) | throws する例外だけ違う |
可変長引数 (...) と固定引数の組み合わせ | 修飾子 (public / final) だけ違う |
典型的な利用例 (合計を計算)
|
public class Calculator { |
コンストラクタのオーバーロード
|
public class User { |
オーバーロードとオーバーライドの違い
| 項目 | オーバーロード | オーバーライド |
|---|---|---|
| 関係 | 同一クラス内 (継承関係でも可) | 親 → 子のクラス間 |
| 判別 | 引数の数・型・順序 | シグネチャは親と同じで内容を上書き |
| ディスパッチ | 静的 (コンパイル時) | 動的 (実行時のインスタンス型) |
| 典型用途 | 同名メソッドの引数違いを集約 | 多態 (ポリモーフィズム) |
詳しくは オーバーライド も参照。
呼び出し時の型解決ルール
- コンパイラはもっとも「狭い (具体的な)」型一致を選ぶ
- 暗黙の型変換 (
int→long等) が必要なものより、ぴったり一致を優先 - autoboxing (
int→Integer) は最後の手段として選ばれる - 可変長引数 (
...) は他の候補が無いときに選ばれる - あいまいな場合はコンパイルエラー (
reference to ... is ambiguous)
注意点・アンチパターン
- 引数の意味が違うメソッドは別名にする。
save(File)とsave(String)のように「同じ意味で型違い」の場合のみオーバーロードが適切 - autoboxing と可変長引数を混ぜない。
m(int)とm(Integer)等は予想外の選択になりやすい - 戻り値型だけ違うのはオーバーロードではなくコンパイルエラー
- 引数の順序を入れ替えただけのオーバーロードは呼び側を混乱させる。可能なら避ける
- API 設計時は「同じ名前で 3 つ以上のオーバーロード」になったら、別メソッド名や Builder の検討
- ジェネリクスでの消去 (Erasure) によって、見た目が違っても実体が同じになり、オーバーロード不可になることがある