首先这其实是泛型设计的问题
ArrayList<E>这个E是类型参数,是指明Class类型的,以提供编译器进行类型擦除用的,这里就要求必须是一个类,Object体系里面的,基本数据类型则不是一个类或者对象,是JDK中比较特殊的。
顺便拓展一下泛型的知识点:
-
类型擦除 无论何时定义一个泛型类型,都会自动提供一个相应的原始类型(raw type),原始类型的名字就是泛型类型删去类型参数之后的泛型类型名。
比如:public class Pair<T> { private T first; private T second; public Pair(T first, T second) { this.first = first; this.second = second; } public T getFirst() {return first;} public T getSecond() {return second;} public T setFirst(T val) {this.first = val} public T setSecond(T val) {this.second = val} } ===> public class Pair<Object> { private Object first; private Object second; public Pair(Object first, Object second) { this.first = first; this.second = second; } public Object getFirst() {return first;} public Object getSecond() {return second;} public Object setFirst(Object val) {this.first = val} public Object setSecond(Object val) {this.second = val} }ArrayList<E> -> ArrayList<Object> ArrayList<E extends Comparable> -> ArrayList<Comparable> Pair<E> -> Pair<Object>这里因为E/T是一个无类型限定的变量,所以直接用Object替换
-
翻译泛型表达式
Pair<Employee> ep = ...; Employee buddy = ep.getFirst(); //public Object getFirst()在这个例子中,因为类型擦除的缘故,getFirst返回的是一个Object类型(使用的时候其实都是原始类型 raw type, 在类型擦除之后T已经不存在了),编译器(或者虚拟机)会自动加入强制类型转换,将Object转换成Employee。 对于这个问题虚拟机的底层操作分为两步:
- 对原始方法Pair.getFirst()调用
- 将返回的Object类型强制转换成Employee类型
-
翻译泛型方法
public static <T extends Comparable> T min(T[] arr) ===> public static <Comparable> Comparable min(Comparable[] arr)
类型参数限定
class Air<T extends Serializable & Comparable>
- 类型变量可以有多个限定,对于多个限定要用 & 进行分隔
- 不论T的限定是接口还是类都用extends关键字,这只是一个约定
- Java的类和接口设计中,一个类可以实现多个接口,但最多只能继承一个类。这里的类型参数也是一个类,所以类型限定最多只能有一个类且必须为限定列表的第一个,而接口限定则可以有多个。
泛型转换
- 虚拟机中没有泛型,只有普通的类和方法
- 所有的类型参数都用它们的限定类型替换
- 桥方法被合成来保持多态
- 为保持类型安全性,必要时插入强制类型转换