山崎屋の技術メモ

IT業界で働く中で、気になること、メモしておきたいことを書いていきます。

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

指定する引数の型にあわせてメソッドが呼ばれます。引数の実態の型ではないので注意しましょう。

まとめ

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

でわ。

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

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

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

↓もう第6版だw。