?extends T 和? super T 的区别

<? extends T>

<? extends T>表示类型的上界,也就是说参数化的类型 可能是T或是T的子类。

例如下面的写法都是合法的赋值语句:

List<? extends Number>list=new ArrayList<Number>();
//Integer是Number的子类
List<? extends Number>list=new ArrayList<Integer>();
//Float也是Number的子类
List<? extends Number>list=new ArrayList<Float>();

<? extends T>被设计为用来读取数据的泛型(只能读取数据为T的元素),原因如下:

1、在上面赋值的示例中,对读数据进行分析:

      (1)不管给list如何赋值,可以保证list里面存放的一定是Number类型或其子类,因此可以从list列表里面读取Number类型的值。

      (2)不能从list中读取Integer,因为里面可能存放的是Float值,同理,也不可以从list里面读取Float。

2、对写数据进行分析:

      (1)不能向list中写Number,因为list中有可能存放的是Float。

      (2)不能向list中写Integer,因为list中有可能存放的是Float。

      (3)不能向list中写Float,因为list中有可能存放的是Integer。

从上面的分析可以发现,只能从List<? extends T> 读取T,因为无法确定它实际指向列表的类型,所以无法确定列表里面存放的实际的类型,也就无法向列表里面添加元素。

<? super T>

<? super T>表示类型下界,也就是说,参数化的类型就是此类型的超类型。

List<? super Float>list=new ArrayList<Float>();
//Number是Float的父类
List<? super Float>list=new ArrayList<Number>();
//Object是Number的父类
List<? super Float>list=new ArrayList<Object>();

<? super T>被设计为用来写数据的泛型(只能写入T或T的子类型),不能用来读,分析如下:

1、读数据

        无法保证list里面一定存放的是Float类型或Number类型,因为有可能存放的是Object类型,唯一能确定的是list里面存放存放的是Object或其子类,但是无法确定具体子类的类型。所以无法从list里面读取数据。

2、写数据

      (1)可以向list里面写入Float类型的数据;同理,也可以向list里面添加Float子类类型的元素。

      (2)不可以向list里面添加Number或Object类型的数据,因为list中可能存放的是Float类型de数据。

下面给出一个以上两个泛型使用的场景:

public class Collections{
     public static<T> void copy(List<? super T>dest,List<? extends T>src){
          for(int i=0;i<src.size();i++){
               dest.set(i,src.get(i));
          }         
     }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值