Java:重载构造函数之间的选择

标签 java compiler-errors ambiguous-call

根据 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 可能指两种(AB)。但它给出了一个模棱两可的引用错误。

实际上是如何选择构造函数的?我通读了the docs但坦率地说,我不能完全理解它是如何确定特异性的。我希望能准确描述为什么它不能确定 EA 更具体。

最佳答案

它不是基于可转换为参数类型的类型的数量 - 由于隐式转换,它是否对一个重载有效的任何值对另一个有效。

例如,有一个来自 String 的隐式转换。至Object ,但反过来不正确,所以 StringObject 更具体.

同样有一个来自 B 的隐式转换至A ,但反过来不正确,所以 BA 更具体.

AE但是,两者都不比另一个更具体 - 没有来自 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/

相关文章:

java - 我得到了 javax.net.ssl.SSLPeerUnverifiedException : peer not authenticated on my JUnit test

java - 什么是用于在 JSON 对象数组中选择字段值的 Rest Assured 正确 JsonPath get() 格式

function - Haskell-使用用户输入调用所有其他功能的主要功能

c - 编译 MEX 文件时出现链接问题

c++ - 为什么此 C++ 代码仅在 Microsoft 编译器上具有模棱两可的方法调用?

java - 多线程和 putIfAbsent 的竞争条件

java - 生成 session key 时出现问题

java - 编译错误 : 'void' type not allowed here

java - 向 Mockito.any() 提供类以使 verify() 调用明确的正确语法是什么?

c++ - 模板参数不明确 : could not deduce template argument