Based on your comment, I think the right thing to do here might be to use an unchecked cast on List.class
, but first, the reason the code in the question doesn't compile is roughly:
T
of addConverter
is inferred to be List<?>
.
- The bounded wildcard in
cls
requires that its type argument be T
or a subtype of T
, but the raw type List
is a supertype of List<?>
(specified here).
- Therefore,
Class<List>
is incompatible with the inferred type of cls
which is Class<? extends List<?>>
.
So, for example, either of the following two declarations would compile with the invocations in the question:
<T> void m(Class<T> cls, Converter<? extends T> converter) {}
<T> void m(Class<? super T> cls, Converter<T> converter) {}
That of course doesn't help you out, but it illustrates the relationship between List
and List<?>
.
You might see also these two answers of mine which discuss similar situations.
So anyway, based on your comment saying that you're trying to eliminate raw types and can't change the declaration of addConverter
, what could be appropriate is to use an unchecked cast from Class<List>
to Class<List<?>>
:
@SuppressWarnings("unchecked")
static final Class<List<?>> WILD_LIST =
(Class<List<?>>) (Class<? super List<?>>) List.class;
This will let you call e.g.:
addConverter(WILD_LIST, new ProblematicConverter());
However, I'd like to point out that unchecked casting is not a general solution. It's a solution to this specific problem of converting e.g. a Class<GenericType>
to a Class<GenericType<?>>
. It's safe to do because GenericType<?>
is a more restrictive type than the raw type GenericType
and because Class
has a very limited range of things it can do with its type argument.
If you could change the declaration of addConverter
, I think I would recommend using something like Guava TypeToken
instead of Class
, because then you don't have this sort of problem.