java - 在 Java 中,通配符能做什么常规泛型不能做什么?

标签 java generics bounded-wildcard unbounded-wildcard

我是 Java 新手。在 this记录他们将此作为使用通配符的用例:

static void printCollection(Collection c) {
    Iterator i = c.iterator();
    for (int k = 0; k < c.size(); k++) {
        System.out.println(i.next());
    }
}

这是他们的解决方案:

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

但我可以在没有通配符的情况下做同样的事情:

static <T> void printCollection(Collection<T> c) {
    Iterator i = c.iterator();
    for (int k = 0; k < c.size(); k++) {
        System.out.println(i.next());
    }
}

谁能告诉我一个简单的用例,其中常规泛型不起作用但通配符可以?

更新:这里的答案When to use wildcards in Java Generics?不要告诉我们需要通配符。实际上是相反的。

最佳答案

通配符允许我们做的一件事是声明与特定类型参数无关的类型,例如“任何类型列表的列表”:

List<List<?>> listOfAnyList = ...;

listOfAnyList.add( new ArrayList<String>() );
listOfAnyList.add( new ArrayList<Double>() );

如果没有通配符,这是不可能的:*,因为元素列表可能有不同的类型。

如果我们尝试 capture它,我们会发现我们做不到:

static <E> void m(List<List<E>> listOfParticularList) {}

m( listOfAnyList ); // <- this won't compile

通配符允许我们做的另一件事是类型参数不能设置下限。 (类型参数可以声明为 extends 边界,但不能声明为 super 边界。**)

class Protector {
    private String secretMessage = "abc";

    void pass(Consumer<? super String> consumer) {
        consumer.accept( secretMessage );
    }
}

假设 pass而是宣布采取Consumer<String> .现在假设我们有一个 Consumer<Object> :

class CollectorOfAnything implements Consumer<Object> {
    private List<Object> myCollection = new ArrayList<>();

    @Override
    public void accept(Object anything) {
        myCollection.add( anything );
    }
}

问题是:我们不能将它传递给一个接受 Consumer<String> 的方法。 .声明 Consumer<? super String>意味着我们可以通过任何接受 String 的消费者. (另见 Java Generics: What is PECS?。)

大多数时候,通配符只是让我们做出整洁的声明。

如果我们不需要使用类型,我们就不必为它声明类型参数。


* 技术上也可以使用 raw type ,但不鼓励使用原始类型。

** 我不知道为什么 Java 不允许 super对于类型参数。 4.5.1. Type Arguments of Parameterized Types可能暗示它与类型推断的限制有关:

Unlike ordinary type variables declared in a method signature, no type inference is required when using a wildcard. Consequently, it is permissible to declare lower bounds on a wildcard […].

关于java - 在 Java 中,通配符能做什么常规泛型不能做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29856889/

相关文章:

java - 将 setText 用于 EditText 框,onClick 认为它为空

java - 如何重试 Camel 直达路线一次?

java - 通用 : ArrayList of ? 在 Java 中扩展 ISomeInterface

java - Logback 日志记录 - 同步或异步

java - 如何命名 JAXB 类?

c# - 如何使用泛型比较 C# 中的 X 列表和 Y 列表?

generics - 是否可以在 ‘T is constrained to be a tuple of type ' T2*'T3 处编写一个 genericFunction<'T>?

java - 对泛型类的非泛型引用导致非泛型返回类型

具有有界通配符的泛型类型的 Java 泛型集合

java - 为什么这种通用分配是非法的?