List <Object>和List <?>之间有什么区别

Ald*_*nik 29 java

以前你把我烧死了,我必须说我多次搜索这个问题,我仍然无法理解List <Object>和List <?>之间的区别

我读过的所有书都说在Java中,每个类都隐含着Object的子类.

但是我在这里看到了以下代码:

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

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

[...]只打印一个Object实例列表; 它不能打印List <Integer>,List <String>,List <Double>等,因为它们不是List <Object>的子类型

解决方案是:

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

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

public static void printList(List<Object> list) {
public static void printList(List<?> list) {
Run Code Online (Sandbox Code Playgroud)

这就是我的问题的原因:List <Object>和List <?>之间有什么区别?

毕竟是对象超类的全部与否?

如果有人可以帮我一个简单的解释(我是Java的新手),我将不胜感激.

先感谢您.

Rob*_*tti 19

说明:

?是一个"通配符".您可以通过不同方式使用它:

无界通配符:

? 
Run Code Online (Sandbox Code Playgroud)

带上限的通配符:

? extends Object (or another class)
Run Code Online (Sandbox Code Playgroud)

带下限的通配符

? super Object (or another class)
Run Code Online (Sandbox Code Playgroud)

例子:

List <?> list;
Run Code Online (Sandbox Code Playgroud)

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

List<? extends Number> list;
Run Code Online (Sandbox Code Playgroud)

您可以使用类型参数Number(或Integer,Float,ecc)分配任何List列表

List<? super Integer> list;
Run Code Online (Sandbox Code Playgroud)

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

摘要:

宣言

List<Object> list;
Run Code Online (Sandbox Code Playgroud)

类似于

List<? super Object> list;
Run Code Online (Sandbox Code Playgroud)

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

    list = new ArrayList<Object>();
    list.add(new String(""));
    list.add(new Integer(3));
Run Code Online (Sandbox Code Playgroud)


mer*_*ike 7

String是一个子类型Object并不意味着它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 ...
Run Code Online (Sandbox Code Playgroud)

因此,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
Run Code Online (Sandbox Code Playgroud)


Joh*_*erg 6

其中一个主要区别是如何修改列表.以下效果很好

List<Object> l1;
l1.add(new Object()); // OK
Run Code Online (Sandbox Code Playgroud)

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

List<?> l2;
l2.add(new Object()); // Compile error
Run Code Online (Sandbox Code Playgroud)

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