Community
Participate
Working Groups
I20040104-1600-gtk Consider the below snippet. The eclipse compiler claims that b.getOne() should only return an Object, which is consistent with javac. Inlining the call to B.getTwo produces an error... It seems that the type bound resolution depends on the calling context: inside B.getTwo the return type of getOne is resolved to be at least a Number. Outside of B, however, the resolvation is not made. Also, as soon as the type parameter is bound to a concrete type (vs. just restricted), type resolvation succeeds again, as can be seen with type C. It looks like, while stepping up the type hierarchy, the compiler does not sidestep from the superinterface clause "extends A<T>" to the formal type declaration "B<T extends Number>" to collect the type bound. ------------ snip ---------- package test1; public interface A<E>{ E getOne(); } abstract class B<T extends Number> implements A<T> { Number getTwo() { return getOne(); // succeeds } } abstract class C extends B<Integer> { } class X { void foo(A a, B b, C c){ Object o= a.getOne(); Number n1= b.getOne(); // fails Number n2= b.getTwo(); // succeeds, but inlining fails Integer i = c.getOne(); // succeeds } } ------ The error message from eclipse: "Type mismatch: cannot convert from Object to Number" Javac: test1/A.java:20: incompatible types found : java.lang.Object required: java.lang.Number Number n1= b.getOne(); ^ 1 error
What exactly do you mean by "Inlining the call to B.getTwo produces an error..." ?
[I jump in because Tom is away and we looked at this together.] If you inline the call to "b.getTwo()" (either manually, or with Refactor > Inline), the call becomes "b.getOne()" (already done in "n1= b.getOne();" in the line above). "... produces an error ... " means that the compiler marks an error here: Number n1= b.getOne(); ^^ Type mismatch: cannot convert from Object to Number We can't see why the statement "Number n1= b.getOne();" is marked as an error. The upper bound of the return type of B#getOne() is Number. Therefore, the object returned from B#getOne() must always be a Number or a subtype of Number, and the statement "Number n1= b.getOne();" should be valid.
The return type of #getTwo() is Number, which definitely matches expectation for n2. For n1, the invocation of b.getOne() is performed on raw type B. The superclass of raw type B is raw type A, which defines a method #getOne() of type: erasure of <E> --> Object (since it carries no bound). Thus the invocation of #getOne() returns an Object, which isn't compatible with Number.