3

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!

Patrick
  • 809
  • 3
  • 9
  • 21
  • A similar question with the answer: http://stackoverflow.com/questions/1998544/method-has-the-same-erasure-as-another-method-in-type – salman.mirghasemi Jun 29 '11 at 09:41
  • It is really strange that eclipse 3.4 compiles this cade! – AlexR Jun 29 '11 at 09:41
  • @salman.mirghasemi, the referenced question is not similar. @Patrick understand why this code does not work and asks how is it possible that eclipse 3.4 compiles it and how to modify the code. The person that asked question that your mentioned did not understand erasures at all. – AlexR Jun 29 '11 at 09:45
  • 1
    Can be related to this bug report https://bugs.eclipse.org/bugs/show_bug.cgi?id=317719 – denis.solonenko Jun 29 '11 at 09:47
  • If Eclipse 3.4 compiles it, it means that there is a bug and it is fixed in Eclipse 3.6. – salman.mirghasemi Jun 29 '11 at 09:49
  • It's not a bug, it's a feature. – irreputable Jun 29 '11 at 09:53
  • I'm just wondering why you could not just do: IBaseElementService createElementService(BaseElement element); IBooleanElementService createElementService(BooleanElement element); Wihtout additional context, it looks like overkill to use generics here. – maasg Jun 29 '11 at 10:45
  • I 'm using Eclipse 3.5 .. and the comipler gave me the same error... – success_anil Jun 29 '11 at 11:30

3 Answers3

1

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.

Community
  • 1
  • 1
irreputable
  • 44,725
  • 9
  • 65
  • 93
0

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> { ... }
Dorus
  • 7,276
  • 1
  • 30
  • 36
  • I thought about this possibility but preferred to rename the methods instead of using reflection mechanisms. Thanks anyways! – Patrick Jun 30 '11 at 07:16
  • True, I should have mentioned that if there are significant differences between both interfaces, renaming is the way to go. This solution works best if both interfaces are (almost) identical. – Dorus Jun 30 '11 at 08:15
0

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 (i.e. it compiled a language which was not really Java).

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
  • Compiler should ignore the return type when it chooses among various overloaded methods. Return type is not a part of signature because caller may ignore the return value, e.g. call method int foo(int i) as foo(5). So your comment is interesting but seems to be not exact... Although I do not have better explanation... – AlexR Jun 29 '11 at 13:01
  • @AlexR: Eclipse 3.4 was not choosing by the return type, but by the type parameter of the argument - the return type was only used for the VM to distinguish. But as you are saying (and I said), this would be wrong here. – Paŭlo Ebermann Jun 29 '11 at 13:11