两个单独的泛型类型具有相同的擦除?

时间:2010-08-21 23:41:02

标签: java generics

我偶然发现了一个我以前从未见过的有趣错误,无法解释为什么

考虑以下课程

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

咦?两种不同的泛型类型如何具有相同的签名?完全独立!

我可能遗漏了一些完全基本的东西,但我之前没遇到过这个问题。我通过调用方法putAputB来帮助修复问题,但我真的很好奇为什么这个错误发生在第一位。

有人会介意解释吗?

4 个答案:

答案 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术语。

编译器告诉您两个泛型类型具有相同的签名:

  • 类型(通用或其他)在正式意义上没有签名。方法有签名。

  • AB不是通用类型。它们是类型参数。

  • 编译器告诉您具有相同签名的内容为put(A)put(B)。这些是方法,而不是类型。

修改

好的......所以你了解术语。

如果您使用的技术术语不正确,请不要感到惊讶:

  • 有些人误解了你的问题(和答案),
  • 有些人会因为错误地使用术语而打电话给你,
  • 有些人打折你的要求/说是不知情的。

但我最担心的情况(以及我花时间回答你的问题的真正原因!! )就是当一些可怜的混淆Java新手做谷歌搜索时,发现你的SO问题充满了草率的术语,并且更加困惑