パラメーターを持つ3つのメソッドを追加しました。
public static void doSomething(Object obj) {
System.out.println("Object called");
}
public static void doSomething(char[] obj) {
System.out.println("Array called");
}
public static void doSomething(Integer obj) {
System.out.println("Integer called");
}
doSomething(null)
を呼び出すと、コンパイラはambiguous methodsとしてエラーをスローします。 Integer
とchar[]
メソッド、またはInteger
とObject
メソッドが原因で問題が発生していますか?
Javaは常に、使用可能なメソッドの最も具体的な適用可能なバージョンを使用しようとします( JLS§15.12.2 を参照)。
Object
、char[]
、およびInteger
はすべて、null
を有効な値として使用できます。したがって、3つのバージョンすべてが適用されるため、Javaは最も具体的なバージョンを見つける必要があります。
Object
はchar[]
のスーパータイプであるため、配列バージョンはObject
- versionよりも具体的です。したがって、これらの2つのメソッドのみが存在する場合、char[]
バージョンが選択されます。
char[]
とInteger
の両方のバージョンが使用可能な場合、bothの両方はObject
よりも具体的ですが、他よりも具体的なものはないため、Javaはどちらを呼び出すかを決定できません。この場合、適切な型に引数をキャストすることで、呼び出したいものを明示的に指定する必要があります。
実際には、この問題は考えられるよりもはるかにまれにしか発生しないことに注意してください。この理由は、null
を使用して、またはかなり不特定のタイプの変数(Object
など)を使用してメソッドを明示的に呼び出している場合にのみ発生するためです。
それどころか、次の呼び出しは完全に明確です。
char[] x = null;
doSomething(x);
まだ値null
を渡していますが、Javaは変数の型を考慮するため、呼び出すメソッドを正確に知っています。
これら3つのメソッドの各ペアは、null
引数で呼び出された場合、それ自体があいまいです。各パラメータタイプは参照タイプであるためです。
以下は、nullを使用して特定のメソッドを呼び出す3つの方法です。
doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);
null
引数を使用してこれらのメソッドを実際に呼び出す場合は、このあいまいさを解消することをお勧めします。このような設計では、将来的にエラーが発生します。
null
は、3つのタイプのいずれに対しても有効な値です。そのため、コンパイラは使用する関数を決定できません。代わりにdoSomething((Object)null)
またはdoSomething((Integer)null)
などを使用してください。
JavaのすべてのクラスはObjectクラスを拡張します。整数クラスでもObjectを拡張します。したがって、オブジェクトと整数の両方がオブジェクトインスタンスと見なされます。したがって、パラメーターとしてnullを渡すと、コンパイラーはどのオブジェクトメソッドを呼び出すか、つまりパラメーターObjectまたはパラメーターIntegerが両方ともオブジェクトであり、参照がnullになる可能性があるため、どのオブジェクトメソッドを呼び出すのか混乱します。ただし、JavaのプリミティブはObjectを拡張しません。
私はこれを試してみましたが、オーバーロードされたメソッドのペアがちょうど1つあり、そのうちの1つにパラメータ型Objectがある場合、コンパイラは常により具体的な型のメソッドを選択します。ただし、特定の型が複数ある場合、コンパイラはあいまいなメソッドエラーをスローします。
これはコンパイル時イベントであるため、このメソッドに意図的にnullを渡した場合にのみ発生します。これが意図的に行われる場合、このメソッドをパラメーターなしで再度オーバーロードするか、別のメソッドを作成することをお勧めします。
class Sample{
public static void main (String[] args) {
Sample s = new Sample();
s.printVal(null);
}
public static void printVal(Object i){
System.out.println("obj called "+i);
}
public static void printVal(Integer i){
System.out.println("Int called "+i);
}
}
出力はnullと呼ばれるIntであるため、あいまいさはchar []とIntegerにあります
doSomething(char [] obj)およびdoSomething(Integer obj)のためにあいまいさがあります。
char []とIntegerは、どちらもnullの場合と同じ優れているため、あいまいです。