The main difference lies in the (self-)documentation of the code to the reader. A variable declared as Class<?>
says: “the actual type represented by this Class
instance is unknown or not representable at compile-time and I know that”. In contrast the type Class
says: “I’m not using Generics here”, perhaps, because you don’t know that Class
is generic, or you are a bit sloppy, didn’t understand the difference between Class<?>
and Class
, or this is very old pre-Generics code.
This has consequences for the code. E.g.
Class<?> unknownType=Object.class;
Class<String> string=unknownType;
produces a compile-time error as you are assigning an explicitly unknown type to a variable declaring a known type.
In contrast
Class nonGenericType=Object.class;
Class<String> string=nonGenericType;
will only produce a (suppressible) warning as you are performing a non-generic, aka unchecked, operation.
Regarding what you can do with a Class
object, besides assignments, there is no difference, as, when you use it to create a new instance, the compile-time type of the returned reference will be the most abstract type there is, java.lang.Object
, in both cases. Had Class
methods receiving arguments related to the type parameter, a difference showed up as you can’t invoke such methods for an unknown type, Class<?>
(it would be the same as trying to insert an element into a List<?>
) while you could invoke such a method unchecked on a raw Class
instance. But since there are no such methods, there’s no difference in functionality between Class<?>
and Class
.
Still, you should always use Class<?>
to be sure that no accidental unchecked operations, like the assignment shown above, happen. If using Class
doesn’t produce compiler warnings, you should check how to (re-)enable them. If the compiler silently ignores raw types or unchecked operations, there might be other problems, with other types than Class
, hiding somewhere.