List<?>
is a list with an unknown type. You cannot insert there because you cannot know what type you would be allowed to insert. It has a generic type (or not) but there is no way you can know it. If you get to insert something (typecasting the list first) you may be violating something so you should not.A
List<Object>
is a list where you can insert any object and when you get an item you only know (at first) that it is an object (and you already knew that).List
is only allowed to be backward compatible (I think). Before Java 5 there were no generics. Java need to allow typecast betweenList
andList<Anything>
so the legacy code may work with modern code.
Differences just List and List<Object> and List<?>
Pergunta
According erasure concept I thought that
List
and List<Object>
are indentically but I noticed that
List<String> strList = new ArrayList<String>();
List<Object> objList = strList; //error
List objList = strList; //valid construction
List<?> objList = strList; //valid construction
Solução
Outras dicas
List<?>
is generic
(wildcard
), which means that it accepts from String to anything, that's why
List<?> objList = strList; //valid construction
while List<String>
is not a subtype of List<Object>
(But String[] is in fact a subtype of Object[], that's one of the reasons why generics and arrays don't mix well). For Object
List<? extends Object> objList = strList; //valid construction
because String
extends Object
, here means anything extends to Object is accepted.
First explanation:
If you define a List of Objects, than you state, that this List can contain anything you want. (This is some additional information you provide.)
If you define a List of Strings, than this is NOT a List of anything. It is a List of Strings.
A List of Strings is not the same as a List of Objects.
Technical explanation:
Let's say you have a class like this:
class Machine<T> {
void process(T input) {
...
}
}
If you then create an instance: new Machine<String>()
, than the compiler knows, that your new object is ment to process Strings. It will fail if you want to make it process a Number, an Array or anything else.
If you create a more general machine, but calling new Machine<Object>()
, than the compiler knows, that Strings, Numbers, Arrays and any kind of stuff can be processed by that machine.
The compiler will not allow you to cast the specific String-Machine (new Machine<String>()
) to a general Object-Machine (Machine<Object>
), because this would allow you to let it process Numbers, Arrays, etc. for what it was not meant for.