java 泛型 t extends_java 泛型<? super T>和<? extends T>

本文以list为例,其他集合类似。

为了安全,编译器在List进行存储的时候只会保存为一种类型。

List super T> list中的元素全是T的某个父类型

List extends T> list中的元素全是T的某个子类类型

上面这种定义类型的使用场景:

PECS指“Producer Extends,Consumer Super”。换句话说,如果参数化类型表示一个生产者,就使用 extends T>;如果它表示一个消费者,就使用 super T>。

在实际的使用中, extends T> 实际上代表的是T的某个子类,X继承自T,当我们插入一个数据T的时候无法保证其能够转换成X,但是我们可以保证读取的数据可以转换成T。

同理 super T>实际上也是代表的T的某个父类,当我们读取一个数据的时候是无法保障Y能够转换成T的,但是能够保障插入T数据能够转换成Y。

由于List extends T>是list中的某个子类,如果我们向list中添加元素,子类之间并不能相互转换,导致添加失败,而List super T> 则可以用来添加T的子类,因为T的子类型都可以转为T的某个父类。 相反List extends T>中的元素则都可以转为T,则可以用来读取list中的元素,但是List super T> 中的元素不能转为T则无法用来读取list中的元素,除非读取为Object 类型。

这样这两个类型的用途就很明显:

List super T> 保证向list中添加的元素全是T的子类含T,用于只写操作,读操作可能会导致异常

List extends T> 保证读取list中的元素全是T的子类含T ,用于只读操作,写操作会有异常

用例(java.util.Collections的copy方法):

public static void copy(List super T> dest, List extends T> src) {

int srcSize = src.size();

if (srcSize > dest.size())

throw new IndexOutOfBoundsException("Source does not fit in dest");

if (srcSize < COPY_THRESHOLD ||

(src instanceof RandomAccess && dest instanceof RandomAccess)) {

for (int i=0; i

dest.set(i, src.get(i));

} else {

ListIterator super T> di=dest.listIterator();

ListIterator extends T> si=src.listIterator();

for (int i=0; i

di.next();

di.set(si.next());

}

}

}

保证dest只用来存储数据,src的数据只会被读取。

附加:

对于实现了RandomAccess接口的列表,随机读取的效率高于迭代器,而没有实现RandomAccess的接口的列表使用迭代器效率要高一些。(Java接口RandomAccess全面了解)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值