当前位置: 首页 > 面试题库 >

为什么在运行时未在Java中擦除所有类型信息?

申奇希
2023-03-14
问题内容

到目前为止,我对Java Generics的理解显然是错误的,即Type
Erasure删除了所有类型信息,从而在运行时几乎没有剩余。最近,我偶然发现了一个代码片段,不得不问自己:这种破解是如何工作的?简化后,它表示为:

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();
    }
}

执行Main Class结果Hi, my type parameter is class java.lang.Integer

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

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


问题答案:

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

事实证明,尽管JVM不会跟踪泛型类实例的实际类型参数,但它会跟踪泛型类的子类的实际类型参数。换句话说,虽然new
ArrayList<String>()实际上ArrayList()在运行时只是一个new
,但是如果一个class扩展了ArrayList<String>,那么JVM就会知道这String是的type参数的实际List类型参数。

在您的情况下,您正在制作参数化类型的匿名子类,因此将保留类型信息。请参阅本文以获取详细说明。



 类似资料:
  • 问题内容: 考虑这个例子,该例子取自一本书,其中有一个超类Gen和一个子类Gen2 … 现在,该书指出以下内容将无法编译(让我们在主要方法中假设其内容) 由于泛型类型信息在运行时不存在,因此无法编译。如果在运行时不存在,什么时候存在?我以为它不会在编译时存在,而会在运行时存在。当然,以下适用于带有通配符的运行时… 因此要澄清,我的问题是为什么泛型类型信息在运行时不存在?我是否忽略了一个简单的概念?

  • 问题内容: 我有以下代码: 实际上,它可以像人们期望的那样进行编译和工作。但是,如果将返回类型设为相同,则不会编译,因为预期的“名称冲突:method(Pair)和method(Pair)具有相同的擦除” 鉴于返回类型不是方法签名的一部分,这种重载怎么可能? 问题答案: 考虑以下4种方法 根据当前的Java语言规范, m1和m2无法共存,m3和m4也不能共存。因为它们具有相同的参数类型。 M1和M

  • 问题内容: 类型擦除应该擦除所有泛型信息…如果是这种情况,那么像GSON这样的库如何使用泛型来确定反序列化为哪种类型? 例如 这将反序列 化为 将反序列化为 因此以某种方式在运行时使用通用信息。 问题答案: 类型擦除不会擦除所有类型信息。它不会从类,字段,返回类型和参数定义中将其删除。保留以下示例中的类型信息: 这是可以通过反射实现的。您可以检查给定的是否是该类,将其强制转换为该类并获取类型信息。

  • 我正在将代码从Processing移植到Netbeans Java。我在运行多个java类时遇到问题。我的代码分为14个类,其中我的主要类仅包括这组代码: 无论项目何时运行,都只会弹出一个灰色背景的小屏幕,然而,仅此而已。在我看来,它无法读取其他13个类的所有代码。有什么想法吗?

  • 问题内容: Java在Java 5中引入了带有泛型的类型擦除,因此它们可以在Java的旧版本上使用。这是兼容性的折衷。从那以后,我们就失去了兼容性–字节码可以在JVM的更高版本上运行,但不能在较早的版本上运行。这似乎是最糟糕的选择:我们丢失了类型信息,并且仍然无法在较旧版本上运行针对较新版本JVM编译的字节码。发生了什么? 具体来说,我是在问是否存在任何技术原因,导致无法在下一版JVM中删除类型擦

  • 考虑下面的代码示例: 用Java编译时 警告:(7,39)java:需要未经检查的转换: