igrek51
igrek51

Reputation: 336

Java generic type parameter not within its bound

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?"

Upvotes: 3

Views: 1391

Answers (1)

Valentin Ruano
Valentin Ruano

Reputation: 2809

The third, useMe3, fails as V is not guaranteed to extend Number given the lack of bounds on its declaration <V>. And since the argument is declared as A<V> there is no scape, V must extend Number and 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 with extend Number even when V itself is a priory not restricted by any particular bound in relation to Number.

You must notice that extend Number is not affecting V any longer but ? whatever that is. Another way to put it, there is a unknown class that is represented by that ? and must extend Number and on top of that for method useMe1, for instance, it must be a super of V where V would be determined by the code that calls that method.

This is perhaps more interesting in the case of useMe2 where V could effectively be anything totally unrelated to Number. Eg:

interface FooInterface { ... }
class MyNumber extends Number implements FooInterface { ... }

A<?> subject = ...;
A<MyNumber> param = ...; 
FooInterface foo = subject.useMe2(param);

In the useMe2 call above, V is FooInterface that has nothing to do with Number, and the ? in in this case MyNumber. MyNumber is restricted by A type-parameter bound to extends Number and by the type-parameter definition of the argument in useMe2 to extend FooInterface but V itself is totally unrestricted.

Upvotes: 1

Related Questions