通配符在泛型中的应用
先定義類
class A {public void fun() {System.out.println("A");} }class B extends A {@Overridepublic void fun() {System.out.println("B");}}class C extends B {@Overridepublic void fun() {System.out.println("C");} }1. 為什么在泛型中需要通配符?
ArrayList<A> ls = new ArrayList<B>();//compile error
即使A是B的父類,這是因?yàn)锽的list不是A的list的子類
所以這就需要通配符
2. extends
ArrayList<? extends A> arrlist = new ArrayList<B>();
arrlist可以指定A或者A的子類的ArrayList
但是
arrlist.add(new B());
arrlist.add(new A());
就會有編譯錯誤,這是因?yàn)閍dd 的參數(shù)是 ? extends A, 是A的子孫類,所以不能傳入任何對象。
arrlist.contains(new A());
arrlist.indexOf(new A());
以上兩條語句是正確,因?yàn)閏ontains和indexOf的參數(shù)是Object
A a= arrlist.get(0);//ok, 因?yàn)榉祷氐氖?? extends A, 是A或者A的子類,所以可以賦值給類A
B b = arrlist.get(0);//error, 不能保證返回的一定是B或者B的子類
如果這樣寫:
public class Factory<T> {
}
class part {
public String toString () {
return getClass().getSimpleName();
}
}
class filter extends part {
}
class fuel extends filter {
}
class A extends Factory<part> {
}
class B extends A {
}
class C extends Factory<filter> {
}
List<Factory<? extends A>> ls = new ArrayList<Factory<? extends A>>();
ls.add(new A());
ls.add(new B());
ls.add(new C());
這樣寫是Ok的
3. super
?
public static void write(List<? super B> ls) {//ls 要求容器內(nèi)的元素必須是類B,或者B的父類,所以在add的時候,//只能添加B 或者B的孩子,這是因?yàn)椴荒艽_保ls的泛化的元素是A,只能確認(rèn)至少是B,即B是下界ls.add(new B());ls.add(new C());//ls.add(new A());//不能添加A}public static void main(String[] args) {// TODO Auto-generated method stub//List<A> ls = new ArrayList<A>();//okList<B> ls = new ArrayList<B>();//okwrite(ls);for (A a : ls)a.fun(); }http://blog.csdn.net/lonelyroamer/article/details/7927212
通配符有三種:
1、無限定通配符?? 形式<?>
2、上邊界限定通配符 形式< ? extends Number>??? //用Number舉例
1、泛型中的?通配符
如果定義一個方法,該方法用于打印出任意參數(shù)化類型的集合中的所有數(shù)據(jù),如果這樣寫
[java]?view plaincopy
語句printCollection(listInteger);報(bào)錯
The method printCollection(Collection<Object>) in the type GernericTest is not applicable for the arguments (List<Integer>)
這是因?yàn)榉盒偷膮?shù)是不考慮繼承關(guān)系就直接報(bào)錯。
這就得用?通配符
[java]?view plaincopy
在方法public static void printCollection(Collection<?> collection){}中不能出現(xiàn)與參數(shù)類型有關(guān)的方法比如collection.add();因?yàn)槌绦蛘{(diào)用這個方法的時候傳入的參數(shù)不知道是什么類型的,但是可以調(diào)用與參數(shù)類型無關(guān)的方法比如collection.size();
總結(jié):使用?通配符可以引用其他各種參數(shù)化的類型,?通配符定義的變量的主要用作引用,可以調(diào)用與參數(shù)化無關(guān)的方法,不能調(diào)用與參數(shù)化有關(guān)的方法。
?
?
2、泛型中的?通配符的擴(kuò)展
1:界定通配符的上邊界
Vector<? extends 類型1> x = new Vector<類型2>();
類型1指定一個數(shù)據(jù)類型,那么類型2就只能是類型1或者是類型1的子類
Vector<? extends Number> x = new Vector<Integer>();//這是正確的
Vector<? extends Number> x = new Vector<String>();//這是錯誤的
?
2:界定通配符的下邊界
Vector<? super 類型1> x = new Vector<類型2>();
類型1指定一個數(shù)據(jù)類型,那么類型2就只能是類型1或者是類型1的父類
Vector<? super Integer> x = new Vector<Number>();//這是正確的
Vector<? super Integer> x = new Vector<Byte>();//這是錯誤的
?
提示:限定通配符總是包括自己
總結(jié)
以上是生活随笔為你收集整理的通配符在泛型中的应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java注释Override、Depre
- 下一篇: 使用svm的一个常见错误