简体   繁体   中英

Java Generics Type Erasure Method Signature Problem

Given the following hypothetical type hierarchy:

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

I have a class interface in the form:

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:

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. 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 bug report (Thanks denis.solonenko for the link!)

If someone is interested about technical details of this bug, make sure to read the post from Paŭlo Ebermann, thx!

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)

By current language spec, your two methods should compile. see here . I heard in Java 7 such 2 methods cannot coexist anymore. Not sure about the rationale.

You can add a generic to IBaseElementService .

Inside the creaseElementService you need to do some checking to return the right elementservice.

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. Thus, your two methods have the signature createElementService(Class):IBooleanElementService and createElementService(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.

On the Java language level, a method is differentiated only by name and argument types. Here your methods have the signatures createElementService(Class<? extends BooleanElement>) and 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.

I think the 3.4 compiler had a bug here (ie it compiled a language which was not really Java).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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