什么是现实生活中的通用<?超级T>?

2022-08-31 13:12:20

我理解它代表任何超类(任何级别的父类)。但我真的很难想象这个通用绑定通配符的任何现实生活中的例子。<? super T>TT

我明白是什么意思,我已经看到了这种方法:<? super T>

public class Collections {
  public static <T> void copy(List<? super T> dest, List<? extends T> src) {
      for (int i = 0; i < src.size(); i++)
        dest.set(i, src.get(i));
  }
}

我正在寻找一个现实生活中用例的例子,其中可以使用这种结构,而不是解释它是什么。


答案 1

我能想到的最简单的例子是:

public static <T extends Comparable<? super T>> void sort(List<T> list) {
    list.sort(null);
}

取自同一 .通过这种方式,一个可以实现,如果已经实现了,则不必做任何事情。CollectionsDogComparable<Animal>AnimalDog

编辑一个真实的例子:

在一些电子邮件乒乓球之后,我被允许从我的工作地点提出一个真实的例子(耶!

我们有一个叫做(它做什么并不重要),这个想法是积累东西。该声明非常琐碎(简化):Sink

interface Sink<T> {
    void accumulate(T t);
}

显然,有一个辅助方法可以采用 a 并将其元素排出到 a(这有点复杂,但要简单一些):ListSink

public static <T> void drainToSink(List<T> collection, Sink<T> sink) {
    collection.forEach(sink::accumulate);
}

这很简单,对吧?井。。。

我可以有一个,但我想把它消耗到一个 - 这对我们来说是一个相当普遍的事情;但这将失败:List<String>Sink<Object>

Sink<Object> sink = null;
List<String> strings = List.of("abc");
drainToSink(strings, sink);

为此,我们需要将声明更改为:

public static <T> void drainToSink(List<T> collection, Sink<? super T> sink) {
    ....
}

答案 2

假设您有这样的类层次结构:Cat 继承自哺乳动物,而哺乳动物又继承自动物。

List<Animal> animals = new ArrayList<>();
List<Mammal> mammals = new ArrayList<>();
List<Cat> cats = ...

这些调用是有效的:

Collections.copy(animals, mammals); // all mammals are animals
Collections.copy(mammals, cats);    // all cats are mammals
Collections.copy(animals, cats);    // all cats are animals
Collections.copy(cats, cats);       // all cats are cats 

但这些调用无效

Collections.copy(mammals, animals); // not all animals are mammals
Collections.copy(cats, mammals);    // not all mammals are cats
Collections.copy(cats, animals);    // mot all animals are cats

因此,方法签名只是确保从更具体的(继承层次结构中的较低)类复制到更通用的类(继承层次结构中的较高),而不是相反。


推荐