由于 java 使用擦拭法来实现泛型,导致编译器把类型<T>视为``Object,同时编译器根据`的实际情况来实现安全的强制类型转换。也就是说,虚拟机看到字节码的时候对有没有泛型毫不知情,编译器编译的时候自动的完成了类型转换和检查的工作。

  • <T>不能是基本类型,比如intdouble等,因为泛型的实际类型是Object,而Object类型无法持有基本类型。

  • 无法取得带泛型的Class,因为<T>Object类型,在编译后,所有泛型实例的getClass返回的是同一个Class实例。

  • 无法判断带泛型的Class

    例如:

    Pair<Integer> p = new Pair<>(123, 456);
    // Compile error:
    if (p instanceof Pair<String>.class) {
    }
    // 并不存在 Pair<String>.class,而是只有唯一的 Pair.class。
    
  • 不能实例化T类型。

    例如:

    public class Pair<T> {
        private T first;
        private T last;
        public Pair() {
            // Compile error:
            first = new T();
            last = new T();
        }
    }
    // first = new T(); 在擦拭后实际变成了 first = new Object(); 这样的话,创建的所有泛型到头来全成 Object 了。
    

    如果要实例化的话,需要借助Class<T>参数:

    public class Pair<T> {
        private T first;
        private T last;
        public Pair(Class<T> clazz) {
            first = clazz.newInstance();
            last = clazz.newInstance();
        }
    }
    

    上述代码借助Class参数并通过反射来实例化T类型,使用的时候,也必须传入Class。例如:

    Pair<String> pair = new Pair<>(String.class);
    

Java 的泛型是采用擦拭法实现的;

擦拭法决定了泛型<T>

  • 不能是基本类型,例如:int

  • 不能获取带泛型类型的Class,例如:Pair.class

  • 不能判断带泛型类型的类型,例如:x instanceof Pair

  • 不能实例化T类型,例如:new T()

泛型方法要防止重复定义方法,例如:public boolean equals(T obj)

子类可以获取父类的泛型类型<T>

本文转载并精简自 https://www.liaoxuefeng.com/wiki/1252599548343744/1265104600263968