通配符:?
类A是类B的父类,G<A>和G<B>是没有关系的,二者共同的父类是:G<?>
/*
*/
@Test
public void test3(){
List<Object> list1 = null;
List<String> list2 = null;
List<?> list = null;
list = list1;
list = list2;
//编译通过
// print(list1);
// print(list2);
//
List<String> list3 = new ArrayList<>();
list3.add("AA");
list3.add("BB");
list3.add("CC");
list = list3;
//添加(写入):对于List<?>就不能向其内部添加数据。因为不知道?的类型
//除了添加null之外。 因为类的默认值都为null
// list.add("DD");
// list.add('?');
list.add(null);
//获取(读取):允许读取数据,读取的数据类型为Object。
//我们可以调用get()方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object。
Object o = list.get(0);
System.out.println(o);
}
public void print(List<?> list){
Iterator<?> iterator = list.iterator();
while(iterator.hasNext()){
Object obj = iterator.next();
System.out.println(obj);
}
}
=====================================================================
? extends A:
G<? extends A> 可以作为G<A>和G<B>的父类,其中B是A的子类
? super A:
G<? super A> 可以作为G<A>和G<B>的父类,其中B是A的父类
看下面的代码(64-87行)理解这两句话:
/*
3.
*/
@Test
public void test4(){
//上限Person
List<? extends Person> list1 = null;
List<? super Person> list2 = null;//下限是Person
List<Student> list3 = new ArrayList<Student>();
List<Person> list4 = new ArrayList<Person>();
List<Object> list5 = new ArrayList<Object>();
//list1可以作为list3和list4的父类 ,其中list3是list4的子类。
//extends可以看成 <= ; 在此代码中 <=Person 的类都可以赋值给list1。
list1 = list3;
list1 = list4;
// list1 = list5; 编译不通过;因为Object > Person
**相反的,super可以看成 >=;在下面代码中,>=Person的类都可以赋值给list2.**
-----
// list2 = list3; 编译不通过,因为list3(Student) < Person
list2 = list4;
list2 = list5;
---------------------
//读取数据:
list1 = list3;
Person p = list1.get(0); // List<? extends Person> 最大就是Person 要覆盖所有可能。
//Student s = list1.get(0);
//编译不通过,list1.get(0)的值可能是Persn也可能是Student类, 如果返回的值是Person类,用Student去接收会出错的。
//要用最大的类型person(上限)接收类型
//子类可以赋值给父类,反过来不行
list2 = list4;
Object obj = list2.get(0);
编译不通过 因为list2下限是Person ,可能有比person大的类过来,怎么能用person接收呢?类似上个说明。
// Person obj = list2.get(0);
===========================================================
//写入数据:
//编译不通过
// list1.add(new Student());
/* Student虽然是Person的子类,但是<? extends Person> 代表 <= Person(没有下限,只有上限是Person。) 还有比Student更小的类,
父类不可以赋值给子类*/
当你将一个变量声明为List<? extends Person>时,它表示一个未知类型的列表,该类型是Person的子类型或扩展类型。
它可以是Student、Teacher或Person的任何其他子类。
然而,编译器无法在运行时确定list1可以持有的具体Person子类型。
它可能是Student或任何其他子类,因此向这样的列表中添加元素是不安全的。
编译器会阻止你向列表中添加元素,因为无法保证被添加的元素与未知子类型兼容。
如果你想向列表中添加元素,应该将其声明为List<Person>,而不是List<? extends Person>。这样,
列表可以保存任何Person类型或其子类的对象,包括Student,你就可以将Student对象添加到列表中而不会出现编译错误。
//编译通过 因为list2下限是Person 不能添加比Person大的类了。因为通配符(?)可能是比Person大的。
list2.add(new Person());
list2.add(new Student());//Student比Person还小 也可以添加。
}
}
===========
## 注意点
============
~~~java
//注意点1:
public static <?> voidtest(ArrayList<?> list){
//编译错误:不能用在泛型方法声明上,返回值类型前面<>不能使用?
}
//注意点2:
class GenericTypeClass<?>{
//编译错误:不能用在泛型类的声明上
}
//注意点3:
ArrayList<?> list2 = new ArrayList<?>();
//编译错误:不能用在创建对象上;右边属于创建集合对象
List<?> list = null;//这种是可以的。
通配符可以用在一般方法的参数上和对象的声明上。
~~~
##
因篇幅问题不能全部显示,请点此查看更多更全内容