Syn*_*sso 25 java generics contravariance
在Java中,协方差允许API设计者指定实例可以被概括为某种类型或任何该类型的子类型.例如:
List<? extends Shape> shapes = new ArrayList<Circle>();
// where type Circle extends Shape
Run Code Online (Sandbox Code Playgroud)
反方差则是另一种方式.它允许我们指定实例可以概括为某种类型或超类型.
List<? super Shape> shapes = new ArrayList<Geometry>();
// where Shape extends Geometry
Run Code Online (Sandbox Code Playgroud)
Java泛型的逆变是如何有用的?你什么时候选择使用它?
Sea*_*oyd 35
以下是Java Generics和Collections的相关摘录:
尽可能插入通配符可能是一种好习惯,但是如何确定使用哪个通配符?你extends应该在哪里使用,你应该在哪里使用,在super哪里使用通配符是不合适的?
幸运的是,一个简单的原则决定哪个是合适的.
Get和Put原则:
extends当你只从结构中获取值时使用super通配符,当你只将值放入结构时使用通配符,并且当你同时获取和放置时不使用通配符.
我们已经在复制方法的签名中看到了这个原则:
public static <T> void copy(List<? super T> dest, List<? extends T> src)
Run Code Online (Sandbox Code Playgroud)
该方法从源src中获取值,因此使用extends通配符声明它,并将值放入目标dst,因此使用super通配符声明它.每当使用迭代器时,都会从结构中获取值,因此请使用extends
通配符.这是一个采用数字集合的方法,将每个数字转换为double,并将它们相加:
public static double sum(Collection<? extends Number> nums) {
double s = 0.0;
for (Number num : nums) s += num.doubleValue();
return s;
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 30
那么,你的第二个例子可以让你写:
Shape shape = getShapeFromSomewhere();
shapes.add(shape);
Run Code Online (Sandbox Code Playgroud)
而你不能用第一种形式做到这一点.它不像协方差那样有用,我会授予你.
可比较有用的一个领域是比较.例如,考虑:
class AreaComparer implements Comparator<Shape>
...
Run Code Online (Sandbox Code Playgroud)
您可以使用它来比较任何两个形状......所以如果我们也可以使用它来排序List<Circle>例如,那将是很好的.幸运的是,我们可以通过逆转来做到这一点,这就是为什么有一个重载Collections.sort:
public static <T> void sort(List<T> list, Comparator<? super T> c)
Run Code Online (Sandbox Code Playgroud)
例如,在实现Collections.addAll()方法时,您需要一个可以包含某个类型T或T的超类型的集合.该方法如下所示:
public static <T> void addAll(Collection<? super T> collection, T... objects) {
// Do something
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6137 次 |
| 最近记录: |