If we have a variable for the class of a generic class, like List
, what type should it be?
List<Class> c1;
or
List<Class<?>> c2;
If we have a variable for the class of a generic class, like List
, what type should it be?
List<Class> c1;
or
List<Class<?>> c2;
The second one, because the first one uses the raw type instead of generics.
i.e.
List
is raw, butList<?>
is generic, and you shouldn't mix-and-match between both raws and generics.Do you want to represent a runtime class, or a type? (The distinction being that
List<String>
andList<Integer>
are different types, but share the same runtime class).Type: Use something like a type token.
Runtime class: Since
compiles, but
does not, I'd opt for using the raw type in the type expression. There really isn't any benefit from specifying the type argument to
List
because the class does not determine it, and using a wildcard type will require weird casting to get it to the proper type, for instance:Edit: Why it doesn't compile
Lifted from the comments:
List.class
is of typeClass<List>
. SinceList<?>
andList
are different types,Class<List<?>>
andClass<List>
are unrelated types, but the right-hand type of an assignment must be a subtype of the left-hand type. ThegetClass()
case is analogous.I would not blame the JDK, they only implemented the rules laid down in the language specification itself, in particular:
(source)
(source)
(source)
... and why is it defined like that?
It's hard to give a definite answer to that, since the spec does not expand on the reasons for that definition. However, it might be because the runtime type might not be a subtype of the static type, a pathological situation that can arise by incorrect suppression of unchecked warnings (c.f heap pollution). By specifying that the return type only contains the erasure, the specification ensures that even in the presence of heap pollution, the class object returned by
getClass()
is an instance of the declared return type ofgetClass()
. It also serves as a reminder that the runtime the programmer is about to access using the reflection API only thinks in terms of erased types.since List itself is an interface here, this might be a better option.