次のコード スニペットがあります。
public static void foo(Object x) {
System.out.println("Obj");
}
public static void foo(String x) {
System.out.println("Str");
}
私が電話した場合foo(null)
、なぜあいまいさがないのですか?foo(String x)
プログラムが代わりに呼び出すのはなぜfoo(Object x)
ですか?
次のコード スニペットがあります。
public static void foo(Object x) {
System.out.println("Obj");
}
public static void foo(String x) {
System.out.println("Str");
}
私が電話した場合foo(null)
、なぜあいまいさがないのですか?foo(String x)
プログラムが代わりに呼び出すのはなぜfoo(Object x)
ですか?
プログラムが
foo(String x)
代わりに呼び出す理由foo(Object x)
これは、String
class が から拡張されているObject
ため、 により固有であるためObject
です。したがって、コンパイラはそのメソッドを呼び出すことを決定します。Compiler は常に、呼び出す最も具体的なメソッドを選択することに注意してください。JLSのセクション15.12.5を参照してください
複数のメンバー メソッドがアクセス可能で、メソッド呼び出しに適用できる場合は、ランタイム メソッド ディスパッチの記述子を提供するために 1 つを選択する必要があります。Java プログラミング言語では、最も具体的な方法が選択されるという規則が使用されます。
非公式の直観は、最初のメソッドによって処理された呼び出しが、コンパイル時の型エラーなしで別のメソッドに渡される場合、あるメソッドが別のメソッドよりも具体的であるということです。
String
ただし、パラメータ - 、およびを持つ 2 つのメソッドがある場合、コンパイラは非共変型であるため、どちらがより具体的であるかを判断できないため、エラーInteger
が発生します。ambiguity
null
の型null
は、定義上、他のすべての参照型のサブタイプです。JLS 4.1 の引用:
null 参照は、常に任意の参照型への拡大参照変換を受けることができます。
呼び出しに含まれるメソッド シグネチャの解決は、互換性のあるすべてのシグネチャのセットの中で最も具体的なシグネチャの原則に従います。(JLS 15.12.2.5. 最も具体的な方法の選択)。
まとめると、これはString
、例でオーバーロードが選択されていることを意味します。
最も具体的なメソッドを呼び出しています。
String は Object のサブクラスであるため、String は Object よりも「より具体的」です。
引数が両方のパラメーターに対して有効な 2 つのメソッドから選択する場合、コンパイラーは常に最も具体的なパラメーターを一致として選択します。この場合、はおよびnull
として扱えるリテラルです。はより具体的であり、のサブクラスであるため、コンパイラはそれを使用します。Object
String
String
Object