16.

オーバーロード

編集

本稿は Java のオーバーロードに関する記事です。

オーバーロードとは?

オーバーロード (Overload) とは、同一クラス内でメソッド名は同じでも、引数の数・型・順序が異なるメソッドを複数定義する仕組みです。呼び出し側は引数の形に応じて自動的に適切なメソッドが選択される (静的ディスパッチ) ため、似た用途のメソッドを統一的な名前で扱えます。

例えば、同じ「合計を計算する」処理を、整数 2 つ・整数 3 つ・配列で受け取りたいといった場合に、いずれも sum(...) という名前で呼び出せるようにできます。メソッドだけでなくコンストラクタもオーバーロード可能です。

オーバーロードの実装例

以下はいずれも異なるオーバーロードとして扱われます。

void testMethod(int val1) { ... }
void testMethod(int val1, int val2) { ... }
void testMethod(String val1, int val2) { ... }
void testMethod(int val2, String val1) { ... }

オーバーロードの条件

判別される判別されない (コンパイルエラーになる)
引数のが違う引数名だけ違う
引数のが違う戻り値の型だけ違う
引数の順序が違う (型が変わるため)throws する例外だけ違う
可変長引数 (...) と固定引数の組み合わせ修飾子 (public / final) だけ違う

典型的な利用例 (合計を計算)

public class Calculator {
  public int sum(int a, int b) {
    return a + b;
  }
  public int sum(int a, int b, int c) {
    return a + b + c;
  }
  public int sum(int... nums) {
    int s = 0;
    for (int n : nums) s += n;
    return s;
  }
  public double sum(double a, double b) {
    return a + b;
  }
}

Calculator c = new Calculator();
c.sum(1, 2);           // int + int
c.sum(1, 2, 3);        // 3 個版
c.sum(1, 2, 3, 4, 5);   // 可変長版
c.sum(1.5, 2.5);       // double 版

コンストラクタのオーバーロード

public class User {
    private final String name;
    private final int age;

    public User(String name) {
        this(name, 0);  // 別コンストラクタへ委譲
    }

    public User(String name, int age) {
        this.name = name;
        this.age  = age;
    }
}

オーバーロードとオーバーライドの違い

項目オーバーロードオーバーライド
関係同一クラス内 (継承関係でも可)親 → 子のクラス間
判別引数の数・型・順序シグネチャは親と同じで内容を上書き
ディスパッチ静的 (コンパイル時)動的 (実行時のインスタンス型)
典型用途同名メソッドの引数違いを集約多態 (ポリモーフィズム)

詳しくは オーバーライド も参照。

呼び出し時の型解決ルール

  • コンパイラはもっとも「狭い (具体的な)」型一致を選ぶ
  • 暗黙の型変換 (intlong 等) が必要なものより、ぴったり一致を優先
  • autoboxing (intInteger) は最後の手段として選ばれる
  • 可変長引数 (...) は他の候補が無いときに選ばれる
  • あいまいな場合はコンパイルエラー (reference to ... is ambiguous)

注意点・アンチパターン

  • 引数の意味が違うメソッドは別名にするsave(File)save(String) のように「同じ意味で型違い」の場合のみオーバーロードが適切
  • autoboxing と可変長引数を混ぜないm(int)m(Integer) 等は予想外の選択になりやすい
  • 戻り値型だけ違うのはオーバーロードではなくコンパイルエラー
  • 引数の順序を入れ替えただけのオーバーロードは呼び側を混乱させる。可能なら避ける
  • API 設計時は「同じ名前で 3 つ以上のオーバーロード」になったら、別メソッド名や Builder の検討
  • ジェネリクスでの消去 (Erasure) によって、見た目が違っても実体が同じになり、オーバーロード不可になることがある

関連

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 基本的なルール
  2. データ型
  3. 変数
  4. 定数
  5. 配列
  6. コレクション(List,Set,Queue)
  7. Map(連想配列)
  8. 演算子
  9. 条件分岐
  10. 繰り返し制御文
  11. クラス
  12. メソッド
  13. インスタンス化
  14. コンストラクタ
  15. staticキーワード
  16. オーバーロード
  17. 継承
  18. オーバーライド
  19. this
  20. super
  21. パッケージ
  22. アクセス修飾子
  23. 抽象クラス・メソッド
  24. インターフェース
  25. カプセル化
  26. データベース接続
  27. セッション
  28. ファイル入出力
  29. ラムダ式