通配符:谈论“对象”与“?”

时间:2014-02-10 15:38:37

标签: java generics collections wildcard

看看这两个例子:

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

VS

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

这两者有什么区别?我读到第二个例子更强大。但那是为什么呢?您无法将哪个参数传递给方法1,您可以将其传递给方法2?

1 个答案:

答案 0 :(得分:3)

泛型aren't covariant。换句话说,Collection<String>不是Collection<Object>,即使StringObject。使用第一个签名,我将无法打印List<String>例如。

通用通配符有助于表达协方差(如您的示例所示)和逆变。 Collection<?>Collection<? extends Object>的缩写,意思是“某个特定的,未知类型的集合,是Object”。因此,我们无法向此类集合添加除null之外的任何内容,因为我们无法保证添加的对象的类型有效。

以下是使用通配符表示逆差的示例:

void populateCollection(Collection<? super Integer> c) {
    for (int i = 0; i < 10; i++) {
        c.add(i);
    }
}

我可以将Collection<Object>Collection<Number>Collection<Integer>传递给此方法,因为它被视为Integer使用者。在您的示例中,该集合是Object生成器。有关通配类泛型类型的“生产者”和“消费者”之间的区别,请参阅此文章:What is PECS (Producer Extends Consumer Super)?