Here\'s my issue: given these classes
class A {}
class B extends A {}
This code compiles:
List
Damn good question, and I don't know the answer, but here's a work around:
List<Class<? extends A>> numbers = new ArrayList<Class<? extends A>>(Arrays.asList(B.class));
Arrays.asList(B.class);
is generified as
List<Class<B>> numbers = Arrays.asList(B.class);
Since it has only 1 attribute of type T that match the parameterized type (in this case, B.class).
This is a problem of Covariance/Contravariance in Generics. The following SO question should help you understand and solve the problem:
Demonstrate covariance and contravariance in Java?
How would contravariance be used in Java generics?
This will compile:
List<Class<? extends A>> numbers = Arrays.<Class<? extends A>>asList(B.class);
Just to add, we can rewrite the code as below
List<Class<? extends A>> asListA = Arrays.asList(B.class, A.class);
List<Class<B>> asListB = Arrays.asList(B.class);
List<Class<? extends A>> numbers = asListA;
List<Class<? extends A>> numbers2 = asListB; // it will fail here
And @Inerdia explained the details already.
In the first example, the inferred type of the Arrays.asList() call is List<Class<? extends A>>, which is obviously assignable to a variable of the same type.
In the second example, the type of the right side is List<Class<B>>. While Class<B> is assignable to Class<? extends A>, List<Class<B>> is not assignable to List<Class<? extends A>>. It would be assignable to List<? extends Class<? extends A>>.
The reason for this is the same one as why a List<B> isn't assignable to List<A>. If it was, it would make the following (not-typesafe) code possible:
List<Class<B>> bb = new ArrayList<B>();
List<Class<? extends A>> aa = bb;
aa.add(A.class);