java - 通用和删除过程

标签 java generics

我对阅读用 Java 编写的这篇文章有疑问 tutorial :

In the introduction, we saw invocations of the generic type declaration List, such as List. In the invocation (usually called a parameterized type), all occurrences of the formal type parameter (E in this case) are replaced by the actual type argument (in this case, Integer).

但如果没有限制形式类型参数不被Object代替? 为什么说E换成Integer?

此外,here ,在 Java 教程中说:

To reference the generic Box class from within your code, you must perform a generic type invocation, which replaces T with some concrete value, such as Integer:

但是,再次感谢删除,盒子类中的编译时间 T 被替换了 按对象而不是整数。整数类型仅用于转换操作。

其实还是一样的tutorial据说:

During the type erasure process, the Java compiler erases all type parameters and replaces each with its first bound if the type parameter is bounded, or Object if the type parameter is unbounded.

我真的很困惑。哪个是真相? T 是替换为 Integer 还是替换为 Object

最佳答案

你们说的是不同的东西。

教程中的引文谈到类型实例化。这与类型删除无关,后者是一个恕我直言的错误命名概念,只是意味着泛型类型在运行时不再可用。

但在编译时它们是,并且实例化发生在编译时。

要回答您的问题,“在编译时”是一个宽泛的概念。以下内容全部发生在编译时:

  1. 阅读源文件
  2. 词法分析
  3. 解析
  4. ...
  5. 类型检查
  6. ...
  7. 代码生成

请注意,该列表绝不是完整的。 但是,如您所见,在类型检查期间,编译器知道您的类型实例化并可以检查它们。

稍后,它发出字节码,由于字节码无法表示泛型,类型被“删除”,这意味着,强制转换被插入到各处。

因此,您认为“编译时间”是某种程度上所有事情同时发生的瞬间的假设是不正确的。


进一步编辑:

我认为您从字面上理解了所有这些(即“替换”一词)。当然,编译器有一些数据结构,其中保存了程序中所有项目的类型、名称和范围。

看,原则上很简单,如果我们有:

static <X> List<X> meth(X[] arr) { .... }

稍后,您会:

Integer arr = new Integer[100];
List<Integer> list = meth(arr);
Integer foo = list.get(1);

然后你正在实例化 meth 方法的类型:

static List<Integer> meth(Integer[] arr) { .... }

泛型的重点是说 meth适用于任何类型。这正是编译器检查的内容。它会知道,对于 所有 X,如果您传递一个 X 数组,您将返回一个 X 列表,因此,由于您传递了 Integer[],结果必须是 List<Integer>list分配是正确的。此外,编译器知道,对于所有 X **,如果您从 List<X> 中获取元素, 它将是一个 X。

因此,编译器注意到并检查 foo 是一个 Integer .稍后,在代码生成时,它将插入一个到 Integer 的转换,因为由于类型删除,List.get 的返回值是 Object。

另请注意,“替换”并不意味着编译器以某种方式更改您的代码。它只是从通用类型签名创建(可能是临时的)一个非通用类型签名(通过替换 - 如果你更喜欢这个 - 所有类型参数及其实际类型),并使用它来检查类型。

这就像在数学中,如果我说:请将 a 替换为 42 并检查等式是否正确:

一个 + 1 = 43

那么问这个替换发生的“确切位置”是没有意义的。很可能在您的大脑中。

关于java - 通用和删除过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19834369/

相关文章:

java - 如何将多Activity转化为少Activity?

swift - Swift 中的通用/多态搜索

c# - 是否有语法进行反向类型推断?

Java 泛型 - 使用元素列表实现接口(interface)

java - 打印通用类列表

java - 扩展 List 及其泛型

JavaFX - ScrollPane 滚动内容扭曲问题

java - 用于小型独立应用程序的 64 位 Java

java - JPA复合键+序列

java - 如何等待 HTTP 请求在 Java 中完成