代码之家  ›  专栏  ›  技术社区  ›  Dónal

列表<?>或List<Object>

  •  17
  • Dónal  · 技术社区  · 13 年前

    我有一个方法,它的参数应该是“任何东西的列表”。此方法不会修改列表的内容。将此方法定义为

    void foo(List<?> list) {
    }
    

    void foo(List<Object> list) {
    }
    

    到底有什么区别?

    6 回复  |  直到 8 年前
        1
  •  16
  •   aioobe    13 年前

    简短回答,使用 List<?> 会让你接受 List<String> 使用时 List<Object> 不会。

    这在官方的泛型测试中讨论过, here here .

    […]这里有一个使用泛型(和新的for循环语法)编写它的天真尝试:

       void printCollection(Collection<Object> c) {
           for (Object e : c) {
               System.out.println(e);
           }
       }
    

    问题是,这个新版本远不如旧版本有用。旧代码可以用任何类型的集合作为参数调用,而新代码只接受 Collection<Object> ,正如我们刚才所展示的,这并不是所有类型的集合的超类型!
    那么,什么是各种收藏的超级类型呢?写着 Collection<?> (发音为“collection of unknown”),即元素类型与任何内容匹配的集合。 它被称为通配符类型有明显的原因。我们可以写:

       void printCollection(Collection<?> c) {
           for (Object e : c) {
               System.out.println(e);
           }
       }
    

    现在,我们可以称之为任何类型的收藏。

        2
  •  1
  •   Buhake Sindi Tesnep    13 年前

    这个 List<Object> 具有参数化类型 Object 这意味着你可以 全部的 列表中的对象。

    然而, List<?> 意思是说 未知数清单 . 只要你不打算在列表中添加任何内容,它基本上与 列表<对象> 但你必须担心以下情况:

    List<?> unknownList = new ArrayList<String>();
    unknownList.add(new Object()); //Compilation error.
    

    这个 ? (在本例中)意味着您只能添加 String 或是 字符串 .

    如果你要遍历列表并检索值, 列表<?> 列表<对象> 基本上是一样的。

    更多信息 here .

        3
  •  1
  •   Dónal    8 年前

    二者截然不同

    void foo(List<?> list)
    

    意思是你想要一个列表,但是你没有指定它是什么

    void foo(List<Object> list)
    

    表示您希望传递的列表是一个对象列表,因此如果您尝试传递一个列表,它将不会被接受(与第一个声明相反)

    一个常见的错误是假设 List<String> 是一个 子类型 可以说 List<Object> 即使String是一个suptype对象,情况也并非如此。

        4
  •  0
  •   DerMike Vladimír Schäfer    13 年前

    如果不想修改列表,则 List<?> 更合适。

    这样你就可以通过。 List<String> List<BigInteger> 你的方法。

        5
  •  0
  •   jqno    13 年前

    你需要 void foo(List<?> list) ,否则您将无法传入 List<String> .

    如果你用 void foo(List<Object> list) ,那你就只能进去了 List<Object> .

    这是因为,在Java中,泛型不是 covariant : 列表<字符串> 不是的子类型 列表<对象> .

        6
  •  0
  •   Dónal    8 年前

    本教程的第3节和第4节应回答您的问题:

    http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

    引用教程:

    一般来说,如果Foo是Bar的子类型(子类或子接口),G是某种泛型类型声明,则G<Foo>不是G<Bar>的子类型。。。。

    ... Collection<Object>,正如我们刚刚演示的,它不是所有类型集合的超类型! 那么,什么是各种收藏的超级类型呢?它的书面收藏;?>(发音为未知的集合),即元素类型与任何内容匹配的集合。

    然而,在 严格的 假设foo方法将不修改集合,则实现上应该没有差异。