打字猴:1.700447287e+09
1700447287 编写高质量代码:改善Java程序的151个建议 [:1700438170]
1700447288 编写高质量代码:改善Java程序的151个建议 建议97:警惕泛型是不能协变和逆变的
1700447289
1700447290 什么叫协变(covariance)和逆变(contravariance)?Wiki上是这样定义的:
1700447291
1700447292 Within the type system of a programming language, covariance and contravariance refers to the ordering of types from narrower to wider and their interchangeability or equivalence in certain situations(such as parameters, generics, and return types).
1700447293
1700447294 在编程语言的类型框架中,协变和逆变是指宽类型和窄类型在某种情况下(如参数、泛型、返回值)替换或交换的特性,简单地说,协变是用一个窄类型替换宽类型,而逆变则是用宽类型覆盖窄类型。其实,在Java中协变和逆变我们已经用了很久了,只是我们没发觉而已,看如下代码:
1700447295
1700447296 class Base{
1700447297
1700447298 public Number doStuff(){
1700447299
1700447300 return 0;
1700447301
1700447302 }
1700447303
1700447304 }
1700447305
1700447306 class Sub extends Base{
1700447307
1700447308 @Override
1700447309
1700447310 public Integer doStuff(){
1700447311
1700447312 return 0;
1700447313
1700447314 }
1700447315
1700447316 }
1700447317
1700447318 子类的doStuff方法返回值的类型比父类方法要窄,此时doStuff方法就是一个协变方法,同时根据Java的覆写定义来看,这又属于覆写。那逆变是怎么回事呢?代码如下:
1700447319
1700447320 class Base{
1700447321
1700447322 public void doStuff(Integer i){
1700447323
1700447324 }
1700447325
1700447326 }
1700447327
1700447328 class Sub extends Base{
1700447329
1700447330 public void doStuff(Number n){
1700447331
1700447332 }
1700447333
1700447334 }
1700447335
1700447336 子类的doStuff方法的参数类型比父类要宽,此时就是一个逆变方法,子类扩大了父类方法的输入参数,但根据覆写定义来看,doStuff不属于覆写,只是重载而已。由于此时的doStuff方法已经与父类没有任何关系了,只是子类独立扩展出的一个行为,所以是否声明为doStuff方法名意义不大,逆变已经不具有特别的意义了,我们来重点关注一下协变,先看如下代码是否是协变:
[ 上一页 ]  [ :1.700447287e+09 ]  [ 下一页 ]