标签:4行 测试 https 高效 method from ima 往里面 table
前段时间看《Java编程思想》泛型时对 <? extends T>与<? super T>很懵逼,接着看到泛型与集合的更蒙蔽,随后又翻开《码出高效》时,对这些知识点才恍然大悟,发篇博客记录下
List、List<Object>、List<?> 的三者的区别以及 <? extends T>与<? super T> 的区别
List、List<Object>、List<?>
代码验证:(感觉用博客的页面插入代码效果不好,在此处贴了图片,代码在文章末尾补上)
<? extends T>与<? super T>
List
<? extends T>的场景是put功能受限,而<? super T>的场景是get功能受限。
代码示例如下(以加菲猫、猫、动物为例,说明extends和super的详细语法差异0):
在代码第二段中的23行编译时报错:
Type mismatch: cannot convert from List
因为List
在第三段代码的36、36、37行均编译出错:
The method add(capture#1-of ? extends Cat) in the type List<capture#1-of ? extends Cat> is not applicable for the arguments (Animal)
无法进行add操作,这是因为除null外,任何元素都不能添加进<? extends T>集合中。但<?super Cat>可以往里面添加元素,但只能添加Cat自身即其子类对象,如上面代码中的41、42行。因为猫的笼子中只能关猫,不能关其他动物,如代码中的40行。
在上面代码中的第四段中,所有的 List<? super T>集合 都能执行get方法返回元素,但是泛型丢失,只能返回object对象,如上面代码中的46、47、48行。List<? extends T>集合 可以返回带类型的元素,但只能返回Cat自身及其父类对象,因为子类对象被擦除了,如代码中的50到54行。
附:
第一张图片中的代码
import java.util.ArrayList;
import java.util.List;
public class TestArrayList {
public static void main(String[] args) {
//第一段:泛型出现之前集合定义方式
List a1 =new ArrayList();
a1.add(new Object());
a1.add(new Integer(10));
a1.add(new String("string"));
//第二段:把a1引用赋值给a2,(a2与a1的区别是增加了泛型限制)
List<Object> a2 =a1;
a2.add(new Object());
a2.add(new Integer(20));
a2.add(new String("string2"));
a2.add(25);
//List<Object> 接受其他泛型赋值时,会报异常(因为在下面例子中List<Integer>不能转为List<Object>)
List<Integer> aint = new ArrayList<Integer>();
List<Object> a22 =aint;//Type mismatch: cannot convert from List<Integer> to List<Object>
//第三段:把a1引用赋值给a3,(a3与a1的区别是增加了泛型<Integer>)
List<Integer> a3 = a1; //此时如果遍历a3则会报类型转换异常ClassCastException
a3.add(new Integer(20));
//下面两行编译出错,不允许增加非Integer类型进入集合
a3.add(new Object());//The method add(Integer) in the type List<Integer> is not applicable for the arguments (Object)
a3.add(new String("string2"));
//第四段:把a1引用赋值给a4,a4与a1的区别是增加了通配符
List<?> a4 = a1;
//允许删除和清除元素
a4.remove(0);
a4.clear();
//编译错误,不允许添加任何元素
a4.add(new Object());//The method add(capture#3-of ?) in the type List<capture#3-of ?> is not applicable for the arguments (Object)
a4.add(new Integer(20));
a4.add(new String("string2"));
}
}
第二张图片中的代码
import java.util.ArrayList;
import java.util.List;
class Animal{}
class Cat extends Animal{}
class Garfield extends Cat{}
//用动物,猫,加菲猫的继承关系说明extends与super在集合中的意义
public class AnimalCatGarfield {
public static void main(String[] args) {
//第一段:声明第三个依次继承的集合:Object>动物>猫>加菲猫 三个泛型集合可以理解为三个不同的笼子
List<Animal> animal = new ArrayList<Animal>(); //动物
List<Cat> cat = new ArrayList<Cat>(); //猫
List<Garfield> garfield = new ArrayList<Garfield>(); //加菲猫
animal.add(new Animal());
cat.add(new Cat());
garfield.add(new Garfield());
//第二段:测试赋值操作 以Cat为核心,因为它既有子类又有父类
//下行编译出错。只能赋值Cat或Cat子类集合
List<? extends Cat> extendsCatFromAnimal = animal;
List<? super Cat> superCatFromAnimal = animal;
List<? extends Cat> extendsCatFromCat = cat;
List<? super Cat> superCatFromCat = cat;
List<? extends Cat> extendsCatFromGarfield = garfield;
//下行编译出错。只能赋值Cat或着Cat父类集合
List<? super Cat> superCatFromGarfield = garfield;
//第三段:测试add方法
//下面三行中所有的<? extends T>都无法进行add操作,编译出错
extendsCatFromCat.add(new Animal());
extendsCatFromCat.add(new Cat());
extendsCatFromCat.add(new Garfield());
//下行编译出错。只能添加Cat或者Cat的子类集合。
superCatFromCat.add(new Animal());
superCatFromCat.add(new Cat());
superCatFromCat.add(new Garfield());
//第四段:测试get方法
//所有的super操作能够返回元素,但是泛型丢失,只能返回object对象
Object object1 = superCatFromCat.get(0);
Animal object = superCatFromCat.get(0);//Type mismatch: cannot convert from capture#8-of ? super Cat to Animal
Cat object3 = superCatFromCat.get(0);//
//以下extends操作能够返回元素
Animal catExtends3 = extendsCatFromCat.get(0);
Object catExtends2 = extendsCatFromCat.get(0);
Cat catExtends1 = extendsCatFromCat.get(0);
//下行编译错误。虽然Cat集合从Garfield赋值而来,但类型擦除后,是不知道的
Garfield cat2 = extendsCatFromGarfield.get(0);
}
}
一文搞懂List 、List<Object>、List<?>的区别以及<? extends T>与<? super T>的区别
标签:4行 测试 https 高效 method from ima 往里面 table
原文地址:https://www.cnblogs.com/minghaiJ/p/11259346.html