Java泛型类型擦除方法签名问题

时间:2011-06-29 09:36:47

标签: java class generics type-erasure

给出以下假设类型层次结构:

BaseElement
  + StringElement
      + ....
      + ....
  + BooleanElement
      + ....
      + ....
  + ...

我有一个类接口:

IBaseElementService    createElementService(Class<? extends BaseElement>    element);
IBooleanElementService createElementService(Class<? extends BooleanElement> element);

这在eclipse 3.4中编译得很好,但在eclipse 3.6中不再编译,失败并出现错误:

Method ... has the same erasure createElementService(Class<T>) as another method in this type

我有点疑惑为什么这个在eclipse 3.4下编译,因为java编译器删除了这个类型。但无论如何,有没有一种优雅的方法来改变它而不重命名方法?

谢谢!

编辑:正如多人所指出的,这似乎是一个日食3.4 - 3.5的错误。 eclipse bug report(感谢denis.solonenko的链接!)

如果有人对此错误的技术细节感兴趣,请务必阅读PaŭloEbermann的帖子,thx!

3 个答案:

答案 0 :(得分:1)

重命名方法。 (但为什么你有两种方法?也许第一种方法应该是唯一的方法;它可以检查类类型并转发到BooleanElement的第二种方法)

根据当前的语言规范,您的两个方法应该编译。见here。我在Java 7中听说过这两种方法不能再存在了。不确定理由。

答案 1 :(得分:0)

您可以将通用添加到IBaseElementService

在creaseElementService中,您需要进行一些检查以返回正确的元素服务。

IBaseElementService<T>    createElementService(Class<T extends BaseElement>    elementClass) {
    if (elementClass.equals(BooleanElement.class))
        return new IBooleanElementService();
    return new IBaseElementService();
}


public class IBooleanElementService implements IBaseElementService<BooleanElement> { ... }

public class IBaseElementService implements IBaseElementService<BaseElement> { ... }

答案 2 :(得分:0)

在VM级别,方法签名也包括返回类型。因此,您的两种方法都有签名 createElementService(Class):IBooleanElementServicecreateElementService(Class):IBaseElementService。只要编译器知道要调用哪个方法,它就可以将调用放在字节码中的正确方法中。我认为这就是Eclipse 3.4所做的。

在Java语言级别上,方法仅通过名称和参数类型进行区分。您的方法在此处具有签名createElementService(Class<? extends BooleanElement>)createElementService(Class<? extends BaseElement>)。但语言规范说明了它们将被删除的泛型类型 - 它们都被删除到createElementService(Class),现在它们根本没有不同,这是不允许的。

我认为3.4编译器在这里有一个错误(即它编译的语言不是真正的Java)。