泛型读书笔记-ArrayList<Integer>中Integer为什么不可以是int

377 阅读2分钟

首先这其实是泛型设计的问题

ArrayList<E>这个E是类型参数,是指明Class类型的,以提供编译器进行类型擦除用的,这里就要求必须是一个类,Object体系里面的,基本数据类型则不是一个类或者对象,是JDK中比较特殊的。

顺便拓展一下泛型的知识点:

  1. 类型擦除 无论何时定义一个泛型类型,都会自动提供一个相应的原始类型(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替换

  2. 翻译泛型表达式

    Pair<Employee> ep = ...;
    Employee buddy = ep.getFirst(); //public Object getFirst()
    

    在这个例子中,因为类型擦除的缘故,getFirst返回的是一个Object类型(使用的时候其实都是原始类型 raw type, 在类型擦除之后T已经不存在了),编译器(或者虚拟机)会自动加入强制类型转换,将Object转换成Employee。 对于这个问题虚拟机的底层操作分为两步:

    1. 对原始方法Pair.getFirst()调用
    2. 将返回的Object类型强制转换成Employee类型
  3. 翻译泛型方法

    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的类和接口设计中,一个类可以实现多个接口,但最多只能继承一个类。这里的类型参数也是一个类,所以类型限定最多只能有一个类且必须为限定列表的第一个,而接口限定则可以有多个。

泛型转换

  • 虚拟机中没有泛型,只有普通的类和方法
  • 所有的类型参数都用它们的限定类型替换
  • 桥方法被合成来保持多态
  • 为保持类型安全性,必要时插入强制类型转换