Ban*_*kyo 74 java generics inheritance super
据我所知,它<? super T>代表任何超级类T(T任何级别的父类).但我真的很难想象这个通用绑定通配符的任何现实生活示例.
我明白了什么<? 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));
}
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找一个真实生活用例的例子,可以使用这种结构,而不是解释它是什么.
Eug*_*ene 46
我能想到的最简单的例子是:
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}
Run Code Online (Sandbox Code Playgroud)
取自同样的Collections.这种方式Dog可以实现Comparable<Animal>,如果Animal已经实现了,Dog则无需执行任何操作.
编辑一个真实的例子:
经过一些电子邮件的ping-pongs,我被允许在我的工作场所展示一个真实的例子(耶!).
我们有一个名为Sink(它无关紧要)的界面,这个想法就是积累东西.声明非常简单(简化):
interface Sink<T> {
void accumulate(T t);
}
Run Code Online (Sandbox Code Playgroud)
显然有一个辅助方法可以将List它的元素排放到一个Sink(它有点复杂,但要简化它):
public static <T> void drainToSink(List<T> collection, Sink<T> sink) {
collection.forEach(sink::accumulate);
}
Run Code Online (Sandbox Code Playgroud)
这很简单吧?好...
我可以有一个List<String>,但我想把它排到一个Sink<Object>- 这对我们来说是相当普遍的事情; 但这会失败:
Sink<Object> sink = null;
List<String> strings = List.of("abc");
drainToSink(strings, sink);
Run Code Online (Sandbox Code Playgroud)
为此,我们需要将声明更改为:
public static <T> void drainToSink(List<T> collection, Sink<? super T> sink) {
....
}
Run Code Online (Sandbox Code Playgroud)
Ben*_*oit 15
假设你有这个类层次结构:Cat继承自Mammal,而Mammal继承自Animal.
List<Animal> animals = new ArrayList<>();
List<Mammal> mammals = new ArrayList<>();
List<Cat> cats = ...
Run Code Online (Sandbox Code Playgroud)
这些调用有效:
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
Run Code Online (Sandbox Code Playgroud)
但是,这些电话是不是有效的:
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
Run Code Online (Sandbox Code Playgroud)
因此,方法签名只是确保您从更具体(在继承层次结构中更低)类复制到更通用的类(继承层次结构中的上层),而不是相反.
例如,查看Collections.addAll方法implmenetation:
public static <T> boolean addAll(Collection<? super T> c, T... elements) {
boolean result = false;
for (T element : elements)
result |= c.add(element);
return result;
}
Run Code Online (Sandbox Code Playgroud)
这里,元素可以插入到元素类型是元素类型的超类型的任何集合中T.
没有下限的通配符:
public static <T> boolean addAll(Collection<T> c, T... elements) { ... }
Run Code Online (Sandbox Code Playgroud)
以下内容无效:
List<Number> nums = new ArrayList<>();
Collections.<Integer>addAll(nums , 1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
因为这个词Collection<T>比限制更严格Collection<? super T>.
另一个例子:
Predicate<T>Java中的接口,它<? super T>在以下方法中使用通配符:
default Predicate<T> and(Predicate<? super T> other);
default Predicate<T> or(Predicate<? super T> other);
Run Code Online (Sandbox Code Playgroud)
<? super T> 允许链接更广泛的不同谓词,例如:
Predicate<String> p1 = s -> s.equals("P");
Predicate<Object> p2 = o -> o.equals("P");
p1.and(p2).test("P"); // which wouldn't be possible with a Predicate<T> as a parameter
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4554 次 |
| 最近记录: |