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


133

パラメータ付きの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)と、コンパイラはあいまいなメソッドとしてエラーをスローします。だから、問題があるためであるIntegerchar[]メソッドまたはIntegerおよびObject方法?


3
ただ、変更Integerしますint
Mudassir 2011年

2
@Mudassir:そして、それは正確に何を解決しますか?
Joachim Sauer

2
@Joachim Sauer:Integerからintに変更した場合、Javaではnullはプリミティブ型を参照しないため、コンパイラーはエラーをスローしません。
Phani

@Joachim Sauer:reference to doSomething is ambiguousエラーは発生しません。
Mudassir 2011年

回答:


211

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

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

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

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

実際には、この問題が発生することはほとんどありません。この理由nullは、あまり具体的でない型(などObject)の変数を使用して、またはそれを使用してメソッドを明示的に呼び出している場合にのみ発生するためです。

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

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

まだ値を渡していますがnull、Javaは変数のタイプを考慮に入れるため、呼び出すメソッドを正確に認識しています。


1
これはJava 7について説明されています。これは以前のJavaバージョンにも適用されますか?つまり、型階層に沿ってのみパラメータを持つ複数のメソッドシグネチャがある場合、実際の値としてnullを使用して保存側にいるよりも、そして、ここでの例のように「階層」を構築した場合、そうではありませんか?
クリスチャンゴッシュ2015

2
これらのルールは、Java 1.1以降(少なくともジェネリックの追加を除いて)すべてにおいて同じであると確信しています。
Joachim Sauer

これは、コンパイラが実行時にdoSomething(null)を使用してdoSomething(String str)とdoSomething(Object obj)のどちらかを選択した場合、doSomething(String str)が呼び出されることを意味しますか。
Sameer

42

これら3つのメソッドの各ペアは、 null引数を指定してです。各パラメータタイプは参照タイプであるためです。

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

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

これらのメソッドをnull引数付きで呼び出す予定がある場合は、このあいまいさを取り除くことをお勧めします。そのような設計は将来エラーを招きます。


1
のみInteger- char[]@JoachimSauerは説明のように、他の2例では、Javaコンパイラは、最も具体的な選択肢を選ぶことができるので、ペアは、あいまいです。
kajacx

1
@kajacx:OPの元の質問は、これらのメソッドをnullパラメータとして呼び出すことでした。その前提条件の下では、3つのペアはすべてあいまいです。一般的なケースでは、Integer - char[]ペアのみがあいまいであることに同意します。
jmg

どの程度doSomething(null)のために public static void doSomething(String str) { System.out.println("String called"); } これはと呼ばれる文字列を返します。
2016年

「nullable」や「not nullable」などのアノテーションを使用して、nullを取得したい1つのメソッドだけを明示的に「null」(まだ暗黙のnull型)引数が常に明確に選択されるように設定することは可能ですか?特定のオーバーロード??
peterk 2017

4

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


Integerパラメータを持つメソッドを削除しました。それは関数を呼び出し、出力を"Array Called"として返すため、ArrayとObjectの間のコントラクトは何ですか?
Phani

2
Java配列もオブジェクトです。
Zds

2

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


1

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

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


0

doSomething(char [] obj)とdoSomething(Integer obj)のため、あいまいさがあります。

char []とIntegerはどちらもnullと同じ優れているため、あいまいです。


0
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にあります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.