Java 泛型 <? super T> 中 super 怎么 理解?与 extends 有何不同?

本文详细解释了Java泛型中的List&lt;? extends E&gt;与List&lt;? super E&gt;的区别。前者用于获取E及其子类型的元素,但不能添加元素;后者允许添加E的子类型元素,但不允许获取元素。文章通过实例说明了这两种泛型用法的设计原理及安全性考量。

https://www.zhihu.com/question/20400700


著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

首先,泛型的出现时为了安全,所有与泛型相关的异常都应该在编译期间发现,因此为了泛型的绝对安全,java在设计时做了相关的限制:

List<? extends E>表示该list集合中存放的都是E的子类型(包括E自身),由于E的子类型可能有很多,但是我们存放元素时实际上只能存放其中的一种子类型(这是为了泛型安全,因为其会在编译期间生成桥接方法<Bridge Methods>该方法中会出现强制转换,若出现多种子类型,则会强制转换失败),例子如下:

List<? extends Number> list=new ArrayList<Number>();
        list.add(4.0);//编译错误
        list.add(3);//编译错误

上例中添加的元素类型不止一种,这样编译器强制转换会失败,为了安全,Java只能将其设计成不能添加元素。

虽然List<? extends E>不能添加元素,但是由于其中的元素都有一个共性--有共同的父类,因此我们在获取元素时可以将他们统一强制转换为E类型,我们称之为get原则。

对于List<? super E>其list中存放的都是E的父类型元素(包括E),我们在向其添加元素时,只能向其添加E的子类型元素(包括E类型),这样在编译期间将其强制转换为E类型时是类型安全的,因此可以添加元素,例子如下:

 List<? super Number> list=new ArrayList<Number>();
        list.add(2.0);
        list.add(3.0);

但是,由于该集合中的元素都是E的父类型(包括E),其中的元素类型众多,在获取元素时我们无法判断是哪一种类型,故设计成不能获取元素,我们称之为put原则

实际上,我们采用extends,super来扩展泛型的目的是为了弥补例如List<E>只能存放一种特定类型数据的不足,将其扩展为List<? extends E> 使其可以接收E的子类型中的任何一种类型元素,这样使它的使用范围更广。

List<? super E>同理。

 

我的一点理解:

1.List中只能存储一种类型

2.List<? extends E> 逻辑上能且只能存放E或者E的任意一个子类,姑且称为EE, 但是add没法限制 只能一种EE的子类型, Java直接不让你add,   但是get 却可以get到 这个EE类型(get到的所有子类型都是EE)

3.List<? super E> 逻辑上能且只能存放E或者E的父类型, 姑且称为SE, 所以可以 add E的任何一个子类(A) 到List中, 最后都会强制类型转换为SE, 但是get的时候, 其实只能返回SE类型, 而不能返回他的子类型, 这对开发者是有困扰的, 我放进去的是A为什么不能拿到A? Java索性不让你get 

转载于:https://my.oschina.net/sfshine/blog/1797107

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值