Mor*_*tch 3 java generics covariance
在Java中,您可以使用extends关键字声明给定的类型参数是协变的.协方差和逆变确实让我感到困惑,但我想我已经对它们有了一般的认识.但是,在我的测试中,似乎Java类型参数本质上是协变的.那么我们为什么要明确说明呢?
例如,我构建了一个如下所示的快速示例:
public class Main<E> {
protected E value;
public Main(E value) {
this.value = value;
}
public <T extends E> void setValue(T value) {
this.value = value;
}
public E getValue() {
return value;
}
public static void main(String[] args) {
Main<Number> example = new Main<Number>(0L);
System.out.println(example.getValue().getClass().getCanonicalName());
example.setValue(32.0);
System.out.println(example.getValue().getClass().getCanonicalName());
}
}
Run Code Online (Sandbox Code Playgroud)
使用的类型是Number,所有盒装类型的超类.在构造函数中,它接受一个声明为E类型的参数(在本例中为Number).setValue另一方面,在该方法中,它采用一个声明为任何扩展类型E 的参数.两个println调用都返回正确的值(首先java.lang.Long,然后java.lang.Double).
我看到它的方式,删除泛型,你仍然可以传递子类.如果声明的类没有类型参数,并且方法/构造函数接受/返回Numbers,它仍然可以正常工作.
那么extends在这种情况下关键字的目的是什么?
在这种情况下,使用extendsin 没有任何好处setValue.你T声明的声明setValue可以用它的上限代替你是对的,E:
public void setValue(E value) {
this.value = value;
}
Run Code Online (Sandbox Code Playgroud)
但请考虑一下:
public <T extends E> T setValueAndGiveItBack(T value) {
this.value = value;
return value;
}
Run Code Online (Sandbox Code Playgroud)
这意味着我们可以这样做:
Double d = example.setValueAndGiveItBack(32.0);
Run Code Online (Sandbox Code Playgroud)
没有T,最具体的类型example.setValueAndGiveItBack可以返回Number.
只是为了澄清,你也是对的,类型参数本质上是协变的.使用的原因extends是限制类型参数的上限.例如,<T>隐含地<T extends Object>.在上面的例子中,没有声明E为T上限,我们将无法分配value,this.value因为它可以是任何Object.
| 归档时间: |
|
| 查看次数: |
89 次 |
| 最近记录: |