最近在看阿里开发手册时看到<? extends T >和<? super T>,以及PECS原则。
记录一下我的理解。
简单理解就是
- ? extends T与?super T两者用于泛型对象的读取和插入操作:
- ? extends T子类限定,被其修饰的对象只能进行读取操作,不能增删。
- ? super T超类限定,被其修饰的对象只能进行增删操作,不能读取。
测试类
class human{}
class man extends human{
private String name;
man(){}
man(String name){this.name = name;}
public String getName(){return name};
}
class xiaoming extends man{
private String name;
xiaoming(String name){
this.name = name;
}
public String getName(String name){
return name;
}
}
测试调用方法
public void test(){
//超类限定对象 可以添加本身和自己的子类
List<? super man> list = new ArrayList<man>();
list.add(new man("man1"));
list.add(new xiaoming("qwe"));
List<man> manList = new ArrayList<>();
manList.add(new man("asd"));
manList.add(new man("qwe"));
testExtends(manList);
testSuper(manList);
}
子类限定
对于传入的泛型对象只能查看,不能删改。被? extends T修饰的泛型对象,不能添加其本身,子类或者父类以及其他任一一种对象。
public void testExtends(List<? extends man> list) {
for(man m : list) {
System.out.println(m.getName());
}
System.out.println(list.get(0).getName());
System.out.println(list.isEmpty());
}
超类限定
对传入的参数可以进行修改,但是不能查看。例如下面的getName()方法就会爆红,因为传来的List<? super man> man List是Object类型,且有? super man T限定,即使加了强制转换(man)也无法识别。
public void testSuper(List<? super man> list){
System.out.println("-----进入super-----");
list.add(new man("qwee"));
list.remove(0);
System.out.println((man)list.get(0));
//上面这条语句如果加上.getName()就会报红
//因为(man)list.get(0)不能被当成man类型的对象
}
将? extends T 和 ? super T运用到实际中。? extends T 修饰的对象只负责读取,? super T修饰的对象只负责插入。就是PECS(Producer Extends, Consumer Super)原则。
接着是官方的标准用法,java.util.collection中的copy方法