[java基础] 泛型篇-02泛型机制

173 阅读1分钟

虚拟机没有泛型类型对象——所有对象都属于普通类。

类型擦除

类型擦除是一种机制,我们编写的泛型类型,最终会被编译器翻译为普通类,擦除类型变量,并替换为限定类型(无限定的变量用Object)。

编译器看到的代码:

public class Pair<T> {
    private T first;
    private T last;
    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() {
        return first;
    }
    public T getLast() {
        return last;
    }
}

虚拟机执行的代码:

// T没有限定,直接翻译为Object
public class Pair {
    private Object first;
    private Object last;
    public Pair(Object first, Object last) {
        this.first = first;
        this.last = last;
    }
    public Object getFirst() {
        return first;
    }
    public Object getLast() {
        return last;
    }
}

翻译泛型表达式

当我们使用泛型时,编译器会自动的进行强制类型转换:

// 编译器的语句
Pair<String> p = new Pair<>("Hello", "world");
String first = p.getFirst();
String last = p.getLast();
// 虚拟机实际执行:(因为在虚拟中进行了类型擦除)
Pair p = new Pair("Hello", "world");
String first = (String) p.getFirst();
String last = (String) p.getLast();

泛型的局限

类型参数T不能是基本类型。

例如int,因为实际类型是Object,Object类型无法持有基本类型。

运行时类型查询只适用于原始类型

虚拟机中的对象只有一个特定的非泛型类型。比如Pair<String>,在虚拟机中只有Pair。 ,getClass方法总是返回原始类型:

Pair<String> stringPair = ...;
Pair<Interger> intergerPair = ...;
stringPair.getClass() ==intergerPair.getClass() // true

不能创建参数化类型的数组

不能实例化参数化类型的数组,例如:

Pair<String>[] table = new Pair<String>[10]; 因为在类型擦除后,table的类型是Pair[],数组会记住它的元素类型,如果试图存储其他类型的元素,就会抛出一个Array-StoreException异常

不能实例化类型变量

不能使用像new T(...)new T[...]T.class这样的表达式中的类型变量。 解决办法:

  • Class.newInstance方法
  • Supplier 函数式接口 (todo 还不理解)