简体   繁体   English

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

[英]Java Generics Type Erasure Method Signature Problem

Given the following hypothetical type hierarchy:给定以下假设的类型层次结构:

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

I have a class interface in the form:我有一个 class 接口,格式如下:

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

This compiles well in eclipse 3.4 but not anymore with eclipse 3.6, failing with the error:这在 eclipse 3.4 中编译得很好,但在 eclipse 3.6 中不再编译,失败并出现错误:

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

I'm a little puzzled why this compiles under eclipse 3.4 since the type is removed by the java compiler.我有点困惑为什么它在 eclipse 3.4 下编译,因为 java 编译器删除了该类型。 But anyways, is there an elegant way to change this without renaming the methods?但无论如何,有没有一种优雅的方法可以在不重命名方法的情况下改变它?

Thanks!谢谢!

EDIT : As it was pointed out by multiple people, this seems to be an eclipse 3.4 - 3.5 bug.编辑:正如多人指出的那样,这似乎是一个 eclipse 3.4 - 3.5 错误。 eclipse bug report (Thanks denis.solonenko for the link!) eclipse 错误报告(感谢 denis.solonenko 提供链接!)

If someone is interested about technical details of this bug, make sure to read the post from Paŭlo Ebermann, thx!如果有人对此错误的技术细节感兴趣,请务必阅读 Paŭlo Ebermann 的帖子,谢谢!

Renamed the methods.重命名了方法。 (but why do you have two methods? maybe the 1st one should be the only public one; it can check the class type and forward to the 2nd method for BooleanElement) (但是为什么你有两种方法?也许第一种应该是唯一的公共方法;它可以检查 class 类型并转发到 BooleanElement 的第二种方法)

By current language spec, your two methods should compile.根据当前的语言规范,您的两种方法应该可以编译。 see here .这里 I heard in Java 7 such 2 methods cannot coexist anymore.我听说在 Java 7 这样的 2 方法不能再共存了。 Not sure about the rationale.不确定其中的原理。

You can add a generic to IBaseElementService .您可以向IBaseElementService添加泛型。

Inside the creaseElementService you need to do some checking to return the right elementservice.在 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> { ... }

On the VM level, methods signatures include the return type as well.在 VM 级别上,方法签名也包括返回类型。 Thus, your two methods have the signature createElementService(Class):IBooleanElementService and createElementService(Class):IBaseElementService .因此,您的两个方法具有签名createElementService(Class):IBooleanElementServicecreateElementService(Class):IBaseElementService As long as the compiler knows which method to call, it can put the call to the right method in the bytecode.只要编译器知道调用哪个方法,它就可以将调用放到字节码中正确的方法。 I think this is what Eclipse 3.4 did.我认为这就是 Eclipse 3.4 所做的。

On the Java language level, a method is differentiated only by name and argument types.在 Java 语言级别上,方法仅通过名称和参数类型来区分。 Here your methods have the signatures createElementService(Class<? extends BooleanElement>) and createElementService(Class<? extends BaseElement>) .在这里,您的方法具有签名createElementService(Class<? extends BooleanElement>)createElementService(Class<? extends BaseElement>) But the language specification says about generic types that they will be erased - they both get erased to createElementService(Class) , and now they are not different at all, which is not permitted.但是语言规范说它们将被删除的泛型类型 - 它们都被删除到createElementService(Class) ,现在它们根本没有什么不同,这是不允许的。

I think the 3.4 compiler had a bug here (ie it compiled a language which was not really Java).我认为 3.4 编译器在这里有一个错误(即它编译的语言不是真正的 Java)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM