首页 > 解决方案 > 了解 Java 中的类型擦除

问题描述

如果没有类型擦除,如何实现泛型?据我了解,如果我有class Foo<T>T则基本上替换为 ,Object并且编译器只有元数据可以帮助它转换为正确的参数化类型。

但是,如果实现了具体化,那么这T将是实际的参数化类型(而不是 Object)......但我不明白编译器如何能够确定是否new T()是有效的调用(即 T 可能没有无参数构造函数)。

标签: javatype-erasure

解决方案


特别是在Java中,构造函数不被子类继承,因此只要给定的参数化类型T不能缩小到特定类型,您就无法运行new T(),因为Java是静态类型的,无论是否发生物化。但是,实例化 usingnew只是使用类的一种情况

实例

对我来说,未擦除的泛型最明显的用途是能够Tinstanceof表达式中使用:

class Box<T> {
   public boolean isInst(Object obj) {
      return obj instanceof T;
   }
}

还有一个想法是查看是否T是其他类的超类或子类,或者检查与类的相等性。

静态方法

通过具体化,Java 将能够“正确地”调用static方法。T假设我们有以下类:

class Parent {
   void doSomething() { System.out.println("Parent"); }
}

class Child extends Parent {
   void doSomething() { System.out.println("Child"); }
}

有了这些定义,那么下面的代码......

class Box<T extends Parent> {

   void test() { T.doSomething(); }

   public static void main(String...args) {
      Box<Parent> parentBox = new Box<>();
      Box<Child> childBox = new Box<>();

      parentBox.test();
      childBox.test();
   }
}

...应该打印:

Parent
Child

而是打印:

Parent
Parent

这是因为被擦除T变成了。Parent

遗产

通用继承(听起来很奇怪)可能(可能)存在:

public class GenericType<T> {
   public class Inner extends T {   }

   public static void main(String...args) {
      GenericType<MyClass>.Inner obj = new GenericType<MyClass>().new Inner();
      System.out.println(obj instanceof MyClass); // Prints true
   }
}

推荐阅读