difference between List and List<?> [duplicate]

主宰稳场 提交于 2019-12-22 18:27:44

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!