【Java初心者向け】オーバーロードとオーバーライドの違いとは?見分け方と使い分けを解説

【Java初心者向け】オーバーロードとオーバーライドの違いとは?見分け方と使い分けを解説

結論として、オーバーロードは「同じクラス内などで、同じメソッド名を引数違いで複数定義すること」、オーバーライドは「親クラスのメソッドを子クラスで上書きすること」です。

名前が似ているため混同しやすいですが、目的も成立条件も異なります。

比較項目 オーバーロード オーバーライド
主な意味 同名メソッドを複数用意する 親クラスの処理を子クラスで上書きする
英語 Overload Override
引数 異なる必要がある 基本的に同じ
継承 必須ではない 必要
主な目的 呼び出し方を増やす クラスごとに処理を変更する

オーバーロードとは

オーバーロードとは、同じメソッド名で、引数の数や型が異なるメソッドを複数定義する仕組みです。

日本語では「多重定義」と呼ばれることがあります。

class Calculator {

    int add(int a, int b) {
        return a + b;
    }

    int add(int a, int b, int c) {
        return a + b + c;
    }

    double add(double a, double b) {
        return a + b;
    }
}

上記では、addという同じメソッド名を使用していますが、引数が異なるため別のメソッドとして扱われます。

オーバーライドとは

オーバーライドとは、親クラスで定義されたメソッドを、子クラスで同じ形のまま再定義する仕組みです。

日本語では「上書き」と説明されることが多くあります。

class Employee {

    void work() {
        System.out.println("仕事をします");
    }
}

class Engineer extends Employee {

    @Override
    void work() {
        System.out.println("システムを開発します");
    }
}

Engineerクラスでは、親クラスEmployeeのworkメソッドをオーバーライドしています。

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

比較項目 オーバーロード オーバーライド
定義場所 同じクラス内が一般的 親クラスと子クラス
メソッド名 同じ 同じ
引数の数 異なってよい 同じ
引数の型 異なってよい 同じ
戻り値 戻り値だけ変えても成立しない 同じ型または互換性のある型
継承関係 不要 必要
判定時期 主にコンパイル時 主に実行時

どんな場面で使われるのか

オーバーロードを使う場面

  • 引数の数が異なる計算処理を用意する
  • 文字列や数値など、複数の型を受け付ける
  • 初期値あり・なしの処理を用意する
  • 同じ目的の処理を統一したメソッド名で呼び出す

オーバーライドを使う場面

  • 親クラスの標準処理を子クラスごとに変更する
  • インターフェースのメソッドを実装する
  • クラスごとに表示内容や計算方法を切り替える
  • 共通処理を残しつつ、一部の動作だけ変更する

なぜ重要なのか

オーバーロードを使うと、似た役割のメソッド名を統一できるため、利用する側が覚えやすくなります。

一方、オーバーライドを使うと、親クラスを共通の型として扱いながら、実際の処理だけを子クラスごとに変更できます。

この仕組みは、オブジェクト指向の重要な考え方であるポリモーフィズム(多態性)につながります。

初心者が混乱しやすいポイント

どちらもメソッド名が同じ

オーバーロードとオーバーライドは、どちらも同じメソッド名を使います。

見分けるときは、引数が違うのか、継承先で上書きしているのかを確認します。

戻り値だけを変えてもオーバーロードにならない

次のように、戻り値だけが異なるメソッドは定義できません。

int getValue() {
    return 1;
}

double getValue() {
    return 1.0;
}

Javaは呼び出し時に戻り値だけでメソッドを区別できないため、コンパイルエラーになります。

引数名を変えてもオーバーロードにならない

void print(String name) {
}

void print(String message) {
}

引数名がnameとmessageで異なっていても、どちらもString型を1つ受け取るため、同じメソッドと判断されます。

オーバーロードが成立する条件

オーバーロードを成立させるには、メソッド名を同じにしたうえで、次のいずれかを変更します。

  • 引数の数
  • 引数の型
  • 引数の並び順
void register(String name) {
}

void register(String name, int age) {
}

void register(int id, String name) {
}

void register(String name, int id) {
}

