Community
Participate
Working Groups
public <T extends Serializable & CharSequence> void doSomething(T t) {} public <K extends CharSequence & Serializable> void doSomething(K k) {} javac complains[*] about duplicate methods in this case where Eclipse JDT 3.7 compiles without marking the mistake. If I arrange the arguments in the same order, I get an error (as expected). Earlier versions of the [*] <T>doSomething(T) is already defined in sample.MyClass
Ironically I get the missing 'Override' marker for class A { <T extends CharSequence & Serializable> void foo(T t) {} } class B extends A { <T extends Serializable & CharSequence> void foo(T t) {} }
(In reply to comment #0) > public <T extends Serializable & CharSequence> void doSomething(T t) {} > > public <K extends CharSequence & Serializable> void doSomething(K k) {} > > javac complains[*] about duplicate methods in this case where Eclipse JDT 3.7 > compiles without marking the mistake. This is fixed in javac 7 b147. Javac no longer complains for duplicate methods, and hence eclipse behaviour is consistent with javac. I'm not too sure about the case in comment 1 though. Srikanth, what do you think?
javac 1.6 complains, but not javac 1.7.
As mentioned in comment#2, and comment#3, this appears to be a regression in javac6 which has since been fixed in JDK7. Basically per JLS3 4.6, "the erasure of a method signature s is a signature consisting of the same name as s, and the erasures of all the formal parameter types given in s" and "The erasure of a type variable (ยง4.4) is the erasure of its leftmost bound". Since the left most bounds differ, the erasures differ and ipso facto, they are not duplicates. As for comment#1, the override marker is indeed correctly diagnosed to be missing. While for erasure, we use only the left most bound, it is not as though the additional constraining types vanish from the picture. Thus K and T both describe the same intersection of behaviors and hence foo in B does override the foo in A. This modified program may be useful in understanding the nuance here: import java.io.Serializable; class A { <T extends CharSequence & Serializable> void foo(T t) { System.out.println(t.length()); } } class B extends A { @Override <T extends Serializable & CharSequence> void foo(T t) { System.out.println(t.length()); } } In A's foo, 't' per erasure is CharSequence while in B's foo 't' per erasure is Serializable. Accordingly in the code generated for A's foo there is no cast required before length() of CharSequence can be invoked, while in B's foo a cast is required and is automatically inserted by the compiler. This compiler inserted cast is guaranteed not to fail at run time, since every call site must have passed a bounds check at compile time. (Also, in general there is no need for the overriding method to have the same signature (or even signature erasure) as the method it overrides.) As eclipse behavior matches latest JDK7 behavior, resolving this as INVALID.
For the testcase in comment 1, the Override annotation doesn't appear in the editor. Filed bug 365545 to take care of it.
Verified for 3.8M4 using build I20111202-0800