我偶然发现了一个我以前从未见过的有趣错误,无法解释为什么
考虑以下课程
public class Sandbox<A,B> {
public void put(B b) {
}
public void put(A a) {
}
}
我的眼睛看起来不错。所以我编译它然后得到这个
name clash: put(B) and put(A) have the same erasure
咦?两种不同的泛型类型如何具有相同的签名?完全独立!
我可能遗漏了一些完全基本的东西,但我之前没遇到过这个问题。我通过调用方法putA
和putB
来帮助修复问题,但我真的很好奇为什么这个错误发生在第一位。
有人会介意解释吗?
答案 0 :(得分:17)
逻辑上,请考虑以下代码:
SandBox<String, String> sandBox = new SandBox<String, String>();
sandBox.put("foo"); // which put is invoked?
(虽然我应该承认,可以生成产生类似情况的完全有效的代码 - 然后选择“随机”方法。)
在形式上,我认为this section of the JLS是相关的。两个版本的put都有相同的参数类型 - 如果我正确读取该部分。
答案 1 :(得分:3)
Java中的泛型只能在代码级别使用,而不能在运行时使用。
因此,当编译器翻译您的源代码时,您为A和B指定的类型将被“擦除”。这意味着两种类型都设置为java.lang.Object
。
所以你最终得到两个相同的方法签名。
答案 2 :(得分:1)
两种不同的泛型类型如何 有相同的签名?那里 完全分开!
Java泛型基于type erasure。这意味着您的代码基本上编译为:
public class Sandbox{
public void put(Object b) {
}
public void put(Object a) {
}
}
答案 3 :(得分:1)
咦?两种不同的泛型类型如何具有相同的签名?完全独立!
问题的根源似乎是您没有很好地掌握Java术语。
编译器不告诉您两个泛型类型具有相同的签名:
类型(通用或其他)在正式意义上没有签名。方法有签名。
A
和B
不是通用类型。它们是类型参数。
编译器告诉您具有相同签名的内容为put(A)
和put(B)
。这些是方法,而不是类型。
修改强>
好的......所以你做了解术语。
如果您使用的技术术语不正确,请不要感到惊讶:
但我最担心的情况(以及我花时间回答你的问题的真正原因!! )就是当一些可怜的混淆Java新手做谷歌搜索时,发现你的SO问题充满了草率的术语,并且更加困惑。