This question already has an answer here:
I did not get this code to compile either way:
List<List> a = new ArrayList();
List<List<?>> b = new ArrayList();
a = b; // incompatible types
b = a; // incompatible types
It seems that java does not consider List
and List<?>
to be the same type when it comes to generics.
Why is that? And is there some nice way out?
Context
There is a library function with following signature: public <T> Set<Class<? extends T>> getSubTypesOf(final Class<T> type)
. This works fine for simple types passed as argument but in case of generics the result is not parametrized with wildcard causing javac to complain about raw type. I would like to propagate the result to the rest of my application as Set<Class<? extends GenericTypeHere<?>>>
but simple cast does not work as I expect.
EDIT: Solution
Thanks for the answers, here is how I get it working in the end:
@SuppressWarnings({"rawtypes", "unchecked"})
private static Set<Class<? extends GenericTypeHere<?>>> factoryTypes() {
return (Set) new Reflections("...").getSubTypesOf(GenericTypeHere.class);
}
Okay, so this is due to a subtle semantic difference.
This is the raw type of
List
, which equates toT
being of typeObject
. So it's the same as saying:Now, the Compiler knows for a fact, that whatever happens, this is a subclass of type
Object
. And if you do..It will work fine! This is because
Object
is the same or it is some derivation of the type.This is literally a list of unknown (Java Docs). We don't even know that the subclass of the things in here are of type
Object
. In fact, the?
type is an unknown type all on its own. It has nothing to do withObject
! This is why when you try and do..You get a compile time error!
works
Set<Class<? extends GenericTypeHere<?>>>
would imply
Set<Class<YourClass extends AnotherClass<YourClass>>>
as mentioned in the above wildcard answerWhat stops you from using
Set<Class<YourClass extends AnotherClass>>
to propagate throughout your app?