Java的泛型
文章目录
一、 List
、List<?>
、List<Object>
三者的区别
-
List
是原生态类型(也就是不带有实际类型参数),出了几个小小的例外,不要使用原声类型;例外1:必须在类文字中使用原生态类型,例如:
List.class
;但是,List<String>.class
和List<?>.class
是非法的;例外2:与instanceof操作符有关。由于泛型信息可以在运行时被擦除,因此在参数化而非无限制通配符类型上使用instanceof操作符时非法的。但无限制通配符在这种情况下不会产生任何作用:
o instanceof Set
和o instanceof Set<?>
是等价的; -
List<?>
是无限制通配符不能讲任何元素(除了null之外)放到
Collection<?>
中 -
List<Object>
是参数化的类型
二、数组是协变且可以具体化的;泛型是不可变的且可以被擦除的
-
数组是协变的,泛型是不可变的
如果Sub为Super的子类型,那么数组Sub[]就是Super[]的子类型;
对于任意两个不同的类型Type1和Type2,
List<Type1>
既不是List<Type2>
,也不是List<Type2>
的超类型; -
数组是具体的,泛型是可被擦除的
数组会在运行时知道和加强它们的元素类型;
泛型是通过擦除来实现的。意味着,泛型只在编译时强化它们类型信息,并在运行时丢弃(或擦除)他们呢的元素类型信息;
三、不能创建不可具体化的类型的数组
不能创建不可具体化的类型的数组,如:E[] elements = new E[DEFAULT_INITIAL_CAPACITY];
(这种写法是非法的)
解决方案有两种:
第一种:
E[] elements = (E[])new Object[DEFAULT_INITIAL_CAPACITY];
第二种:
Object[] elements = new Object[DEFAULT_INITIAL_CAPACITY];
E e = (E)elements.get(i);
四、何时使用<? extends E>
,何时使用<? super E>
<? extends E>
表示?
应当是E的子类;
确定了子类型后,每个类型都是自身的子类型;
<? super E>
表示?
应当是E的超类;
助记符:PECS
表示 producer-extends, consumer-super
如果参数化类型表示一个生产者T,就使用
<? extends T>
;如果它表示一个消费者T,就使用<? super T>
;
案例:
在构造器中使用:
public Chooser(Collection<? extends T> choices){...}
将两个集合合并成一个集合元素:(注意,返回值仍然是Set<E>
)
public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2){...}
获取一个列表的最大值:
public <T extends Comparable<? super T>> T max(List<? extends T> list){...}
所有的comparable
和comparator
都是消费者。