java 泛型通配符

文章为平时学习记录所用,多些一遍加深记忆,方便复习。

 

面试官给写了一道题:

1. List<? extends Object> list = new ArrayList<>();

list.add("123");

2. List<? super String> list = new ArrayList<>();

list.add("123");

上面哪种写法是错误的?

内心OS:哈哈,这个我在《Java编程思想》上看过。答到:第一种写法是错的。

面试官又问:为啥?一个类型继承自Object,添加一个String类型进去是合理的啊。

我:....想不出来理由,好像第二个是错的?..

面试结果可想而知...

 

带着这个问题,我们来看一下java通配符

1.  <? extends Class>

例子:List<? extends Object> = new ArrayList<>();

可以读作“具有任何从Object继承的类型的列表”,但这并不意味着这个列表可以持有任意类型的Object。通配符引用的是明确的类型。通配符引用的是明确的类型。通配符引用的是明确的类型。重要的话重复三遍,通配符代表列表的类型是Object的一个子类,但是它必须是一个明确的具体类型,比如String,比如Integer,但不能二者皆是。所以,当还不确定list里的具体类型是什么的时候,你不能向列表中加入元素。加入了一个String,它的具体类型是Integer咋办?

那么当我们明确了通配符的类型时:

List<? extends Object> list = new ArrayList<String>();

我们就能向其中加入元素了吗,这样看起来可以加入String类型及其子类型。

但是...还是不行,即使明确了列表的具体类型,还是不能向其中添加元素,因为编译器不知道。。(很想打编译器)

这种通配符的使用,只能在初始化时,向其中加入元素:

List<? extends Object> list = Arrays.aslist(new String("123"));

说到这里,已经明白了开头的问题到底是为啥。

继续来看一下其他的通配符

2. 逆变。超类型通配符<? super Class>

List<? super Object> list = new ArrayList<>();

可以读作“任何是Object超类类型的列表”,这个写法其实有点奇怪,Object是继承体系中的根类,没有继承自任何类。<? super Object>同样引用的是明确的类型,并不是变化的类型。而这个“具体的类型”继承自Object,那么向其中添加Object及Object的子类都应该是可以的。的确是这样,这个列表其实可以加入任何类型。。

 

通配符的使用准则PECS(producer-extends, consumer-super):

生产者使用<? extends Class>,只能取,提供数据,生成类型一般固定为几个特定的类型,可以在初始化时加入。

消费者使用<? super Class>,生产者生产的数据,消费者需要put进数据结构后使用。

 

3.无界通配符<?>

无界通配符<?>看起来意味着“任何事物”,因为使用无界通配符好像等价于使用原生类型。<?>可以被认为是一种装饰,它是在声明:我想用Java泛型来写代码。

无界通配符的另一个作用是:当你在处理多个泛型参数时,有时允许一个参数可以是任何类型,同时为其他参数确定某种特定类型。这时候无界通配符就显得很重要。

使用无界通配符时,与通配符<? extends Class>有一点是一样的,就是不能向其中加入元素。

List<?> list;

list.add(new Object())是不合法的,因为无界通配符<?>也是引用的是明确的类型,而不知道具体的类型是什么,所以不允许向列表中加入元素。那么无界通配符<?>也只能作为生产者使用。

 

4. 协变

上面讲到了逆变,这里再来谈一谈协变性质。

class Fruit{}

class Apple extends Fruit{}

数组的协变:Fruit[] f = new Apple[10];

但是泛型容器是不具有协变性质的:

List<Apple> apples = new ArrayList<>();

List<Fruit> list = apples; // error: incompatible types

即使Apple是Fruit的子类,也不能将Apple的列表赋值给Fruit的列表。因为Apple的列表,不是Fruit的列表。

 

参考书籍:《Java编程思想》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值