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

在Java中,为什么在运行时没有通用类型信息?

姬昊焱
2023-03-14
问题内容

考虑这个例子,该例子取自一本书,其中有一个超类Gen和一个子类Gen2 …

class Gen<T> { }

class Gen2<T> extends Gen<T> { }

现在,该书指出以下内容将无法编译(让我们在主要方法中假设其内容)

Gen2<Integer> obj = new Gen2<Integer>();

if (obj instanceof Gen2<Integer>) {

    //do something
}

由于泛型类型信息在运行时不存在,因此无法编译。如果在运行时不存在,什么时候存在?我以为它不会在编译时存在,而会在运行时存在。当然,以下适用于带有通配符的运行时…

if (obj instanceof Gen<?>) {

    //do something else

}

因此要澄清,我的问题是为什么泛型类型信息在运行时不存在?我是否忽略了一个简单的概念?


问题答案:

问题在于,泛型并不总是出现在java中(我认为他们在1.5中添加了泛型)。因此,为了能够实现向后兼容性,提供了类型擦除功能,该功能可以在编译代码以实现该目标的同时有效地擦除通用类型信息。

摘自官方文件的相关部分:

在类型擦除过程中,Java编译器将擦除所有类型参数,如果类型参数是有界的,则将每个参数替换为其第一个边界;如果类型参数是无界的,则将其替换为对象。

所以这段代码例如

public class Node<T extends Comparable<T>> {

    private T data;
    private Node<T> next;

    public Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    }

    public T getData() { return data; }
    // ...
}

在类型擦除后变为:

public class Node {

    private Comparable data;
    private Node next;

    public Node(Comparable data, Node next) {
        this.data = data;
        this.next = next;
    }

    public Comparable getData() { return data; }
    // ...
}

但是,如果您沿着反射的路径前进,就像 光剑
一样,有一种方法可以复活其中一些类型的信息:既强大又危险。



 类似资料:
  • 问题内容: 到目前为止,我对Java Generics的理解显然是错误的,即Type Erasure删除了所有类型信息,从而在运行时几乎没有剩余。最近,我偶然发现了一个代码片段,不得不问自己:这种破解是如何工作的?简化后,它表示为: 和 执行Main Class结果。 我们在这里看到的是,T的类型信息在运行时也可用,这与我的最初理解相矛盾。 所以我的问题是:为什么编译器会保留此?这对于某些内部JV

  • 问题内容: 我该如何实现? 到目前为止,我尝试过的所有操作始终返回类型,而不是所使用的特定类型。 问题答案: 正如其他人所提到的,只有在某些情况下才能通过反思来实现。 如果你确实需要类型,这是通常的(类型安全的)解决方法:

  • 问题内容: 我该如何实现? 到目前为止,我尝试过的所有操作始终返回类型,而不是所使用的特定类型。 问题答案: 正如其他人所提到的,只有在某些情况下才能通过反射来实现。 如果你确实需要类型,这是通常的(类型安全)解决方法:

  • 问题内容: 我注意到了Collections.sort的规格: 为什么这里需要“ ”?如果是extend ,那么我们是否不能保证a 仍然能够比较两个对象而没有“ ”部分? 换句话说,给出以下代码: 为什么即使不为Collections.sort()的声明指定“ ”,编译器也不足够聪明地知道这是可以的? 问题答案: Josh Bloch今年在Google I / O上做了一个名为“ 有效Java重新

  • 问题内容: 该文件说 注意 Swift类不能从通用基类继承。您定义而未指定超类的类将自动成为您要构建的基类。” 摘录自:Apple Inc.“ Swift编程语言。” iBooks。 这对我来说没有多大意义。Objective- C具有通用基类是有原因的,并且同样的原因也适用于Swift,是吗?管理着保留/释放语义,对默认的实现,和。所有这些功能在Swift中也可用。 (Objective-C和S

  • 问题内容: 在Java中,为什么以下代码行不起作用? 如果我将其更改为 起初,我以为您可能没有接口列表,但是我可以创建一个很好的接口。 有想法吗? 问题答案: 泛型类型比较古怪。 表示或任何子类型,但仅表示。如果您想要一个子类型,您需要 我怀疑你可以用 无法执行此操作的原因是,您可以使用对引用的引用,并且必须谨慎使用额外的间接级别。 使用泛型,您可以有两个间接级别,这会给您带来问题,因此它们更容易