类型协变和逆变是什么鬼?

类型协变和逆变,什么鬼?干什么的?怎么用?

不少童鞋面试的时候会被问到关于类型协变和逆变的问题。这不是最近才发生的事情,自从Java5.0开始引入类型协变和逆变的概念到现在,无数的无辜童鞋面试折在这个上面。虽然不是什么新概念、新技术,但是真TMD绕啊!

下面我们就来看看类型协变和逆变到底是什么鬼。

首先,既然是“变”,那么大家就不要觉得所谓“协变”和“逆变”是类型系统自然的结论,一定有什么不那么自然的事情才够刺激!

那么先看看最自然的是什么情况(没有"变"哦):

class Fruit {}
class Apple extends Fruit { ... }
class Orange extends Fruit { ... }

大家一定认可这样的代码:

Fruit fruit = null;
Apple apple = new Apple();
fruit = apple;

 那下面的代码呢?

Fruit[] fruitAry = null;
Apple[] appleAry = new Apple[10];
fruitAry = appleAry;

这个看起来很自然啊!我说我要一个能装水果的篮子,然后你给我一个装苹果的篮子,我说这就是我要的。多么自然啊!

但是不好意思,编译器不这么看。在编译器看来,它只知道苹果是一种水果,现在你拿着一个装苹果的篮子,硬说它是装水果的篮子,编译器当然不同意了。结果就是“编译出错!”

这种情况是出在5.0以前的编译器上的。那么现在的编译器又是怎么说的呢?

现在的编译器把一个具有泛型参数T的泛型类型看做是关于类型T的一种变换,类型T的数组也可以看做是接受泛型参数为T的一种泛型类型。注意这里仅仅是看做,是理论上的,就是说从理论上String[]和Array<String>是等价的。

所以后面的讨论,都是基于泛型来进行的,不特别针对数组这种特殊情况了。

下面来看两个泛型类型的声明:

class Picker<T> {
    public T pick() {
        // ...
        return (T)null;
    }
}

class Ch
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值