最近碰到一个泛型的问题, 就在网上找技术贴, 挖坟挖出个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) { } }