This question already has an answer here:
I've read alot about this, and I know that:
List<Object> listOfObject = new ArrayList<TYPE>(); // (0)
//can only work for TYPE == Object.
//if TYPE extends Object (and thus objects of type TYPE are Objects),
//this is not the same with Lists: List<Type> is not a List<Object>
Now I've read that the following is ok:
List undefinedList = new ArrayList<TYPE>(); // (1)
//works for ANY type (except for primitives)
And
List<?> wildcardList = new ArrayList<TYPE>(); // (2)
//also works for ANY type (except for primitives)
Then:
List undefinedlist = new ArrayList(); //no TYPE specified
undefinedList.add(new Integer(1)); //WORKS
undefinedList.add(new String("string")); //WORKS
However:
List<?> wildcardList = new ArrayList<TYPE>(); //TYPE specified
wildcardList.add(new TYPE(...)); //COMPILER ERROR
example:
List<?> wildcardList = new ArrayList<String>(); //TYPE specified
wildcardList.add(new String("string")); //COMPILER ERROR: The method add(capture#1-of ?) in the type List<capture#1-of ?> is not applicable for the arguments (String)
I do understand why you can't add anything to the wildcardList, since its type can be anything. However, why can you add to the undefinedList?? They seem the same & show the same behavior, given (1) and (2).
The "undefined"
List
contain list of typeObject
which is the father of all types and hence theList
is not type-safe(is interconvertible)which is why this:
well.. works!
Basically,
?
in the followingmeans some unknown (particular) type. So, it doesn't allow you add something like
String
, orInteger
to a list of some unknown type, because generics is meant to be type-safe.While, in the following
you can add anything to it because everything is an
Object
in Java. So it's type-safe.And also with the following
you are telling the compiler that you don't want to use generics there. Which means every method you invoke on
undefinedList
will be non-generic since you have decided to use the rawList
. Non-generic versions of all the containers in the collection framework were written to work forObject
(which any object in Java is).List means that this is a list of unknown type - as such you wouldnt use it at creation time (as in your example), you'd typically use it as a method parameter. Unbound wildcards are only really useful when used as parameters in methods, such as:
This could iterate of a list of (any) unknown items. In this case List items would achieve the same purpose, but client would probably get a warning.
If you had the following:
Then only a list of
Object
could be processed - not a list Strings, Integers etc. Only Objects.Take a look at Unbounded Wildcards - it explains its pretty well
The
List<?>
type is generic: whatever type you put in place of the question mark will be used in the methods of the list. So you can dolist.add(item)
and it will only allow you to put in aString
if you created aList<String>
. Type-safety first.The
List
on the other hand allows anyObject
to be put in there. So you can make aList
, put aGiraffe
in there, and later aSquid
. It does not care, and could be a source of programming errors if you expect onlyGiraffe
objects to be in there.List undefinedList
andList<?> wildcardList
are not the same, as you discovered yourself. The first is raw type and the second is unbounded wildcard.Use the unbounded wildcard if you want to use a generic type but you don’t know or care what the actual type parameter is. You cannot put anything (except null) into this list, and all you know about the element you get out of it is that they extend Object (actually
List<?>
is the same asList<? extends Object>
). Unbounded wildcards are useful, because if you would declare something naively asList<Object>
, you could not assign for exampleList<String>
to it, while you can assign aList<String>
to aList<?>
You should (almost) never have the need to use raw types, they are available only for compatibility with code written before Java 5.
List<?>
is read as a list of some unknown type . As a programmer you can not make any assumption of what type that is and you can not put anything into such a collection other than null . But you can be rest assured that your list is type safe since the compiler will guarantee type safety for you .List
is basically called raw type . That is to say that it has opted out of type safety guaranteed by the compiler . So you can put elements of any type into that List destroying its invariants . Don't code with raw types any more . They are basically supported for backward compatibility because java was already in the second decade of development when Sun brought generics to the table and a awful lot of code was written using raw types and those programs would otherwise break.