根据 this question ,当试图在模棱两可的重载构造函数之间进行选择时,Java 将选择“最具体”的选项。在这个例子中:
public class Test{
private Test(Map map){
System.out.println("Map");
}
private Test(Object o){
System.out.println("Object");
}
public static void main(String[] args){
new Test(null);
}
}
它会打印出来
"Map"
但是,我试图弄清楚“最具体”的确切含义。我认为它的意思是“最不模棱两可”,如“可能指的是最少可能的类型”。在这种情况下,Object
可能是任何不是原始的东西,而 Map
可能只是 Map
或 ?扩展 map
。基本上,我假设无论哪个类更接近继承树的叶子,都会被选中。当一个类是另一个类的子类时,这是有效的:
public class Test{
private Test(A a){
System.out.println("A");
}
private Test(B b){
System.out.println("B");
}
public static void main(String[] args){
new Test(null);
}
}
class A{}
class B extends A{}
"B"
然后我想出了这个:
public class Test{
private Test(A a){
System.out.println("A");
}
private Test(E e){
System.out.println("E");
}
public static void main(String[] args){
new Test(null);
}
}
class A{}
class B extends A{}
class C{}
class D extends C{}
class E extends D{}
我认为它应该打印 E
,因为 E
可能只指一种已知类型,而 A
可能指两种(A
和 B
)。但它给出了一个模棱两可的引用错误。
实际上是如何选择构造函数的?我通读了the docs但坦率地说,我不能完全理解它是如何确定特异性的。我希望能准确描述为什么它不能确定 E
比 A
更具体。
最佳答案
它不是基于可转换为参数类型的类型的数量 - 由于隐式转换,它是否对一个重载有效的任何值对另一个有效。
例如,有一个来自 String
的隐式转换。至Object
,但反过来不正确,所以 String
比 Object
更具体.
同样有一个来自 B
的隐式转换至A
,但反过来不正确,所以 B
比 A
更具体.
与 A
和 E
但是,两者都不比另一个更具体 - 没有来自 A
的转换至E
,并且没有从 E
转换至A
.这就是重载解析失败的原因。
JLS的相关位其实是15.12.2.5 ,其中包括可能使您更容易理解的内容:
The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time error.
如果你有:
void foo(String x)
void foo(Object x)
foo(String)
处理的每个调用可由 foo(Object)
处理,但反之则不然。 (例如,您可以调用 foo(new Object())
,而 foo(String)
无法处理。)
关于Java:重载构造函数之间的选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38979801/