1.List、 List<Object>、 List<?>三者的区别
- List完全没有类型限定和赋值限定
- List<Object>和List一样没有类型限定,但是不能接受其他泛型赋值
List<Object>与List<Integer>不可以相互赋值,类型不是协变的。 - List<?>在没有赋值以前,可以接受任何类型的集合赋值。允许删除,不允许添加。
List<?>的作用:1)作为参数接受外部集合;2)返回一个不知道具体类型的集合
2.<T>、 <? extends T>、 <? super T>
- List<T>只能放置一种类型
怎样才能放置多种受泛型约束的类型呢? - <? extends T>是Get First,适用于消费集合元素为主的应用场景。
可以接受任何T及T子类的集合,上界为T。
null可表示任何类型,除了null外,任何元素都不能添加进该集合内。因为不知道具体集合到底是T的哪种子类型。 - <? super T>是Put First,适用于生成集合元素为主的场景。
可以接受给T及T的父类集合,下界为T。
可添加,因为父类可接受子类的赋值。取数据时,不知道具体类型,相当于泛型丢失。 - 总结:PECS——Producer Extends Consumer Super(有点跟上述介绍反着来,但是是从不同角度介绍同一件事,上面是从用户角度,而这里是从集合角度。用户消费,则集合就是生产)
如果你只需要从集合中获得类型T , 使用<? extends T>通配符,集合就是生产者;
如果你只需要将类型T放到集合中, 使用<? super T>通配符,集合就是消费者;
如果你既要获取又要放置元素,则不使用任何通配符。例如List<T>;
3.<T extends Comparable<? super T>>
- Comparable<T>中的T指明的是另一个比较对象的类型,Comparable<? super T>表明另一个对象可为T的父类型。
public interface Comparable<T> {
public int compareTo(T o);
}
3.1 直接代入验证法
-
以GregorianCalendar为例
public class GregorianCalendar extends Calendar {
public abstract class Calendar implements Serializable, Cloneable,
Comparable<Calendar> {
如下编译正确,可以理解为<GregorianCalendar extends Comparable<Calendar>>,只要带入进去即可,正好符合。
import java.util.GregorianCalendar;
class Demo<T extends Comparable<? super T>>{}
public class Test1
{
public static void main(String[] args) {
Demo<GregorianCalendar> p = null; // 编译正确
}
}
如果去掉super,则是错误的,因为<T extends Comparable<T>>相当于<GregorianCalendar extends Comparable<GregorianCalendar>>但是GregorianCalendar并没有实现Comparable<GregorianCalendar>而是实现的Comparable<Calendar>:
import java.util.GregorianCalendar;
class Demo<T extends Comparable<T>>{}
//这里把? super去掉了
public class Test
{
public static void main(String[] args) {
Demo<GregorianCalendar> p = null;
}
}
3.2 将泛型代入到Comparable接口的compareTo方法
Comparable<T>和Comparable<? super T>如果调用对象是Calendar,另外一个对象可以是Calendar或GregorianCalendar,因为子类型可以赋值给父类型。但是如果调用对象是GregorianCalendar,另外一个对象不能是Calendar,这里就碰到了异常。? super T可以解决这个异常。
- T extends Comparable<T>的compareTo方法如下:
public int compareTo(T other)
如果T为GregorianCalendar,则肯定不能是Calendar,不能与父类进行比较 - T extends Comparable<? super T>:
public int compareTo(? super T other)
如果T为GregorianCalendar,对象可以是GregorianCalendar及其父类Calendar
对Calendar/GregorianCalendar这两个有父子关系的类来说:<T extends Comparable<? super T>>可以接受List<Calendar>,也可以接收 List<GregorianCalendar> 。而<T extends Comparable<T>>只可以接收 List<Calendar>所以,<T extends Comparable<? super T>>这样的类型参数对所传入的参数限制更少,提高了 API 的灵活性。总的来说,在保证类型安全的前提下,要使用限制最少的类型参数。