问题
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).
回答1:
List undefinedList
and List<?> 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 as List<? extends Object>
). Unbounded wildcards are useful, because if you would declare something naively as List<Object>
, you could not assign for example List<String>
to it, while you can assign a List<String>
to a List<?>
You should (almost) never have the need to use raw types, they are available only for compatibility with code written before Java 5.
回答2:
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:
public void printList(List<?> items)
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:
public void printList(List<Object> items)
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
回答3:
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.
回答4:
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 do list.add(item)
and it will only allow you to put in a String
if you created a List<String>
. Type-safety first.
List<String> list = new List<String>();
list.add("A"); // <-- Correct
list.add((Integer)10); // <-- Error, it is a List of Strings
The List
on the other hand allows any Object
to be put in there. So you can make a List
, put a Giraffe
in there, and later a Squid
. It does not care, and could be a source of programming errors if you expect only Giraffe
objects to be in there.
List list = new List();
list.add("A"); // <-- Allowed
list.add((Integer)10); // <-- Also allowed,
// but now the list contains not only strings
回答5:
The "undefined" List
contain list of type Object
which is the father of all types and hence the List
is not type-safe(is interconvertible)
which is why this:
List undefinedlist = new ArrayList<TYPE>(); //IS LIST OF OBJECTS
undefinedList.add(new Integer(1)); //WORKS
undefinedList.add(new String("string")); //WORKS
well.. works!
回答6:
Basically, ?
in the following
List<?> wildcardList = new ArrayList<TYPE>();
means some unknown (particular) type. So, it doesn't allow you add something like String
, or Integer
to a list of some unknown type, because generics is meant to be type-safe.
While, in the following
List<Object> listOfObject = new ArrayList<TYPE>();
you can add anything to it because everything is an Object
in Java. So it's type-safe.
And also with the following
List undefinedList = new ArrayList<TYPE>();
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 raw List
. Non-generic versions of all the containers in the collection framework were written to work for Object
(which any object in Java is).
来源:https://stackoverflow.com/questions/14983489/difference-between-list-and-list