一直对<? super XX> 和<? extends XX>很疑惑,下面用代码来记录一下他们的区别
首先,创建三个类:
class Employee {
}
class Manager extends Employee {
}
class Ceo extends Manager {
}
他们之间的集成关系很简单,然后分别看一下他们在extends和super中的表现:
public void testExtends(List<? extends Manager> list) {
list.add(new Employee());//报错
list.add(new Manager());//报错
list.add(new Ceo());//报错
//由上面三行可以看出,extends不可以加入
/*
*报错原因:
* add(capture<? extends Manager>) int List cannot be applied to Employee/Manager/Ceo
*
*分析:
* capture<? extends Manager> :捕获到Manager的子类
*
* 整句话的意思是:
* add()方法接收的是Manager的一个不确定的子类,所以不能添加...;
*
* 先看Employee,它是Manager的父类,直接就不满足子类这个条件,所以报错
*
* 再看Manager和Ceo,它们都是一个确定的子类,不一定是list的需要的元素,所以报错
*/
Manager manager = list.get(0);
//由上面可以看出,extends可以取出,而且取出的是Manager
/*
*为甚取出的是Manager?
* list里面装的是Manager的某种不确定的子类,但是不管是哪一种,它肯定是一个Manager
*/
}
public void testSuper(List<? super Manager> list) {
list.add(new Employee());//报错
list.add(new Manager());//正常
list.add(new Ceo());//正常
//由上面三行可以看出,extends可以加入Manager及其子类,但不可以加入其父类
/*
*错误原因:
* add (capture<? super Manager>) in List cannot be applied to Employee
*
*分析:
* capture<? super Manager>: 捕获到Manager的父类;
* 整句话的意思是:
* add()方法接收的是Manager的不确定的父类,不能直接应用于Employee
*
* 可以添加Manager及其子类就正常了,这个list的元素既然是Manager的父类,那么肯定是可以用来装他的子类的啦。
*/
Object object = list.get(0);
//由上面可以看出,extends取出的是一个Object,如果要使用具体的类型,需要强制转换
/*
*为甚取出来的是一个Object呢?
* 还是因为存入元素只是指明了是Manager的父类,但是没有指明具体的类型,那么就只能给一个所有类的父类Object啦
*/
}
结论:
作为容器的元素,
<? extends XX>,容器不可以增加元素,但是可以获取元素;
<? super XX>,容器可以增加元素,但是获取的元素是Object.
然后,再来看一下他们作为参数传递时的情况:
public void test() {
List<Employee> employees = new ArrayList<>();
List<Manager> managers = new ArrayList<>();
List<Ceo> ceos = new ArrayList<>();
testExtends(employees);//报错
testExtends(managers);//正常
testExtends(ceos);//正常
//由上面三行可以看出,Extends可以接收Manager的子类
/*
*报错原因:
* testExtends(java.util.List<? extends Manager>) cannot be applied to java.util.List<Employee>
*
* 整句话的意思是:
* testExtends()接收一个List,这个List的元素是Manager的子类,
* 但是employees的元素Employee不是Manager的子类,所以不接收List<Employee>
*
* 同理,managers和ceos的元素都是Manager的子类,所以可以接收
*/
testSuper(employees);//正常
testSuper(managers);//正常
testSuper(ceos);//报错
//由上面三行可以看得出,super可以接收Manager的父类
/*
*报错原因:
* testSuper(java.util.List<? super Manager>) cannot be applied to java.util.List<Ceo>
*
* 整句话的意思是:
* testSuper()接收一个List,这个List的元素是Manager的父类,
* 但是ceos的元素Ceo不是Manager的父类,所以不接收ceos
*
* 同理,managers和employees的元素都是Manager的父类,所以可以接收
*/
}
结论:
对于作为参数传递来说,
<? extends XX> 参数接收XX的子类,不接收它自身以外的父类;
<? super XX>参数接收XX的父类,不接受它自身以外的子类。
网友评论