Eclipse 3.4.Java 编译器级别 1.6JRE IBM 1.6
我们有一个无法更改形式的库类。
import java.util.Hashtable;
public class A extends Hashtable {
...
}
我们已经构建了一个实用程序类来提供对 A 的轻松访问。
public class B {
private A a;
public B() {
this.a = new A();
}
public B(final A props) {
this.a = props;
}
public B(final Map<String, String> props) {
this();
for (String key : props.keySet()) {
add(key, props.get(key));
}
}
@SuppressWarnings("unchecked")
public B add(final String name, final Object value) {
a.put(name, value);
return this;
}
}
当我们尝试从另一个类调用其中一个构造函数时,就会出现问题。
public class C {
public void stuff() {
A a = new A();
B b = new B(a);//Error in javac
}
}
Eclipse编译它没有错误,当它通过ant javac和jenkins编译时,编译器会给出如下错误。
reference to B is ambiguous, both method B(com.foo.A) in com.bar.B and method B(java.util.Map<java.lang.String,java.lang.String>) in com.bar.B match
[javac] B b = new B(a);
这个错误应该发生在javac中吗?在我看来,日食在选择更具体的方法方面是正确的。
由于 HashTable 实现了 Map,因此存在歧义。H他的答案包含一些愚蠢的见解:
在 Java 中调用不明确的重载构造函数
问题是一个构造函数接受原始哈希表,而另一个构造函数接受参数化 Map。这两个构造函数都适用,但是在这种情况下消除歧义逻辑不起作用,因为根据 Java 语言规范 - 只有当构造函数的参数是另一个参数的(严格)子类型时,构造函数才会比另一个构造函数更具体。在此阶段不允许未经检查的子类型,因此存在歧义。
随着类 A 的扩展,Hashtable 本身实现了 Map 接口,所以你可以说类 A 获得了 Map 的属性,它也变成了 Map。
当您有public B(final A props)
和public B(final Map<String, String> props)
时这就像您在两个构造函数中都有一个 map 参数一样。
这就是为什么它给你歧义。