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