山崎屋の技術メモ

IT業界で働く中でテクノロジーを愛するSIerのシステムエンジニア👨‍💻 | AndroidとWebアプリの二刀流🧙‍♂️ | コードの裏にあるストーリーを綴るブログ執筆者✍️ | 日々進化するデジタル世界で学び続ける探究者🚀 | #TechLover #CodeArtisan、気になること、メモしておきたいことを書いていきます。

Java オーバーロードの条件

オーバーロードの話です。オーバーライドではありません。

違いを簡単に

オーバーロードオーバーライドの違いを簡単に説明します。

オーバーライドは、親クラスのメソッドを子クラスで定義しなおすことです。通常、メソッドに @Override アノテーションを付与します。

package org.yyama;

// 親クラス
public class Oya {

	public void method() {
		System.out.println("hoge");
	}

}

↑↑↑ のような親クラスがあったとして、

package org.yyama;

// 子クラス
public class Ko extends Oya {

	@Override
	public void method() {
		System.out.println("fuga");
	}

}

このように子クラスで method メソッドを再定義することがオーバーライド。

一方、オーバーロードは、同一クラス内で、同じメソッド名を複数定義することを指します。

今回はこの「オーバーロード」できる条件についての記事です。

オーバーロードの条件

同一クラス内ですでに使われているメソッド名を再び定義することをオーバーロードするといいます。ただし、引数の数・型・順番の少なくともひとつが異なる必要があります。

具体的に見てみましょう。

まずは、オーバーロードできるケースです。

	public int methodA(int i, String s) {
		return 1;
	}

	public int methodA(int i) {
		return 1;
	}

引数の数が異なっているのでOK。

	public int methodA(int i, String s) {
		return 1;
	}

	public int methodA(long i, String s) {
		return 1;
	}

一個目の引数の型が異なるのでOK。

	public int methodA(int i, String s) {
		return 1;
	}

	public int methodA(String s, int i) {
		return 1;
	}

引数の順番が異なるのでOK。



それでは、オーバーロードできない(コンパイルエラーになります。)場合の具体例を見てみましょう。

	public int methodB(int i) {
		return i;
	}

	public int methodB(int i) {
		return i;
	}

まったく同じ。論外。

	public int methodB(int i) {
		return i;
	}

	public String methodB(int i) {
		return "a";
	}

戻り値の型が異なるだけ。NG。
なんか許していい気もするが、言語仕様的にだめです。

	public int methodB(int i) {
		return i;
	}

	public int methodB(int i) throws Exception {
		return 1;
	}

片方のメソッドで throws を宣言しているが引数が同じ。NG。

	public int methodB(int i) {
		return i;
	}

	public static int methodB(int i) {
		return 1;
	}

片方のメソッドは static メソッドで引数は同じ。
許していい気もするが、NG。

	public int methodB(List<String> sList) {
		return 1;
	}

	public int methodB(List<Long> lList) {
		return 1;
	}

引数の型パラメータのみ異なる。NG。コンパイルされると型パラメータは消去されてしまう。

オーバーロードされたメソッドの引数が継承関係にあたる場合の注意

ややこしい見出しですが、以下のようなコードがあった場合、どちらの method が呼ばれるでしょうか?
main メソッドで method を呼ぶ際の引数 num は Number 型ですが、その実態は Integer です。

public class Oya {
	public static void method(Number n) {
		System.out.println("Number を受け取る methodB");
	}

	public static  void method(Integer i) {
		System.out.println("Integer を受け取る methodB");
	}

	public static void main(String[] args) {
		Number num = new Integer(1);
		method(num);
	}
}


正解はこちら。

Number を受け取る method

メソッド呼び出しに指定する引数の型、ここでは「method(num);」の num が Number 型なので、 Number 型を受け取るメソッドが実行されます。

オーバーロードのまとめ

一見どのメソッドを呼べばいいのか分かりにくくなりそうですが、オーバーロードをうまく使いこなすと、非常に使いやすい API ができます。GoF のデザインパターンでも使用されています。

でわ。

スッキリわかる Java入門 実践編 第2版 (スッキリシリーズ)

スッキリわかる Java入門 実践編 第2版 (スッキリシリーズ)

スッキリわかるJava入門 第2版 (スッキリシリーズ)

スッキリわかるJava入門 第2版 (スッキリシリーズ)

↓もう第 7 版だw。
やさしいJava 第7版 (「やさしい」シリーズ)

やさしいJava 第7版 (「やさしい」シリーズ)