Preparing for OCPJP 6 exam (that's why I'm using Java 1.6 compiler) I've noticed something unclear to me about Java Generics. Consider the following code:
class A<K extends Number> {
public <V> V useMe1(A<? super V> a) { // OK
return null;
}
public <V> V useMe2(A<? extends V> a) { // OK
return null;
}
public <V> V useMe3(A<V> a) { // ERROR, but why, since 2 above were ok
return null;
}
}
When I try to compile the code (with 1.6 compiler), I get the error:
type parameter V is not within its bound
Despite unusability of the code above, I'm wondering why does compiler think that types <? super V> and <? extends V> are matching the class type bound but <V> is not (since V is matching those both bounds).
I'm not going to modify that code, I want to understand it. The code is taken from sample OCPJP 6 exam question asking "Which line will compile?"
The third,
useMe3, fails asVis not guaranteed toextend Numbergiven the lack of bounds on its declaration<V>. And since the argument is declared asA<V>there is no scape,Vmust extendNumberand the Java language asks the programmer to explicitly state so in this case.That is in fact the easy one and perhaps is less obvious why the other two may work. By using
?in their argument type definition you are giving the chance of that bound to be compatible withextend Numbereven whenVitself is a priory not restricted by any particular bound in relation toNumber.You must notice that
extend Numberis not affectingVany longer but?whatever that is. Another way to put it, there is a unknown class that is represented by that?and mustextend Numberand on top of that for methoduseMe1, for instance, it must be a super ofVwhereVwould be determined by the code that calls that method.This is perhaps more interesting in the case of
useMe2whereVcould effectively be anything totally unrelated toNumber. Eg:In the
useMe2call above,VisFooInterfacethat has nothing to do withNumber, and the?in in this caseMyNumber.MyNumberis restricted byAtype-parameter bound to extendsNumberand by the type-parameter definition of the argument inuseMe2to extendFooInterfacebutVitself is totally unrestricted.