JavaSE進(jìn)階

12.3 泛型通配符

  • 只能用于聲明變量|形參上,一般是形參類型上,表示可以接收任意
  • 不能用在
    • 1、創(chuàng)建對象,即new 后面
    • 2、聲明泛型類、泛型接口,即class和interface
    • 3、聲明泛型方法,即返回值類型前面<>中

1、匹配任意類型的通配符

/*

?* ? ?通配符,類型不確定

?* 1、用于聲明變量|形參上

?* 不能用在

?* 1、創(chuàng)建對象

?* 2、聲明泛型類、泛型接口、泛型方法

?*/

public?class?TestGenericWildcard {

public?static?void?main(String[] args) {

ArrayList<?> list?= new?ArrayList();

list?= new?ArrayList<String>();

list?= new?ArrayList<Integer>();

list?= new?ArrayList<Object>();

list = Collections.list(new StringTokenizer("this is a test"));

//但是此list不能添加任意類型的對象,除了null

list.add(null);

// list.add("");//因為?類似于Object,但不等價與Object,所以還是類型不確定,所以除了null可以給任意引用類型之外,其他類型對象都不能隨便賦

Object obj = list.get(0);//可以調(diào)用get()方法并使用其返回值。返回值是一個未知的類型,但是我們知道,它總是一個Object

System.out.println(obj);

test(new?ArrayList<Object>());

test(new?ArrayList<String>());

test(new?ArrayList<Integer>());

//編譯錯誤:不能用在創(chuàng)建對象上,右邊屬于創(chuàng)建集合對象

// ArrayList<?> list2 = new ArrayList<?>();

}

public?static?void?test(ArrayList<?> list){

list.add(null);

// list.add("");

}

//編譯錯誤:不能用在泛型方法聲明上,返回值類型前面<>不能使用?

// public static <?> void test(ArrayList<?> list){

//

// }

}

//編譯錯誤:不能用在泛型類的聲明上

/*class GenericTypeClass<?>{

}*/

2、受限泛型:上限、下限

(1)通配符指定上限

上限extends:使用時指定的類型必須是繼承某個類,或者實現(xiàn)某個接口,即<= ,如

  • ? extends Person
  • ? extends Comparable

滿足以下規(guī)則

  • List<Fruit> 滿足 List<? extends Fruit>
  • List<Apple> 滿足 List<? extends Fruit>
  • List<FujiApple> 滿足 List<? extends Fruit>
  • List<? extends Apple> 滿足 List<? extends Fruit>
  • List<?> 不滿足 List<? extends Fruit> 因為List<?> 等價于List<? extends Object>

public?static?void?main(String[] args) {

ArrayList<Fruit> list1= new?ArrayList<Fruit>();

test(list1);

ArrayList<Apple> list2= new?ArrayList<Apple>();

test(list2);

ArrayList<FujiApple> list3= new?ArrayList<FujiApple>();

test(list3);

ArrayList<? extends?Fruit> list= new?ArrayList<Fruit>();

test(list);

ArrayList<? extends?Apple> list4= new?ArrayList<FujiApple>();

test(list4);

ArrayList<? extends?Apple> list5= new?ArrayList<Apple>();

test(list5);

//編譯錯誤,因為ArrayList<?>類似于ArrayList<? extends Object>

//而且list6有可能賦值new ArrayList<String>();

//而且list6有可能賦值new ArrayList<Object>();

ArrayList<?> list6?= new?ArrayList();

// test(list6);

}

public?static?void?test(ArrayList<? extends?Fruit> list){

如果使用“? extends ?類型”接收泛型對象的時候,則不能設(shè)置被泛型指定的內(nèi)容

public?static?void?test(ArrayList<? extends?Fruit> list){

/*

?* 通通編譯錯誤

?* 只能接收使用,不能修改

?* 因為不知道list最終傳入的到底是什么樣的集合

list.add(new Fruit());

list.add(new Apple());

list.add(new Peach());*/

//此處只能是Fruit或以上,不能是Apple等子類,因為可能傳入的是ArrayList<Fruit>或ArrayList<Peach>

for(Fruit f:list){

System.out.println(f);

}

//Iterator只能使用Iterator<?>或Iterator<? extends Fruit>

Iterator<? extends Fruit> iter = list.iterator();

??????????// Iterator<Fruit> iter = list.iterator();//編譯錯誤,因為泛型不支持多態(tài)

}

(2)通配符指定下限

下限super:使用時指定的類型不能小于操作的類,即>=,如

? super Apple

存在以下規(guī)則:

  • ArrayList<Apple> ?滿足 ArrayList<? super Apple>
  • ArrayList<Fruit> ?滿足 ArrayList<? super Apple>
  • ArrayList<Object> ?滿足 ArrayList<? super Apple>
  • ArrayList<? super Apple> 滿足 ArrayList<? super Apple>
  • ArrayList<? super Fruit> 滿足 ArrayList<? super Apple>
  • ArrayList<?> 不滿足 ArrayList<? super Apple>因為List<?> 等價于List<? extends Object>,那么可能ArrayList<String>
  • ArrayList<? super FujiApple> 不滿足 ArrayList<? super Apple> 因為可能ArrayList< FujiApple>

public?static?void?main(String[] args) {

ArrayList<Apple> list1= new?ArrayList<Apple>();

test(list1);

ArrayList<Fruit> list2= new?ArrayList<Fruit>();

test(list2);

ArrayList<Object> list3= new?ArrayList<Object>();

test(list3);

ArrayList<? super?Apple> list4= new?ArrayList<Apple>();

test(list4);

ArrayList<? super?Fruit> list5= new?ArrayList<Fruit>();

test(list5);

ArrayList<? super?Fruit> list6= new?ArrayList<Object>();

test(list6);

//編譯錯誤

/* ArrayList<? super FujiApple> list= new ArrayList<FujiApple>();

test(list);*/

// //編譯錯誤,因為FujiApple是Apple的子類

// ArrayList<? super Apple> list7= new ArrayList<FujiApple>();

// test(list7);

//編譯錯誤,因為ArrayList<?>類似于ArrayList<? extends Object>

//而且list8有可能賦值new ArrayList<String>();

ArrayList<?> list8?= new?ArrayList();

// test(list8);

}

public?static?void?test(ArrayList<? super?Apple> list){}

如果使用“? super類型”接收泛型對象的時候,則能夠添加數(shù)據(jù),但是不能添加父對象

public?static?void?test(ArrayList<? super?Apple> list){

/*

?* 通通編譯錯誤

?* 只能接收本類或子類對象

?* 因為不知道list最終傳入的到底是什么樣的集合,如果傳入的是ArrayList<Apple>,那添加Fruit對象就有問題了*/

list.add(new?FujiApple());

list.add(new?Apple());

// list.add(new Fruit());

//此處只能是Object,不能是Apple,Fruit,因為可能傳入的是ArrayList<Object>

for(Object a:list){

System.out.println(a);

}

}