Why do I need to explicitly cast a generic call?

generics, java

Solution

For exactly the reason you stated, the type parameter could actually be a supertype of the real runtime type of the object you passed in! `T#getClass()` does not return `Class<T>`, it returns `Class<? extends T>`

Number number = Integer.valueOf(1);
List<Number> list = first(number);

When you call `n.getClass()` at runtime is going to return `Integer.class`, not `Number.class`, yet you are trying to assign the result to `List<Number>`! The compiler has no way to know what the real runtime type will be, it only knows at most that `List<? extends Number>` comes back. Forcing you to put in the cast is its way of saying "I cannot vouch for the safety of this operation, it's on your word that it's correct."

Any time it is impossible for the compiler to confirm that an operation is typesafe, it will force you to cast and thus incur an "unchecked" warning so that it has done its job of letting you know about the problem.

Problem

Let's suppose I have the following: ``` public <T extends Widget> List<T> first(T n) { return first(n.getClass()); } public <T extends Widget> List<T> first(Class<T> n) { return new ArrayList<>(); } ``` The compiler complains at line 3 with "`incompatible types; required: java.util.List<T>; found: java.util.List<capture#1 of ? extends my.app.Widget>`". Which I don't understand why. It seems reasonable to me that the type `T` could never change in either case other than a sub-type. This can be fixed via explicit casting, though I do not know why it is required. ``` public <T extends Widget> List<T> first(T n) { return (List<T>)first(n.getClass()); } public <T extends Widget> List<T> first(Class<T> n) { return new ArrayList<>(); } ``` Could this be a compiler bug? Note I am using JDK 1.7.0_15: ``` java version "1.7.0_15" Java(TM) SE Runtime Environment (build 1.7.0_15-b03) Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode) ```

Original source