通用类型:通配符与裸类型变量

3
考虑以下方法:
public static void listAll(LinkedList list) {

    for(Object obj : list)
        System.out.println(obj);

}

并且

public static void listAll(LinkedList<?> list) {

    for(Object obj : list)
        System.out.println(obj);

}

这两种方法有什么区别?如果没有区别,我们为什么要使用第二种方法呢?

不,我明白了。第二个使用了通配符但它没有出现。 - Sina Barghidarian
请使用代码标签并编辑您的问题。 - Sam R.
第一个是非泛型的。列表中的所有内容都是Object类型,需要进行强制转换。第二个是泛型的。类型将在编译时进行检查。 - Sam R.
谢谢你的帮助,我不知道如何做。:-) - Sina Barghidarian
看看这个原始类型 vs 无界通配符 - Sam R.
显示剩余2条评论
2个回答

6
<?> 不允许您在列表中添加对象。请看下面的程序。我们已将特定类型的列表传递给<?>方法。这里的“特定”意味着,该列表是使用特定类型创建并传递给listAll方法的。不要混淆specific这个词。 这里的“特定”可以是任何普通对象,如狗、老虎、字符串、对象、哈希映射、文件、整数、长整型等等,列表是没有限制的。
JLS强制执行<?>方法,以防止在调用<?>方法时向其添加任何不相关的对象,一旦您定义了包含特定类型对象的列表(在调用方法中定义而不是在called-listAll中)。这就像<?>在说:“别碰我”。
public static void listAll(LinkedList list) 
{
    list.add(new String());  //works fine
    for(Object obj : list)
            System.out.println(obj);

}
public static void listAll(LinkedList<?> list) 
{
     list.add(new String());  //compile time error. Only 'null' is allowed.
     for(Object obj : list)
          System.out.println(obj);
}

现在让我们看一下不同的情况。当我们声明特定类型,例如Dog、Tiger、Object、String等时会发生什么。让我们将方法更改为特定类型
public static void listAll(LinkedList<String> list)// It is now specific type, 'String'
{
    list.add(new String());//works fine. Compile time it knows that 'list' has 'String'
    for(Object obj : list)
         System.out.println(obj);
}

<?> 不允许在列表中设置对象,但我们可以获取对象,对吗?在 getter() 方法中,我们获取的对象类型是什么(是对象还是类型参数边界)? - Sina Barghidarian
它始终是对象类型。泛型只是为了方便而存在。它确保程序员不会误导编码。否则,程序员将在运行时发现混乱。 - AmitG
1
@ CenaPi 你应该查阅Joshua Bloch在他的著作"Effective Java"中介绍的“PECS”机制。“Producer Extends,Consumer Super”。通配符<?>与<? extends Object>同义,因此表示“extends”,即为“生产者”。生产者意味着你可以从列表中获取物品,但不能添加到其中。 - Timmos
在这种情况下,您可以添加任何Foo对象。 ((List<? super Foo>) new LinkedList<>()).add(new Foo()); - Kröw

1

List 是原始类型,List<?> 是带有通配符参数的泛型类型。

假设我们有以下变量:

List<?> a;
List<String> b;
List c;

赋值语句b=a会产生编译时错误(List<String>无法分配给List<?),但是c=a可以编译通过(为了与不使用泛型的遗留代码兼容,List<String>可以分配给原始类型List)。

赋值语句b=c会产生编译时警告(List<?>无法分配给List<String>),但是a=c可以编译通过(List<String>可以分配给List<?>


帮帮忙!我需要更多的解释。 - Sina Barghidarian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接