在 Java 中调用模糊重载的构造函数
我刚刚看到 这个 C# 问题 并想知道,如果Java 中也可能发生类似的事情。它可以,因为
class A<T> {
A(Integer o) {...}
A(T o) {...}
}
调用
new A<Integer>(43);
不明确,我看不出如何解决它。有吗?
I just saw this C# question and wondered, if something similar could happen in Java. It can, with
class A<T> {
A(Integer o) {...}
A(T o) {...}
}
the call
new A<Integer>(43);
is ambiguous and I see no way how to resolve it. Is there any?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以在构造过程中删除泛型(并抑制警告):
或者,不太优选使用反射(您再次必须抑制警告)
You can drop the generics during construction (and suppress a warning):
or, less preferably use reflection (where again you'd have to suppress warnings)
是的,参数化类型的成员 JLS3#4.5 .2 可能会导致普通类声明中排除的冲突(#8.4.8)。很容易想出很多这样的例子。
在 Java 中,示例中的两个构造函数都没有比另一个更具体,因为
T
和Integer
之间没有子类型关系。另请参阅引用与泛型不明确如果方法重载会产生这种情况为了避免歧义,我们通常可以选择使用不同的方法名称。但构造函数不能重命名。
更多诡辩:
如果
,那么T
确实是Integer
的子类型,那么第二个构造函数比第一个,第二个将被选择。实际上 javac 不允许这两个构造函数共存。当前的 Java 语言规范中没有任何内容禁止它们,但字节码中的限制迫使 javac 禁止它们。请参阅 Java 中的类型擦除和重载:为什么会这样?
还有一点:如果
,因为Integer
是final
,所以T只能是Integer
,因此Integer
也必须是T
的子类型,因此第二个构造函数不是也比第一个构造函数更具体吗?不。在子类型化关系中不考虑
final
。实际上有一天可以从Integer
中删除final
,Java 甚至规定删除final
不会破坏二进制兼容性。Yes, members of a parameterized type JLS3#4.5.2 can end up in conflicts that are precluded in a normal class declaration(#8.4.8). It's pretty easy to come up with many examples of this kind.
And in Java, neither constructor in your example is more specific than the other, because there is no subtyping relation between
T
andInteger
. see also Reference is ambiguous with genericsIf method overloading creates this kind of ambiguity, we can usually choose to use distinct method names. But constructors cannot be renamed.
More sophistries:
If
<T extends Integer>
, then indeedT
is a subtype ofInteger
, then the 2nd constructor is more specific than the 1st one, and the 2nd one would be chosen.Actually javac wouldn't allow these two constructors to co-exist. There is nothing in the current Java language specification that forbids them, but a limitation in the bytecode forces javac to forbid them. see Type Erasure and Overloading in Java: Why does this work?
Another point: If
<T extends Integer>
, sinceInteger
isfinal
, T can only beInteger
, soInteger
must also be a subtype ofT
, therefore isn't the 2nd constructor also more specific than the 1st?No.
final
isn't considered in subtyping relations. It is actually possible to dropfinal
fromInteger
one day, and Java even specifies that removingfinal
does not break binary compatibility.事实上,它是不明确的,因此如果您尝试 new A(new Integer(0)) 则无法编译。
Indeed, it is ambiguous, and so doesn't compile if you try
new A<Integer>(new Integer(0))
.