泛型定义中的通配符

阅读更多
泛型定义中的通配符

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

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

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

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

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

List listExtendsNumber_ListNumber = new ArrayList();
List listExtendsNumber_ListInteger = new ArrayList();
List listExtendsNumber_ListDouble = new ArrayList();

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

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

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

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

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

listSuperNumber_ListNumber.add(3);
//正确 - 允许添加Integer到List或者List
listInteger_ListInteger.add(3);         
//正确 - 允许添加Integer到List
listSuperInteger_ListNumber.add(3);     
//正确 - 允许添加Integer到List, List或List
listSuperInteger_ListInteger.add(3);    
//正确 - 允许添加Integer到List, List或List   
   
  
总结:
参数和返回类型是:List
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

你可能感兴趣的:(泛型,通配符)