泛型通配符
泛型在继承方面的体现
虽然类A是类B的父类,但是G<A> 和G<B>二者不具备子父类关系,二者是并列关系。
补充:类A是类B的父类,A<G> 是 B<G> 的父类
下面我举个例子:例子1:
@Test
public void test1(){
Object obj = null;
String str = null;
obj = str;//此时可以赋值
Object[] arr1 = null;
String[] arr2 = null;
arr1 = arr2;//此时也可以赋值
//但是下列这种情况编译不通过,因为不是Date与String不是子父类关系
// Date date = new Date();
// str = date;
这个例子可以看出:
子父类关系是可以相互赋值的,而并列关系却不能赋值,因为这Date与String没有关联关系,两个类是不同类型的。
所以我们可以拿泛型的例子:
List<Object> list1 = null;
List<String> list2 = new ArrayList<String>();
//此时的list1和list2的类型不具有子父类关系
//编译不通过
// list1 = list2;
例2:
//print(list1);不通过
// print(list2);不同过
public void print(List<T> list){
Iterator<T> iterator = list.iterator();
while(iterator.hasNext()){
Object obj = iterator.next();
System.out.println(obj);
回到上面的例子,以上情况就不能使用同一个方法,需要大量的重载print的方法。如何解决上面的问题?总不能为了定义一个新的方法来处理List类型的类,这显然与java中的多台理念相违背。因此我们需要一个在逻辑上可以表示同时是List和List父类的引用类型。由此类型通配符应运而生。
那么,我们如何才能像例子1中的Str和obj一样赋值?而且使用print方法。此时我们就要使用:“通配符?"
@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之外。
// list.add("DD");
// list.add('?');
list.add(null);
//获取(读取):允许读取数据,读取的数据类型为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);
}
}
这个例子说明:通过通配符后,就可以使用方法print和相互赋值了。
此时 :
类Object是类Stirng的父类,List和List是没有关系的,二者共同的父类是:List<?>
2.有限的通配符<?>
通配符指定上限
上限extends :使用时指定的类型必须是继承某个类,或者实现某个接口,即 <=
通配符指定下限
下限super :使用时指定的类型不能小于操作的类
如下:看例子:
List<? extends Person1>
List<? super Person1>
class Person{
}
class Student extends Person{
}
@Test
public void test(){
//只能Person与Person的子类使用
List<? extends Person1> list1 = null;//(Person子类,Person]
//只能Person与Person的父类使用
List<? super Person1> list2 = null;//[Person,person父类)
List<Student1> list3 = new ArrayList<Student1>();
List<Person1> list4 = new ArrayList<Person1>();
List<Object> list5 = new ArrayList<Object>();
list1 = list3;
list1 = list4;
// list1 = list5;//Object是Person的父类。超过了界限
// list2 = list3;//小于了Person的界限,必须是Person本身与Person父类使用
list2 = list4;
list2 = list5;
在读取数据方面:
//读取数据
list1 = list4;//此时list1的类型是Person
//可以使用Person与Object接收 因为Person,Object可以接收Person和Student的值
Person1 person1 = list1.get(0);
//返回的类型可能是Person 因为Student < Person所以 不能用Student来接收Person的值
// Student s = list1.get(0);
list2 = list4;
//返回的类型可能是Person或Object的值,所以只能使用Object接收
Object obj = list2.get(0);
//返回的类型可能有Object的值,Person接收不了Object的值
// Person1 p = list2.get(0);//不能用Person接收 Person < Object
在写入数据方面
//写入数据
//编译错误,
// <? extends Person> ?不确定,要是放入Student有可能?比Student小,
// list1.add(new Student1());
// list1.add(new Person1());
// list1.add(new Object());
// <? super Person> ?不确定,?最起码可以是Person,那比Person更小的都可以
list2.add(new Student1());
list2.add(new Person1());
// list2.add(new Object());//因为[Person - Object)那么要是?是Objcet更不满足要求
最后:小白是新手,写得不好请大佬勿喷。