java extends原则_Java泛型中extends和super的理解(转)

E – Element (在集合中使用,因为集合中存放的是元素)

T – Type(Java 类)

K – Key(键)

V – Value(值)

N – Number(数值类型)

? – 表示不确定的java类型(无限制通配符类型)

S、U、V – 2nd、3rd、4th types

Object – 是所有类的根类,任何类的对象都可以设置给该Object引用变量,使用的时候可能需要类型强制转换,但是用使用了泛型T、E等这些标识符后,在实际用之前类型就已经确定了,不需要再进行类型强制转换。

? 通配符类型

extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类

super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object

在Java的类型擦除我们提到过:类型擦除中第一步——将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。

这里的左边届可以通过extends来体现。

当生成泛型类的字节码时,编译器用类型参数的擦除替换类型参数。对于无限制类型参数 (),它的擦除是 Object。对于上限类型参数(>),它的擦除是其上限(在本例中是 Comparable)的擦除。对于具有多个限制的类型参数,使用其最左限制的擦除。

extends

上界用extends关键字声明,表示参数化的类型可能是所指定的类型,或者是此类型的子类。

比如,我们现在定义:List extends T>首先你很容易误解它为继承于T的所有类的集合,你可能认为,你定义的这个List可以用来put任何T的子类,那么我们看一下下面的代码:

importjava.util.LinkedList;importjava.util.List;/**

* @author hollis

*/publicclasstestGeneric {publicstaticvoidmain(String[]args){List<?extendsSeason>seasonList =newLinkedList<>();seasonList.add(newSpring());}}classSeason{}classSpringextendsSeason{}

seasonList.add(new Spring());这行会报错:The method put(Spring) is undefined for the type List

List extends Season> 表示 “具有任何从Season继承类型的列表”,编译器无法确定List所持有的类型,所以无法安全的向其中添加对象。可以添加null,因为null 可以表示任何类型。所以List 的add 方法不能添加任何有意义的元素,但是可以接受现有的子类型List 赋值。

你也许试图这样做:

List<?extendsSeason>seasonList =newLinkedList();seasonList.add(newSpring());

但是,即使指明了Spring,也不能用add方法添加一个Spring对象。

list中为什么不能加入Season类和Season类的子类呢,原因是这样的:

List extends Fruit>表示上限是Fruit,下面这样的赋值都是合法的

List<?extendsSeason>list1 =newArrayList();List<?extendsSeason>list2 =newArrayList();List<?extendsSeason>list3 =newArrayList();

如果List extends Season>支持add方法的方法合法的话

list1可以add Season和所有Season的子类

list2可以add Spring和所有Spring的子类

list3可以add Winter和所有Winter的子类

这样的话,问题就出现了

List extends Season>所应该持有的对象是Season的子类,而且具体是哪一个子类还是个未知数,所以加入任何Season的子类都会有问题,

因为如果add Spring的话,可能List extends Season>持有的对象是new ArrayList()

Spring的加入肯定是不行的,如果 如果add Winter的话,可能List extends Season>持有的对象是new ArrayList()

Winter的加入又不合法,所以List extends Season> list 不能进行add

但是,这种形式还是很有用的,虽然不能使用add方法,但是可以在初始化的时候一个Season指定不同的类型。比如:

List extends Season> list1 = getSeasonList();//getSeasonList方法会返回一个Season的子类的list

另外,由于我们已经保证了List中保存的是Season类或者他的某一个子类,所以,可以用get方法直接获得值:

List<?extendsSeason>seasonList =newLinkedList();Springspring =(Spring)seasonList.get(0);Seasonseason =seasonList.get(1);

super

下界用super进行声明,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至Object。

如:

Listfruits =newArrayList();List<?superApple>=fruits;fruits.add(newApple());//workfruits.add(newRedApple());//workfruits.add(newFruit());//compile error fruits.add(newObject());//compile error

这里的fruits是一个Apple的超类(父类,superclass)的List。同样地,出于对类型安全的考虑,我们可以加入Apple对象或者其任何子类(如RedApple)对象,但由于编译器并不知道List的内容究竟是Apple的哪个超类,因此不允许加入特定的任何超类型。

而当我们读取的时候,编译器在不知道是什么类型的情况下只能返回Object对象,因为Object是任何Java类的最终祖先类。

PECS原则

如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends)

如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super)

如果既要存又要取,那么就不要使用任何通配符。

参考资料:

http://www.hollischuang.com/archives/255

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
泛型superextends是用来限制泛型类型参数的边界的关键字。 super关键字用于限制泛型类型参数的下限,表示该泛型类型参数必须是指定类型或指定类型的父类。例如,可以使用super关键字来定义一个泛型类,该泛型类的类型参数必须是Integer类型或Integer的父类。\[2\] extends关键字用于限制泛型类型参数的上限,表示该泛型类型参数必须是指定类型或指定类型的子类。例如,可以使用extends关键字来定义一个泛型类,该泛型类的类型参数必须是Number类型或Number的子类。\[3\] 在泛型,使用? extends A来表示一个只读型容器,其的元素都是A类型或A的子类型。这样可以提供泛型协变,提高代码的复用性。例如,可以定义一个List<? extends A>类型的变量,它可以引用一个ArrayList<A>、ArrayList<B>或ArrayList<C>对象。\[1\] 而使用? super B来表示一个只写型容器,其的元素都是B类型或B的父类型。这样可以提供泛型逆变,用于只写操作。例如,可以定义一个List<? super B>类型的变量,它可以引用一个ArrayList<A>对象。\[1\] #### 引用[.reference_title] - *1* [Java 泛型 ? extends 与 ? super](https://blog.csdn.net/qq_41490274/article/details/122886351)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Java泛型extendssuper理解](https://blog.csdn.net/helloxiefei/article/details/129088874)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值