【Java】メソッドのオーバーロードとオーバーライドの違いと覚え方を解説

アイキャッチ画像

Java初心者にとって、つまづくポイントの一つがオーバーロードとオーバーライドの区別だと思います。

この記事では、これら二つの違いをご紹介します。

Java初心者の方におすすめの記事です!

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

早速ですが、オーバーロードとオーバーライドの違いを表にまとめると以下のようになります。どちらも元のメソッドと同じ名前を持つのは共通していますが、以下の違いがあります。

オーバーロードオーバーライド
使いどころ同一のクラス内で、引数のデータ型と順番によって処理を変えるときサブクラスでメソッドの処理を変えるとき
アクセス修飾子制限なし元のメソッドと同じか、よりゆるいもの
戻り値型制限なし共変戻り値(元のメソッドと同じか、そのサブクラスのデータ型)
引数のデータ型と順番元のメソッドと違う元のメソッドと同一
呼び出し方元のメソッドに比べて引数のデータ型と順番が違う元のメソッドと変わらない

以下、表の中で特に気をつけたいポイントについて紹介します。話をわかりやすくするために、こちらのParentクラスのメソッドに対してオーバーロードあるいはオーバーライドしたメソッドを実装する想定でお話します。

“`Java

class Parent {

    Number method() {

        System.out.println(“元のメソッド”);

        return 0;

    }

}

“`

使い所

オーバーロードとオーバーライドは、使う意義が異なります。

まずオーバーロードは、一つのクラス内で、引数のデータ型と順番によって同名のメソッドの処理を変えるときに使います。例えば以下のような形です。引数を複数用意する場合、引数のデータ型が同じでも、順番が違えば別のメソッドとみなされます。

“`Java

class Parent {

    //元のメソッド

    Number method() {

        System.out.println(“元のメソッド”);

        return 0;

    }

    //オーバーロード1 

    Number method(int num) {

        System.out.println(“int型の引数:” + num);

        return 1;

    }

    //オーバーロード2 

    Number method(String text) {

        System.out.println(“String型の引数:” + text);

        return 2;

    }

    //オーバーロード3

    Number method(int num, String text) {

        System.out.println(“int型の引数:” + num + “、String型の引数:” + text);

        return 3;

    }

    //オーバーロード4(引数のデータ型はオーバーロード3と同じだが、順番が異なる)→問題なし

    Number method(String text , int num) {

        System.out.println(“String型の引数:” + text + “、int型の引数:” + num);

        return 4;

    }

}

“`

ただし引数の順番が違っても、その引数間で型変換ができるのならばコンパイルエラーが発生します。例えば以下2つのメソッドでは引数にint型とlong型を設定してその順番を変えていますが、コンパイルエラーが発生します。int型からlong型へ暗黙の型変換が行われてメソッドの区別がつかなくなるためです。

“`Java

    Number method(int num1 , long num2) {

        System.out.println(“int型の引数:” + num1 + “、long型の引数:” + num2);

        return 5;

    }

    Number method(long num1, int num2) {

        System.out.println(“long型の引数:” + num1 + “、int型の引数:” + num2);

        return 6;

    }

“`

“`Java

public class Main {

    public static void main(String[] args){

        Parent parent = new Parent();

        System.out.println(parent.method(0, 0)); //エラー: methodの参照はあいまいです Parentのメソッド method(int,long)とParentのメソッド method(long,int)の両方が一致します

    }

}

“`

一方でオーバーライドは、サブクラスでメソッドの処理を変える際に使います。以下のような形で定義します。

“`Java

class Child extends Parent { //ChildクラスはParentクラスのサブクラス

    @Override

    Number method() {

        System.out.println(“子供のメソッド”);

        return 10;

    }

}

“`

呼び出し方

オーバーロードとオーバーライドのわかりやすい違いの一つが、メソッドを呼び出す時の違いです。

オーバーロードは引数のデータ型や順番ごとに違った呼び出し方をします。

“`Java

public class Main {

    public static void main(String[] args){

        Parent parent = new Parent();

        System.out.println(parent.method());

        System.out.println(parent.method(1)); //オーバーロード1

        System.out.println(parent.method(“テスト”)); //オーバーロード2

        System.out.println(parent.method(1, “テスト”)); //オーバーロード3

        System.out.println(parent.method(“テスト”, 1)); //オーバーロード4

    }

}

“`

一方で、オーバーライドのメソッドの呼び出し方は親クラスのメソッドと変わりません。インスタンスに応じたメソッドが実行されます。

“`Java

public class Main {

    public static void main(String[] args){

        Parent parent = new Parent();

        System.out.println(parent.method());

        Parent child = new Child();

        System.out.println(child.method()); //オーバーライド

    }

}

“`

戻り値型

戻り値型についても、違いがあります。

オーバーロードの戻り値型には制限がありません。以下のように、元のメソッドとは全く関係のないデータ型を戻り値型に指定できます。

“`Java

    String method(double num) {

        System.out.println(“double型の引数:” + num);

        return “テスト”;

    }

“`

一方で、オーバーライドの戻り値型には制限があります。元の戻り値型と同じデータ型か、そのサブクラスのみを戻り値型にできます。これを共変戻り値といいます。

具体例を挙げると、以下のようになります。IntegerはNumberのサブクラスであるため、コンパイルエラーは起きません。

“`Java

public class Child extends Parent {

    @Override

    Integer method() { //IntegerクラスはNumberクラスのサブクラスなので、無問題

        System.out.println(“子供のメソッド”);

        return 10;

    }

}

“`

以下のように戻り値型が元の戻り値のクラスそのものやサブクラスではない場合は、エラーが発生します。

“`Java

public class Child extends Parent {

    @Override

    String method() { //StringクラスはNumberクラスのサブクラスではないので、エラー

        System.out.println(“子供のメソッド”);

        return “これはエラーになります”;

    }

}

“`

違いの覚え方

ここでは、オーバーロードとオーバーライドの違いの覚え方を紹介します。なお以下の説明はあくまでイメージであり、それぞれの処理に現状の名前が付けられた由来を説明するものではありません。

オーバーロード:一つのかご(同名のメソッド)に、複数の荷物(引数のデータ型や順番)を入れる

元々、オーバーロード(Overload)には、「〜に物を過剰に積む」という意味があるようです。これをJavaの文脈に合わせるなら、一つのかご(同名のメソッド)に、例えば以下のような複数の荷物(引数のデータ型や順番)を入れるイメージになると思います。

  • 引数なし
  • String型の引数
  • String型の引数とint型の引数

オーバーライド:親クラスでの記述より、子クラスでの記述が優先される

オーバーライド(Override)には「〜よりも優先される」という意味があるようです。Javaのメソッドの説明に当てはめると、「同じシグネチャのメソッドにおいて、親クラスに書かれた処理より、子クラスに書かれた処理が優先される」ということになります。

まとめ

この記事では、オーバーロードとオーバーライドの違いを紹介しました。どちらも名前こそ似ていますが、使いどころなどに相違点があります。それらの相違点を意識しましょう。