泛型擦除

0 阅读1分钟

在Java中,泛型擦除是编译器的一种机制,它在编译阶段移除泛型类型的信息。这意味着在运行时,泛型类型的信息不会被保留。

原理

泛型擦除的基本原理是:所有的泛型类型信息都会在编译时被移除,并被其边界(或Object,如果没有指定边界)替换。因此,泛型类型不会在运行时存在。

例子

考虑以下泛型类:

public class Box<T> {
    private T value;

    public Box(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

在编译过程中,这个类会被转换成:

public class Box {
    private Object value;

    public Box(Object value) {
        this.value = value;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }
}

边界

如果泛型类型有边界,例如T extends Number,那么在擦除后,类型将被其上界替换:

public class Box<T extends Number> {
    private T value;

    public Box(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

会被转换成:

public class Box {
    private Number value;

    public Box(Number value) {
        this.value = value;
    }

    public Number getValue() {
        return value;
    }

    public void setValue(Number value) {
        this.value = value;
    }
}

限制和影响

  1. 运行时类型检查的限制

    • 泛型类型在运行时被擦除,因此不能直接创建泛型数组:
      // 编译错误
      Box<Integer>[] boxes = new Box<Integer>[10];
      
  2. 类型擦除后不能区分重载方法

    • 以下两个方法在擦除后将具有相同的签名,导致编译错误:
      public void method(List<String> list) { }
      public void method(List<Integer> list) { }
      

总结

泛型擦除是Java泛型类型系统的重要组成部分,它在编译时移除了泛型类型的信息,从而保持了与非泛型代码的兼容性。