java的协变性、逆变性、不变性

    先看看官方的解释:协变和逆变都是术语,前者指能够使用比原始指定的派生类型的派生程度更大(更具体的)的类型,后者指能够使用比原始指定的派生类型的派生程度更小(不太具体的)的类型。协变和逆变是指宽类型和窄类型在某种情况下(如参数、泛 型、返回值)替换或交换的特性。

 

    简单地说A和B是类型,f表示类型转换,≤表示子类型关系:

    协变:你可以用一个子类对象去替换相应的一个父类对象。如果A≤B 则f(A) ≤ f(B) 那么 f是协变的 。如果能在泛型接口或者委托中保证,类型参数只能外部取出而不允许外部传入。那么就可以避免将类型参数作为参数传入方法的情况。可以通过在类型参数前面加out来解决这个问题。

 

    逆变:你可以用一个父类对象去替换相应的一个父类对象。如果A≤B 则f(B) ≤ f(A) 那么 f 是逆变的。如果能在泛型接口或者委托中保证,类型参数只能作为参数从外部传入而不允许将其取出。那么就不存在将类型参数作为返回值返回的情况了。可以通过在类型参数前面加in来解决这个问题。

 

    不变:对于不支持协变和逆变的情况称为不变性。上面两种都不成立,那么f是无关的。

    来实际说明一下协变性和不可性在java中的具体体现。

    一、java的数组就具有协变性

        数组的协变性是指如果类Base是类Sub的基类,那么Base[]就是Sub[]的基类。数组是协变的导致了很多问题的出现,Object[]类型的引用可以指向一个String[]类型的对象。但是运行的时候是会报出如下异常的:Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer 试图将错误类型的对象存储到一个对象数组时抛出的异常。这样导致数组的类型并不安全。数组则是在运行时做类型检查,因为能够记得数组内部元素的具体类型。

 

 

   二、java的泛型就具有不变性

        泛型是不可变的,List<Base>不会是List<Sub>的基类,更不会是它的子类。为了遵守泛型类型安全原则,所以在泛型“编译时进行类型检查”特性决定了其不可协变。因为在泛型进行类型擦除,所以只能选择在编译期进行类型检查,因为一旦运行起来这个类型就会被擦除掉,如果类型不一致编译就不会通过。为了让泛型更灵活也可以具备协变性,就可以使用通配符来模拟协变。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值