在Java中调用歧义重载的构造函数



我刚刚看到这个c#问题,想知道Java中是否会发生类似的事情。可以,用

class A<T> {
    A(Integer o) {...}
    A(T o) {...}
}

调用

new A<Integer>(43);

是模糊的,我看不出如何解决它。有吗?

您可以在构造期间删除泛型(并抑制警告):

A<Integer> a = new A(42);

或者,不太理想地使用反射(在这种情况下,您必须再次抑制警告)

Constructor<A> c = A.class.getDeclaredConstructor(Integer.class);
A<Integer> a = c.newInstance(42);

是的,参数化类型JLS3#4.5.2的成员可能会发生冲突,而这种冲突在正常的类声明(#8.4.8)中是不会发生的。这类例子很容易举出。

在Java中,你的例子中的构造函数没有一个比另一个更具体,因为TInteger之间没有子类型关系。参见Reference与泛型有歧义

如果方法重载造成了这种歧义,通常可以选择使用不同的方法名。但是构造函数不能重命名。


更多的诡辩:

如果<T extends Integer>,则T确实是Integer的子类型,则第二个构造函数比第一个构造函数更具体,将选择第二个构造函数。

实际上javac不允许这两个构造函数共存。当前Java语言规范中没有禁止它们,但是字节码中的限制迫使javac禁止它们。参见Java中的类型擦除和重载:为什么会这样?

另一点:如果<T extends Integer>,因为Integerfinal,所以T只能是Integer,所以Integer也必须是T的子类型,因此第二个构造函数不是也比第一个构造函数更具体吗?

。在子类型关系中不考虑final。实际上有一天从Integer中删除final是可能的,Java甚至指定删除final不会破坏二进制兼容性。

实际上,它是不明确的,因此如果您尝试new A<Integer>(new Integer(0)),则无法编译。

相关内容

  • 没有找到相关文章

最新更新