views:

283

answers:

2

I don't understand why the following code generates a warning.

interface Generic<T> {
}

interface A {
}

class B {
    Generic<A> c;

    <T extends A> B(Generic<T> a) {
     c = (Generic<A>) a; //warning here
    }

}

//Unchecked cast from Generic<T> to Generic<A>

In class B i'm only interested in using instances of Generic that are of type A. This warning suggests that I need to store the Generic argument as a T instead of A.

But this means I would have to declare B generic also, which seems to make things more complicated than they need to be.

+5  A: 

This is not down-casting, since Java generics are invariant: Generic<T> is not a subtype of Generic<A> even though T is a subtype of A. If you only need Generic methods that return A, you can use wildcard Generic<? extends A> in B constructor and in the field that stores the reference.

Yardena
+5  A: 

Because a Generic<T> isn't a subtype of Generic<A> even if T is a subtype of A.

To illustrate this, consider String instance of Object:

List<String> listOfStrings = new ArrayList<String>();
List<Object> listOfObjects = (List<Object>)listOfStrings; // invalid
listOfObjects.add(new Date());
// now listOfStrings contain a date!

The compiler doesn't allow that cast, because it may cause the corruption of the original list. The JVM does not enforce generic bounds requirements at runtime.

The solution here is to declare the field c type as 'Generic`.

notnoop
classic example of the perils of Generics in java
Peter Recore