Search code examples
javagenericscastingraw-typesunbounded-wildcard

List<List<?>> and List<List> are incompatible types in java


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);
}

Solution

  • Okay, so this is due to a subtle semantic difference.

    List
    

    This is the raw type of List, which equates to T being of type Object. So it's the same as saying:

    List<Object>
    

    Now, the Compiler knows for a fact, that whatever happens, this is a subclass of type Object. And if you do..

    List myList = new ArrayList();
    myList.add(new Object());
    

    It will work fine! This is because Object is the same or it is some derivation of the type.

    List<?>
    

    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 with Object! This is why when you try and do..

    List<?> myList = new ArrayList<?>();
    myList.add(new Object());
    

    You get a compile time error!