泛型类型的子类及通配符的使用

最近碰到一个泛型的问题, 就在网上找技术贴, 挖坟挖出个08年的技术贴, 解决了问题

来源: http://webservices.ctocio.com.cn/wsjavtec/128/8571628_1.shtml

原文:

  在java语言中,我们通俗讲一个类是另一个类的子类型,是通过使用extends关键字去继承某一个类或者使用implements关键字去实现某些接口。

  我们不妨试想想,若果List< Integer>类型的变量可以成功赋值给List< Number>类型的变量,会出现什么情况?我们可能在程序的某个位置添加一个double类型的元素进去numList中,而实质上在 numList中其它元素都是Integer的类型的元素,这样就违背了泛型的初衷了。

  有时,我们确实希望将形如List< Integer>的List对象赋给List< Number>的变量,这时就要使用extends关键字的通配符。

  (2) 使用extends关键字的通配符

  Example2.3

  List< Integer> intList = new ArrayList< Integer>();

  List< ? extends Number> numList = intList();

  …

  numList.add(1.35); //compile error (can’t do that)

  从Example2.3看到numList这个变量,我们可以将类型参数为Number及其Number子类的List赋给它。

  记住一条规则如果你使用了”? extends T”,一般情况下,你不能往该数据结构中put元素,而你可以做的就是get元素。

  如果要往内put元素,就需要使用下面提到的super关键字的通配符。

  (3) 使用super关键字的通配符

  Example2.4

  List< Integer> intList = new ArrayList< Integer();

  List< ? super Integer> numList = intList;

  numList.add(3); //can put integer or null

  在example2.4我们可以看到< ? super Integer>的意思为,我们可以将类型参数为Integer或Integer超类的List赋给numList变量,并且可以put元素到列表 中(注意:在该例子中put进的元素只能为Integer或null类型)。

  一条比较通用的规则:如果要往List中put元素则用< ? super T>,如果要从List中get元素则用< ? extends T>,如果既要get又要put则不使用通配符。

实践下来, 用 < ? super T > 既可以add, 也可以get元素, 就是用不了 for (T t : tlist) 不过可以用 iterator来代替

/**
*  执行环境 Eclipse3.5  JDK1.5 
*/

class A {
   protected int a;
   
   public A(int value) { a = value; }

 public int get(){return a; }
}

class AA extends A{
   public AA(int value) { super(value); }
}

public static main(String[] argc){
   List< ? super A > alist = new ArrayList<A>();

    // 以下3种类型,都可以add进list
    A a  = new A(1); 
    alist.add(a);

    A a1 = new AA(2); 
    alist.add(a1);

    AA a2 = new AA(3);
   alist.add(a2);

   Iterator  aa = alist.iterator();
   while ( aa.hasnext()){
        A  theA = (A)aa.next();
       System.out.println(theA.get() );  // 输出1/2/3 
 }

    // 下面代码编译报错
    for( A theA : alist) {
   }

}
 

猜你喜欢

转载自zybing.iteye.com/blog/1537531
今日推荐