web-dev-qa-db-ja.com

null引数のメソッドのオーバーロード

パラメーターを持つ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としてエラーをスローします。 Integerchar[]メソッド、またはIntegerObjectメソッドが原因で問題が発生していますか?

128
Phani

Javaは常に、使用可能なメソッドの最も具体的な適用可能なバージョンを使用しようとします( JLS§15.12.2 を参照)。

Objectchar[]、およびIntegerはすべて、nullを有効な値として使用できます。したがって、3つのバージョンすべてが適用されるため、Javaは最も具体的なバージョンを見つける必要があります。

Objectchar[]のスーパータイプであるため、配列バージョンはObject- versionよりも具体的です。したがって、これらの2つのメソッドのみが存在する場合、char[]バージョンが選択されます。

char[]Integerの両方のバージョンが使用可能な場合、bothの両方はObjectよりも具体的ですが、他よりも具体的なものはないため、Javaはどちらを呼び出すかを決定できません。この場合、適切な型に引数をキャストすることで、呼び出したいものを明示的に指定する必要があります。

実際には、この問題は考えられるよりもはるかにまれにしか発生しないことに注意してください。この理由は、nullを使用して、またはかなり不特定のタイプの変数(Objectなど)を使用してメソッドを明示的に呼び出している場合にのみ発生するためです。

それどころか、次の呼び出しは完全に明確です。

char[] x = null;
doSomething(x);

まだ値nullを渡していますが、Javaは変数の型を考慮するため、呼び出すメソッドを正確に知っています。

204
Joachim Sauer

これら3つのメソッドの各ペアは、null引数で呼び出された場合、それ自体があいまいです。各パラメータタイプは参照タイプであるためです。

以下は、nullを使用して特定のメソッドを呼び出す3つの方法です。

doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);

null引数を使用してこれらのメソッドを実際に呼び出す場合は、このあいまいさを解消することをお勧めします。このような設計では、将来的にエラーが発生します。

40
jmg

nullは、3つのタイプのいずれに対しても有効な値です。そのため、コンパイラは使用する関数を決定できません。代わりにdoSomething((Object)null)またはdoSomething((Integer)null)などを使用してください。

4
Lars Noschinski

JavaのすべてのクラスはObjectクラスを拡張します。整数クラスでもObjectを拡張します。したがって、オブジェクトと整数の両方がオブジェクトインスタンスと見なされます。したがって、パラメーターとしてnullを渡すと、コンパイラーはどのオブジェクトメソッドを呼び出すか、つまりパラメーターObjectまたはパラメーターIntegerが両方ともオブジェクトであり、参照がnullになる可能性があるため、どのオブジェクトメソッドを呼び出すのか混乱します。ただし、JavaのプリミティブはObjectを拡張しません。

2
Ankit

私はこれを試してみましたが、オーバーロードされたメソッドのペアがちょうど1つあり、そのうちの1つにパラメータ型Objectがある場合、コンパイラは常により具体的な型のメソッドを選択します。ただし、特定の型が複数ある場合、コンパイラはあいまいなメソッドエラーをスローします。

これはコンパイル時イベントであるため、このメソッドに意図的にnullを渡した場合にのみ発生します。これが意図的に行われる場合、このメソッドをパラメーターなしで再度オーバーロードするか、別のメソッドを作成することをお勧めします。

1
Jafar Ali
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の場合と同じ優れているため、あいまいです。