List<List<?>> and List<List> are incompatible types in java [duplicate]
Asked Answered
P

2

9

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);
}
Pneumato answered 14/3, 2015 at 23:31 Comment(3)
can you give example code to show how you're calling this?Merwyn
Unfortunately, when a raw type is used as a generic type parameter, the specification becomes pretty vague. There is no conversion defined between List<List> and List<List<?>>. I don't think we know enough about the context here to say if a cast is appropriate but I showed how to do it in the Q&A I linked to.Amyloid
@Radiodef, that explain it perfectly.Candelabra
B
2

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!

Brighten answered 14/3, 2015 at 23:43 Comment(3)
Saying List is not the same as saying List<Object> -- but you're not the first person on this page to make that claim. Where does this misconception come from? I find it very strange.Papyrus
The subset of semantics shared between List and List<Object> is unrelated to the compilation error, which has to do with a lack of inclusion of raw types in the specification for generic subtyping.Amyloid
This does not really answer the questionBullbat
H
-2
    List<? extends List> a = new ArrayList();
    List<? extends List<?>> b = new ArrayList();
    a = b;

works

Set<Class<? extends GenericTypeHere<?>>>

would imply Set<Class<YourClass extends AnotherClass<YourClass>>> as mentioned in the above wildcard answer

What stops you from using

Set<Class<YourClass extends AnotherClass>> to propagate throughout your app?

Hardworking answered 14/3, 2015 at 23:35 Comment(4)
This is a comment, but it seems to work in IDEOne, however if you take OP's unedited code, you'll find that it does not!Brighten
No it doesnt. ArrayList<List<?>> x = new ArrayList<List>(); This is an error.Merwyn
That's not equivalent.ArrayList<List> x = new ArrayList<List<?>>(); worksHardworking
a=b works but not b=a if you read the question, you'll see that what the OP is after is really b=a.Merwyn

© 2022 - 2024 — McMap. All rights reserved.