java - 为什么 Java 在运行时不会删除所有类型信息?

标签 java generics type-erasure

到目前为止,我对 Java 泛型的明显错误理解是,Type Erasure 会删除所有类型信息,这样在运行时就什么都没有了。最近我偶然发现了一个代码片段,我不得不问自己:这个 hack 是如何工作的?简而言之,它表现为:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public abstract class SuperClass<T> {

    private final Type type;

    protected SuperClass(){
        ParameterizedType parameterizedType =
                (ParameterizedType) getClass().getGenericSuperclass();
        type = parameterizedType.getActualTypeArguments()[0];
    }

    public void tellMyType(){
        System.out.println("Hi, my type parameter is " + type);
    }    
}

public class Example {

    public static void main(String[] args) {
        SuperClass sc = new SuperClass<Integer>(){};
        sc.tellMyType();
    }
}

执行主类导致嗨,我的类型参数是class java.lang.Integer

这里我们可以看到,T 的类型信息在运行时也是可用的,这与我最初的理解相矛盾。

所以我的问题是:为什么编译器会保留这个?这是某些内部 JVM 行为所必需的,还是对此效果有任何合理的解释?

最佳答案

来自 http://www.artima.com/weblogs/viewpost.jsp?thread=208860 :

It turns out that while the JVM will not track the actual type arguments for instances of a generic class, it does track the actual type arguments for subclasses of generic classes. In other words, while a new ArrayList<String>() is really just a new ArrayList() at runtime, if a class extends ArrayList<String>, then the JVM knows that String is the actual type argument for List's type parameter.

在您的情况下,您正在创建参数化类型的匿名子类,因此保留了类型信息。请参阅文章以获得深入的解释。

关于java - 为什么 Java 在运行时不会删除所有类型信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2320658/

相关文章:

java通用可比较习语

java - Box2D 主体不渲染并崩溃

java - 如何使用 bat 文件在 Windows 服务器上卸载 java?

Scala 输入 : "Expected _$1, got T"

java - 什么是原始类型,为什么我们不应该使用它呢?

C++ -& CRTP 。类型删除与多态性

c++ - 我该如何创建一个类,以对对象进行类型删除,直到调用了一个函数,而没有事先指定可能的函数列表?

java - 与 Java 相比,Scala 对于泛型和通配符有哪些机制?

java - SpEL表达式利用 "contains()"字符串方法

java - 是否可以在验证后将 input.next 作为可变长度参数列表中的参数直接传递给方法? <在java中>