泛型定义中的通配符

泛型定义中的通配符

List<? extends Number> foo3
 
含义是:变量foo3可以包含任何继承自Number的类型。
以下都是合法的定义:
List<? extends Number> foo3 = new ArrayList<Number>();  //Number "extends" Number
List<? extends Number> foo3 = new ArrayList<Integer>();  //Integer "extends" Number
List<? extends Number> foo3 = new ArrayList<Double>();  //Double "extends" Number
 
因此,考虑到以上可能的定义,什么类型的对象可以被合法的添加到List<? extends Number> foo3中呢?
  • 你不能添加Integer对象,因为foo3可能被定义为 List<Double>。
  • 你不能添加Double对象,因为foo3可能被定义为 List<Integer>。
  • 你不能添加Number对象,因为foo3可能被定义为 List<Integer>。
你不能添加任何对象到List<? extends T>中,因为你不能确定List真正被定义成什么,也就不能确定某个类型是否可以被List接受。
唯一可以确定的是你可以从List中读取一个Number类型的对象或一个Number类型的子类对象。

相反的逻辑也使用于super,如List<? super T>。一下定义都是合法的:
List<? super Number> foo3 = new ArrayList<Number>();  //Number is a "super" of Number
List<? super Number> foo3 = new ArrayList<Object>();  //Object is a "super" of Number
 
你不能从List<? super T>中读取一个特定类型的类(如Number),因为你不能确定List真正被定义成什么。(但是可以读取一个Object对象)
唯一可以确定的是你可以向List添加一个T类型的对象或T类型的超类对象。

一个很好的例子是Collection.copy()的定义:
public static <T> void copy(List<? super T> dest, List<? extends T> src)
 
注意src的定义,用extends允许接受任何值为T类型或T类型的子类型的List,并从中读取值,但你不能向src执行添加操作。
dest的定义,用super允许接受任何值为T类型或T类型的超类的List,并向其写入值,但你不能向dest执行读取操作。

由此,感谢泛型通配符,通过如上的一个定义,我们可以做以下这些调用。
//copy(dest, src)
Collection.copy(new ArrayList<Number>(), new ArrayList<Number());
Collection.copy(new ArrayList<Number>(), new ArrayList<Integer());
Collection.copy(new ArrayList<Object>(), new ArrayList<Number>());
Collection.copy(new ArrayList<Object>(), new ArrayList<Double());


下面做一些练习。被注释掉的代码是错误的
List<Number> listNumber_ListNumber = new ArrayList<Number>();
//List<Number> listNumber_ListInteger = new ArrayList<Integer>();
//错误 - 只能接受Number类型。
//List<Number> listNumber_ListDouble = new ArratList<Double>();
//错误 - 只能接受Number类型。
List<Integer> listInteger_ListInteger = new ArrayList<Integer>();
//List<Integer> listInteger_ListDouble  = new ArrayList<Double>();
//错误 - 只能接受Integer类型

List<? extends Number> listExtendsNumber_ListNumber = new ArrayList<Number>();
List<? extends Number> listExtendsNumber_ListInteger = new ArrayList<Integer>();
List<? extends Number> listExtendsNumber_ListDouble = new ArrayList<Double>();

List<? extends Integer> listExtendsInteger_ListInteger = new ArrayList<Integer>();
//List<? extends Integer> listExtendsInteger_ListNumber  = new ArrayList<Number>();
//错误 - Number不是Integer的子类
//List<? extends Integer> listExtendsInteger_ListDouble  = new ArrayList<Double>();
//错误 - Double不是Integer的子类

List<? super Number> listSuperNumber_ListNumber = new ArrayList<Number>();
//List<? super Number> listSuperNumber_ListInteger = new ArrayList<Integer>();
//错误 - Integer不是Number的超类
//List<? super Number> listSuperNumber_ListDouble = new ArrayList<Double>();
//错误 - Double不是Number的超类
//List<Integer> listInteger_ListNumber = new ArrayList<Number>();
//错误 - 只能接受Integer类型

List<? super Integer> listSuperInteger_ListNumber  = new ArrayList<Number>();
List<? super Integer> listSuperInteger_ListInteger = new ArrayList<Integer>();
//List<? super Integer> listSuperInteger_ListDouble  = new ArrayList<Double>();    
//错误 - Double is not a superclass of Integer

listNumber_ListNumber.add(3);
//正确 - 允许添加Integer对象到List<Number>中

//下面的代码将出现编译错误。
//他们有相同的原因:你不知道List<T>真正指向那个类,它也许不能处理Integer。
//所以你不能添加任何类(Object, Number, Integer, Double等)到List<? extends Number>
//listExtendsNumber_ListNumber.add(3);
//错误 - 不能添加Integer,list可能是List<Double>,即使List就是被定义为List<Number>也不行。
//listExtendsNumber_ListInteger.add(3);   
//错误 - 不能添加Integer,list可能是List<Double>,即使List就是被定义为List<Integer>也不行。
//listExtendsNumber_ListDouble.add(3);    
//错误 - 不能添加Integer,list可能是List<Double>, 特别是List真的是List<Double>。
//listExtendsInteger_ListInteger.add(3);  
//错误 - 不能添加Integer,list可能是List<X>,它只接受X类型的对象。

listSuperNumber_ListNumber.add(3);
//正确 - 允许添加Integer到List<Number>或者List<Object>
listInteger_ListInteger.add(3);         
//正确 - 允许添加Integer到List<Integer>
listSuperInteger_ListNumber.add(3);     
//正确 - 允许添加Integer到List<Integer>, List<Number>或List<Object>
listSuperInteger_ListInteger.add(3);    
//正确 - 允许添加Integer到List<Integer>, List<Number>或List<Object>
 
总结:
参数和返回类型是:List<Foo>
1、可以作为参数传递给List方法的类型:
  • List< Foo>
2、可以作为List方法结果的类型:
  • List< Foo>
  • List< ? super Foo>
  • List< ? super SubFoo>
  • List< ? extends Foo>
  • List< ? extends SuperFoo>
3、用原生方法可以被写入List的元素类型:
  • Foo & subtypes
4、用原生方法读取List,返回的元素类型:
  • Foo & supertypes (up to Object)
参数和返回类型是:List< ? extends Foo>
1、可以作为参数传递给List方法的类型:
  • List< Foo>
  • List< Subfoo>
  • List< SubSubFoo>
  • List< ? extends Foo>
  • List< ? extends SubFoo>
  • List< ? extends SubSubFoo>
2、可以作为List方法结果的类型:
  • List< ? extends Foo>
  • List< ? extends SuperFoo>
  • List< ? extends SuperSuperFoo>
3、用原生方法可以被写入List的元素类型:
  • None! Not possible to add.
4、用原生方法读取List,返回的元素类型:
  • Foo & supertypes (up to Object)

参数和返回类型是:List< ? super Foo>
1、可以作为参数传递给List方法的类型:
  • List< Foo>
  • List< Superfoo>
  • List< SuperSuperFoo>
  • List< ? super Foo>
  • List< ? super SuperFoo>
  • List< ? super SuperSuperFoo>
2、可以作为List方法结果的类型:
  • List< ? super Foo>
  • List< ? super SubFoo>
  • List< ? super SubSubFoo>
3、用原生方法可以被写入List的元素类型:
  • Foo & supertypes
4、用原生方法读取List,返回的元素类型:
  • Object
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值