ただし、引数の並び順だけを変える方法は、呼び出す側が混乱しやすいため、実務では慎重に使用します。

オーバーライドが成立する条件

オーバーライドでは、親クラスのメソッドと次の内容を合わせる必要があります。

  • メソッド名
  • 引数の数
  • 引数の型

また、子クラス側で親クラスよりアクセス範囲を狭くすることはできません。

親クラス 子クラス 結果
public public
protected public
public protected ×

@Overrideを付ける理由

オーバーライドするメソッドには、@Overrideアノテーションを付けるのが基本です。

@Override
void work() {
    System.out.println("システムを開発します");
}

@Overrideを付けると、メソッド名や引数を間違えた場合にコンパイラが検出してくれます。

付けなくても条件を満たせばオーバーライドは成立しますが、入力ミスを防ぐため、実務では付けることが推奨されます。

実際のIT現場での利用例

オーバーロードの利用例

ログ出力処理では、通常メッセージだけを渡す場合と、例外情報も一緒に渡す場合があります。

void writeLog(String message) {
    System.out.println(message);
}

void writeLog(String message, Exception exception) {
    System.out.println(message);
    exception.printStackTrace();
}

オーバーライドの利用例

通知システムでは、通知方法ごとにsendメソッドの処理を変更できます。

class Notification {

    void send() {
        System.out.println("通知します");
    }
}

class EmailNotification extends Notification {

    @Override
    void send() {
        System.out.println("メールを送信します");
    }
}

class ChatNotification extends Notification {

    @Override
    void send() {
        System.out.println("チャットへ送信します");
    }
}

筆者が実際に経験した失敗例

新人時代、親クラスのメソッドをオーバーライドしたつもりで、引数の型を間違えて定義したことがありました。

実際にはオーバーライドではなく、新しいオーバーロードとして扱われていたため、親クラスの処理がそのまま実行されました。

@Overrideを付けたところ、コンパイル時に誤りを検出できました。それ以降、オーバーライドするメソッドには必ず@Overrideを付けています。

業務でよくあるトラブル例

  • オーバーライドしたつもりがオーバーロードになっている
  • 引数の型を間違えて親クラスの処理が実行される
  • @Overrideを付けず、入力ミスに気付けない
  • 戻り値だけを変えてオーバーロードしようとする
  • 親クラスより狭いアクセス修飾子を指定する

原因の切り分け

期待したメソッドが呼び出されない場合は、次の順番で確認します。

  1. 実際に生成されているオブジェクトのクラスを確認する
  2. メソッド名が一致しているか確認する
  3. 引数の数と型を確認する
  4. @Overrideが付いているか確認する
  5. 親クラスと子クラスの継承関係を確認する
  6. IDEのデバッグ機能で実行されるメソッドを確認する

GUIでの確認方法

IntelliJ IDEAやEclipseでは、メソッド名の横に表示されるアイコンから、親クラスや子クラスのメソッドへ移動できます。

  • メソッド名を右クリックして定義元を確認する
  • 呼び出し階層を表示する
  • ブレークポイントを設定して実行箇所を確認する
  • オーバーライドされているメソッドの一覧を確認する

よく使うショートカットキー

操作 IntelliJ IDEA Eclipse
定義へ移動 Ctrl + B F3
実装へ移動 Ctrl + Alt + B Ctrl + T
呼び出し階層 Ctrl + Alt + H Ctrl + Alt + H

macOSでは、Ctrlの代わりにCommandやOptionを使用する場合があります。

CUIでの確認方法

Javaのコンパイル結果やテスト結果は、コマンドからも確認できます。

  • javac ファイル名.java
  • mvn test
  • gradle test

オーバーライド条件を満たしていない場合、@Overrideを付けていればコンパイルエラーとして検出されます。

ログの確認方法

どのメソッドが実行されているか分からない場合は、クラス名とメソッド名をログへ記録します。

System.out.println("EmailNotification.sendを実行しました");

実務では、System.out.printlnではなく、プロジェクトで採用されているログ出力ライブラリを使用します。

