List <object>和List <! - ? - > </object>之间有什么区别

时间:2012-09-09 16:32:28

标签: java

以前所有你烧我的活着,我必须说我多次搜索这个问题,我仍然无法理解List&lt; Object&gt;之间的区别。和列表&lt;?&gt;

我读过的所有书都说Java中的每个类都是隐式的Object 的子类。

但是我看到here以下代码:

public static void printList(List<Object> list) {
    for (Object elem : list)
        System.out.println(elem + " ");
    System.out.println();
}

此代码错误(故意用于教育目的),根据作者的原因是:

[...]只打印一个Object实例列表;它无法打印列表&lt;整数&gt;,列表&lt; String&gt;,列表&lt; Double&gt; 等,因为它们不是List&lt; Object&gt; 的子类型

解决方案是:

public static void printList(List<?> list) {
    for (Object elem: list)
        System.out.print(elem + " ");
    System.out.println();
}

如您所见,唯一的区别是第一行:

public static void printList(List<Object> list) {
public static void printList(List<?> list) {

这就是我的问题的原因:List&lt; Object&gt;之间的区别是什么?和列表&lt;?&gt; ?

毕竟是 Object 超级类的一切与否?

如果有人可以帮我解释一下(我是Java的新手),我会很感激。

提前谢谢你。

7 个答案:

答案 0 :(得分:18)

说明:

?是一个“通配符”。您可以通过不同方式使用它:

无界通配符:

? 
带上限的

通配符:

? extends Object (or another class)

带下限的通配符

? super Object (or another class)

示例:

List <?> list;

您可以使用任何类型参数为list分配任何列表。

List<? extends Number> list;

您可以为列表分配任何具有类型参数Number(或Integer,Float,ecc)的List

List<? super Integer> list;

您可以为列表分配任何带有类型参数Integer的List,或者类型为Integer类型的类型(Number,Comparable,Serializable,Object ...)

要点:

声明

List<Object> list;

类似于

List<? super Object> list;

因为您只能为“列表”分配一个对象列表;那么你可以这样使用这个列表:

    list = new ArrayList<Object>();
    list.add(new String(""));
    list.add(new Integer(3));

答案 1 :(得分:7)

StringObject的子类型并不意味着List<String>List<Object>的子类型。如果是,则编译以下代码:

List<String> strings = new ArrayList<String>();
List<Object> objects = strings;
objects.add((Integer) 1);
strings.get(0).charAt(0); // but the Integer 1 does not have a charAt method ...

因此,List<String>不是List<Object>的子类型。

List<String>List<Object>都是List<?>的子类型。但由于List<?>是更通用的类型,因此无法知道add方法采用的类型:

List<String> strings = new ArrayList<String>();
List<?> objects = strings;
objects.add((Integer) 1); // does not compile

答案 2 :(得分:6)

主要区别之一是如何修改列表。以下效果很好

List<Object> l1;
l1.add(new Object()); // OK

而第二种情况产生编译错误。

List<?> l2;
l2.add(new Object()); // Compile error

我认为原因已在网站上多次辩论过了。简而言之,<?>表示 a (如一个特定未知类型。由于该类型不是编译时知道的,因此不允许修改列表。

答案 3 :(得分:2)

您基本上可以以类似的方式使用这两个版本。但是,有一个很大的区别。我们声明如下:

List<Object> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<String>();

现在,让我们试试下面的代码:

list1.add("");// this works fine
list2.add("");// this one issues a compile error

有人可能会问为什么这样。这是因为在List<Object>中,代码会告诉您,那里有Object或子类型,但在List<?>中,您可以拥有相同的内容,但您不知道究竟是什么。有人可以添加StringDouble,然后尝试阅读并转换为Integer。但同样,这是不可能的。

我现在可能还有其他不同之处。

答案 4 :(得分:2)

Object是String的超类,但是List&lt; Object&gt;不是List&lt; String&gt;的超类。如果是,这将是一个问题:

List<String> strings = ...
addObject(strings);
...
void addObjects(List<Object> objects) {
    objects.add(new Object());
}

现在字符串包含一个不是String的元素。

答案 5 :(得分:2)

  

此代码错误(故意用于教育目的),根据作者的原因是:

     

[...]只打印一个Object实例列表;它无法打印   列表,列表,列表等,因为它们是   不是List的子类型

这是因为参数化类型是不变,例如对于类X和Y,List<X>既不是子类型也不是List<Y>的超类型。

区别在于无界通配符类型 ?意味着该类型未知,您无法对此采取任何措施。 List<?>是类型安全的,你不能在其中放置null以外的任何元素,你不能假设它所包含的对象的类型。

List<Object>显然意味着List可以包含任何类型的对象。

答案 6 :(得分:0)

 public static void main(String args[]){

   List<? super Object> list=new ArrayList<>();
   list.add("A");//works

   List<Object> list1=new ArrayList<>();
   list1.add("B");//works

   List<?> list2=new ArrayList<>();
   list2.add("11");//compile time error;

   List<? extends Object> list4=new ArrayList<>();
   list4.add("123");//compile Time error
}

列表与LT; ? extend Object&gt; &安培;列表与LT; ? &GT;不允许添加任何内容以了解原因:enter link description here但另一方面List&lt; ?超级对象&gt;允许向List添加值,因为提供的链接中的问题不存在。