1、List ,List<?> 与 List< Object > 有区别吗?
1、我们先来看看 List 与 List< Object >
很多可能觉得 List< Object >的用法与 List 是一样的,例如很多人认为
List< Object > list;与List list;这两种定义方法是一模一样的,然而他们是不一样的
List<String> list1=new ArrayList<>();
List list2=list1;//编译通过
List<Object> list3=list1;//编译报错,不兼容的类型
从这里可以看出List list;与List< Object > list是有区别的,List 变量可以接受任何泛型的变量,而 List< Object > 则不可以。
2、我们在看看 List<?> 有什么需要注意的地方
List<Object> list1 = new ArrayList<>();
List<?> list2 = list1;
// 编译通过
list2.remove(0);
list2.clear();
list2.add(new Object());// 编译不通过
List<?> 是一个泛型,在没有赋值之前,是可以接受任何集合的赋值的,但是请注意,赋值之后就不能往里面添加元素了。
所以 List<?> 一般用来作为参数来接受外部的集合,或者返回一个不知道具体元素的集合。
2、<? extends T> 与 <? super T>你真的懂吗?
我们知道泛型 List< T > 只能放置一种类型,如果你采用 List< Object > 来放置多种类型,然后再进行类型强制转换的话,那会失去了泛型的初衷。
为了能够放置多种类型,于是有了 <? extend T> 与 <? super T>,下面先说一些你可能原本就知道的知识
1、对于 < ? extends T > a
a 这个变量可以接受 T 及其 T 子类的集合,上界为 T,并且从 a 取出来的类型都会被强制转换为 T
//Cat extends Animal,RedCat extends Cat
List<Animal> animals = new ArrayList<>();
List<Cat> cats = new ArrayList<>();
List<RedCat> redCats = new ArrayList<>();
// 可以通过编译
List<? extends Cat> extendsCat = redCats;
// 不能通过编译,因为只能接受 Cat 及其子类的集合
extendsCat = animals;
// 重点注意:下面三行都不能通过编译
extendsCat.add(new Animal());
extendsCat.add(new Cat());
extendsCat.add(new RedCat());
// 重点注意:可以通过编译
extendsCat.add(null);
注意:< ? extends T>最需要注意的是,就是不能向里面添加除null之外的其他所有元素,这个和 List<?> 有点类似
2、现在说说 <? super T>
它和 <? extends T> 有点相反。对于<? super T> a,a 这个变量可以接受 T 及其 T 父类的集合,下界为 T,并且从 a 取出来的类型都会被转换为 Object。
List<Animal> animals = new ArrayList<>();
List<Cat> cats = new ArrayList<>();
List<RedCat> redCats = new ArrayList<>();
// 可以通过编译
List<? super Cat> superCat = animals;
// 不能通过编译,因为只能接受 Cat 及其父类的集合
superCat = redCats;
// 重点注意:不能通过编译,只能添加 Cat 及其 Cat 的子类
superCat.add(new Animal());
// 重点注意,可以通过编译
superCat.add(new Cat());
superCat.add(new RedCat());
superCat.add(null);
注意,<? super T>最需要注意的是,虽然可以接受 T 及其父类的赋值,但是只能向里面添加 T 及其 T 的子类。
总结
1、List<? extends T> a ,可以把 a 及其 a 的子类赋给 a,从 a 里取的元素都会被强制转换为 T 类型,不过需要注意的是,不能向 a 添加任何除 null 外是元素。
2、List<? super T> a ,可以把 a 及其 a 的父类赋给 a,从 a 里取的元素都会被强制转换为 Object 类型,不过需要注意的是,可以向 a 添加元素,但添加的只能是 T 及其子类元素。