ログでは次の内容を確認します。

  • 実行されたクラス名
  • 実行されたメソッド名
  • 渡された引数
  • 処理の開始時刻と終了時刻
  • 例外の有無

確認結果の見方

確認結果 判断
同名で引数が異なる オーバーロード
親子関係があり、同じ引数で再定義 オーバーライド
戻り値だけが異なる コンパイルエラー
@Overrideでエラーになる メソッド名や引数が親クラスと一致していない可能性

初心者がやりがちなミス

  • オーバーロードとオーバーライドの名前を逆に覚える
  • 引数名を変えればオーバーロードになると思う
  • 戻り値を変えればオーバーロードできると思う
  • 継承していないクラスでオーバーライドしようとする
  • privateメソッドをオーバーライドできると思う

注意点

privateメソッドは子クラスから直接見えないため、オーバーライドできません。

また、finalが付いたメソッドもオーバーライドできません。

メソッド オーバーライド
publicメソッド 可能
protectedメソッド 可能
privateメソッド 不可
finalメソッド 不可
staticメソッド 通常のオーバーライドではない

上司へ報告するポイント

  • 期待した処理と実際に実行された処理
  • 対象クラスとメソッド名
  • 引数の型と数
  • 継承関係
  • 影響を受ける機能
  • 再現手順
  • 修正内容とテスト結果

エスカレーションするタイミング

  • 共通クラスの変更が複数機能へ影響する
  • 継承設計そのものを見直す必要がある
  • 外部ライブラリのメソッドを正しく拡張できない
  • 修正後の影響範囲を判断できない
  • 本番環境で誤った処理が実行されている

応用知識

ポリモーフィズムとの関係

オーバーライドを利用すると、親クラス型の変数に異なる子クラスのオブジェクトを代入し、それぞれ異なる処理を実行できます。

Notification notification = new EmailNotification();
notification.send();

変数の型はNotificationですが、実際のオブジェクトはEmailNotificationのため、EmailNotificationでオーバーライドしたsendメソッドが実行されます。

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

コンストラクタも引数を変えることでオーバーロードできます。

class User {

    User() {
    }

    User(String name) {
    }

    User(String name, int age) {
    }
}

一方、コンストラクタは継承されないため、オーバーライドはできません。

関連するIT用語

  • 継承
  • 親クラス
  • 子クラス
  • メソッド
  • 引数
  • 戻り値
  • ポリモーフィズム
  • アクセス修飾子
  • インターフェース
  • 抽象クラス
  • アノテーション

よくある質問(FAQ)

オーバーロードとオーバーライドの簡単な覚え方はありますか?

オーバーロードは「同じ名前のメソッドを追加する」、オーバーライドは「親の処理を上書きする」と覚えると区別しやすくなります。

戻り値を変えるだけでオーバーロードできますか?

できません。オーバーロードでは、引数の数、型、並び順のいずれかを変える必要があります。

@Overrideは必須ですか?

文法上は必須ではありませんが、入力ミスをコンパイル時に発見できるため、付けるのが基本です。

staticメソッドはオーバーライドできますか?

通常の意味でのオーバーライドはできません。子クラスで同じ形のstaticメソッドを定義した場合は、メソッドの隠蔽と呼ばれます。

privateメソッドはオーバーライドできますか?

できません。privateメソッドは子クラスから参照できないため、同名メソッドを定義しても別のメソッドとして扱われます。

まとめ

オーバーロードとオーバーライドは、どちらも同じメソッド名を使いますが、目的と成立条件が異なります。

  • オーバーロードは引数を変えて同名メソッドを複数定義する仕組み
  • オーバーライドは親クラスのメソッドを子クラスで上書きする仕組み
  • オーバーロードに継承は必要ない
  • オーバーライドには親子関係が必要
  • 戻り値だけを変えてもオーバーロードにはならない
  • オーバーライド時は@Overrideを付ける

見分けるときは、「引数違いで同名メソッドを増やしているのか」「親クラスの処理を子クラスで上書きしているのか」を確認しましょう。この違いを理解すると、Javaの継承やポリモーフィズムも理解しやすくなります。

コメント

タイトルとURLをコピーしました