JavaSE进阶

12.3 泛型通配符

  • 只能用于声明变量|形参上,一般是形参类型上,表示可以接收任意
  • 不能用在
    • 1、创建对象,即new 后面
    • 2、声明泛型类、泛型接口,即class和interface
    • 3、声明泛型方法,即返回值类型前面<>中

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

/*

 * ?  通配符,类型不确定

 * 1、用于声明变量|形参上

 * 不能用在

 * 1、创建对象

 * 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);//可以调用get()方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object

System.out.println(obj);

test(new ArrayList<Object>());

test(new ArrayList<String>());

test(new ArrayList<Integer>());

//编译错误:不能用在创建对象上,右边属于创建集合对象

// 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:使用时指定的类型必须是继承某个类,或者实现某个接口,即<= ,如

  • ? extends Person
  • ? extends Comparable

满足以下规则

  • 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  类型”接收泛型对象的时候,则不能设置被泛型指定的内容

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();//编译错误,因为泛型不支持多态

}

(2)通配符指定下限

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

? super Apple

存在以下规则:

  • 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类型”接收泛型对象的时候,则能够添加数据,但是不能添加父对象

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);

}

}