Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java类型擦除会擦除我的泛型类型吗?

Java类型擦除会擦除我的泛型类型吗?
EN

Stack Overflow用户
提问于 2013-07-03 12:19:04
回答 5查看 1.3K关注 0票数 12

我曾认为java擦除会在编译时清除泛型类型,但是当我自己测试它时,我意识到字节码中有一些关于泛型类型的信息。

这是我的测试:

我写了两个类:

代码语言:javascript
运行
AI代码解释
复制
import java.util.*;
public class Test {
    List integerList;
} 

代码语言:javascript
运行
AI代码解释
复制
import java.util.*;
public class Test {
    List<Integer> integerList;
} 

我编译了这两个类,在泛型类的某个地方,我看到了下面这行

代码语言:javascript
运行
AI代码解释
复制
integerList{blah blah}Ljava/util/List;{blah blah}
Signature{blah blah}%Ljava/util/List<Ljava/lang/Integer;>;{blah blah}<init>

在非泛型类中:

代码语言:javascript
运行
AI代码解释
复制
integerList{blah blah}Ljava/util/List;{blah blah}<init>

显然,我在字节码中有通用信息,那么这个擦除是什么??

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-07-03 12:21:41

一些泛型类型信息存储在Signature属性中。请参阅JLS 4.84.6JVM spec 4.3.4。阅读here

关于Java语言中泛型最常见的抱怨可能是它们没有被具体化--没有办法在运行时知道List<String>List<Long>有什么不同。我已经习惯了这一点,以至于我很惊讶地遇到了Neil Gafter关于超级类型令牌的工作。事实证明,虽然JVM不会跟踪泛型类实例的实际类型参数,但它会跟踪泛型类的子类的实际类型参数。换句话说,虽然新的ArrayList<String>()在运行时实际上只是一个新的ArrayList(),但如果一个类扩展了ArrayList<String>,那么JVM就知道StringList的类型参数的实际类型参数。

Neal Gafter's blog

票数 5
EN

Stack Overflow用户

发布于 2013-07-03 12:57:18

这个擦除是什么东西??

擦除是从泛型类型到原始类型的映射。常见的短语“由于擦除”本质上是没有意义的。重要的是使用映射的规范。

这里有两个有趣的用法。

  • 它用于将方法签名从使用泛型映射到原始类型。用于重载的是原始类型的签名。这导致了“擦除”的绝大多数问题。例如,您不能在同一类型中有两个方法add(List<String>)add(List<Integer>)。重载可能不是一个好主意,也没有很大的意愿去添加这个特性。
  • 对象实例在运行时可用的类型是它被创建时使用的类型。因此,如果您强制转换为,比方说,将在运行时检查的(String),但如果您强制转换为List<String>,则只会检查该类型(List)的擦除。您可以让List<String>List<Integer>类型的变量指向完全相同的实例。实际上,您不应该在1.5和更高版本中使用(引用类型的)类型转换。

在可行的情况下,泛型信息保存在类文件中,并通过反射提供。所以你可以在类定义、超类型、字段、方法、构造函数等方面找到它。

票数 6
EN

Stack Overflow用户

发布于 2013-07-04 17:47:20

这是术语的准确使用实际上很重要的一个实例:字节码是Java虚拟机的指令集。类文件不仅包含字节码,还包含用于链接的信息(字段签名、方法签名等),用于字节码验证器、调试器等。

类型擦除意味着泛型类型信息不会转换为字节码;更具体地说,泛型类型的所有实例在字节码中共享相同的表示。同样,运行库跟踪的对象的动态类型(由cast和instanceof运算符使用,并可通过getClass()获得)对于泛型类的所有实例都是相同的,而与源代码中提供的任何类型参数无关。

您的实验证明,泛型类型信息保留在类文件中,更具体地说,保留在方法和字段签名的类型中。这并不奇怪,因为签名实际上是在编译时使用的。也可以在链接时使用,甚至可以通过反射api访问。关键的区别在于它们是字段或方法的声明类型,而不是实际对象的运行时类型。

也就是说,从Java1.5开始,我们必须区分变量的声明类型和它引用的对象的运行时类型。前者支持泛型,后者不支持。是的,这意味着编译时和运行时类型之间没有一对一的对应关系。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17447781

复制
相关文章
Java泛型,你了解类型擦除吗?
大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很小巧的概念,但同时也是一个很容易让人迷惑的知识点,它让人迷惑的地方在于它的许多表现有点违反直觉。
Java团长
2018/08/03
2.3K0
Java泛型之类型擦除类型擦除参考资料
学过C++模板的,在使用Java泛型的时候,会感觉到有点不疑问,例如:(1)无法定义一个泛型数组、无法调用泛型参数对象中对应的方法(当然,通过extends关键字是可以做到,只是比较麻烦);(2)ArrayList<Integer>和ArrayList<String>在运行时的类型是相同的。Java中的泛型有这些问题,是它的实现机制决定的,即“类型擦除”。
阿杜
2018/08/06
6280
Java泛型类型擦除问题
以前就了解过Java泛型的实现是不完整的,最近在做一些代码重构的时候遇到一些Java泛型类型擦除的问题,简单的来说,Java泛型中所指定的类型在编译时会将其去除,因此List<String> 和 List 在编译成字节码的时候实际上是一样的。因此java泛型只能做到编译期检查的功能,运行期间就不能保证类型安全。我最近遇到的一个问题如下:
用户7353950
2022/06/23
1.2K0
JAVA泛型与类型擦除
为什么要用T而不是其它字母?事实上是可以任意字符串(如Result< something >),但是为了显得专业,一般约定几个大写字母在不同场景使用。
acupt
2019/08/26
1.8K0
转:Java 泛型,你了解类型擦除吗?
大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很小巧的概念,但同时也是一个很容易让人迷惑的知识点,它让人迷惑的地方在于它的许多表现有点违反直觉。
剑影啸清寒
2019/05/26
1.4K0
带你深挖Java泛型类型擦除以及类型擦除带来的问题
大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除。Java的泛型基本上都是在编译器这个层次上实现的,在生成的字节码中是不包含泛型中的类型信息的,使用泛型的时候加上类型参数,在编译器编译的时候会去掉,这个过程成为类型擦除。
Bug开发工程师
2020/02/13
3.9K1
带你深挖Java泛型类型擦除以及类型擦除带来的问题
带你深挖Java泛型类型擦除以及类型擦除带来的问题
大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除。Java的泛型基本上都是在编译器这个层次上实现的,在生成的字节码中是不包含泛型中的类型信息的,使用泛型的时候加上类型参数,在编译器编译的时候会去掉,这个过程成为类型擦除。
业余草
2020/02/13
1.8K0
Kotlin 泛型之类型擦除
Kotlin 基于 Java 6,因此 Kotlin 天生支持泛型。但是 Kotlin 的泛型有自己的特点。
fengzhizi715
2019/06/11
1.8K0
Java 泛型擦除_泛型和泛型擦除
如果仅凭直觉来看,该程序可能会输出 false 这个结果,但在具体的环境下运行时会输出 true 。这很令人费解,这是为什么呢?
全栈程序员站长
2022/11/01
2.5K0
揭开Java 泛型类型擦除神秘面纱
大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很小巧的概念,但同时也是一个很容易让人迷惑的知识点,它让人迷惑的地方在于它的许多表现有点违反直觉。
Java技术栈
2018/09/29
9810
揭开Java 泛型类型擦除神秘面纱
大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很小巧的概念,但同时也是一个很容易让人迷惑的知识点,它让人迷惑的地方在于它的许多表现有点违反直觉。
java思维导图
2018/10/24
1.3K0
揭开Java 泛型类型擦除神秘面纱
揭开Java 泛型类型擦除神秘面纱
大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很小巧的概念,但同时也是一个很容易让人迷惑的知识点,它让人迷惑的地方在于它的许多表现有点违反直觉。
用户1257393
2018/10/26
1.1K0
Java基础篇:泛型与类型擦除
泛型的本质是 参数化类型,也就是说 将所操作的数据类型 指定为一个参数,在不创建新类的情况下,通过参数来指定所要操作的具体类型(类似于方法中的变量参数,此时类型也定义成参数形式),也就是说,在创建对象或者调用方法的时候才明确下具体的类型。可以在类、接口、方法中使用,分别称为泛型类、泛型接口、泛型方法。
全栈程序员站长
2021/12/23
1.2K0
Java基础篇:泛型与类型擦除
【进阶之路】Java的类型擦除式泛型
Java选择的泛型类型叫做类型擦除式泛型。什么是类型擦除式泛型呢?就是Java语言中的泛型只存在于程序源码之中,在编译后的字节码文件里,则全部泛型都会被替换为原来的原始类型(Raw Type),并且会在相应的地方插入强制转型的代码。
南橘
2022/03/07
1.2K0
【进阶之路】Java的类型擦除式泛型
Java语法糖之泛型与类型擦除
泛型,JDK 1.5新特性,本质是参数化类型(Parametersized Type) 的应用,即所操作的数据类型被指定为一个参数。这种参数类型可用在:
JavaEdge
2021/12/07
5840
Java语法糖之泛型与类型擦除
Java语法糖之泛型与类型擦除
泛型,JDK 1.5新特性,本质是参数化类型(Parametersized Type) 的应用,即所操作的数据类型被指定为一个参数。这种参数类型可用在:
JavaEdge
2018/05/16
1.1K0
Java语法糖之泛型与类型擦除
Java泛型擦除
语法糖只不过是一种程序的表达式,语法糖可以提高程序的可读性,语法糖经过编译后,将会恢复原来的样貌。
shysh95
2021/03/16
7700
Java泛型擦除
【说站】java泛型中类型擦除的转换
2、这个特征被称为类型删除。当泛型被删除时,他有两种转换方法。第一种是,如果泛型没有设置类型上限,泛型将转换为Object类型,第二种是如果设置了类型上限,泛型将转换为其类型上限。
很酷的站长
2022/11/23
1.3K0
【说站】java泛型中类型擦除的转换
泛型(泛型擦除)【java基础—-泛型】
Java泛型是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter),这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
全栈程序员站长
2022/11/02
2.9K0
泛型(泛型擦除)【java基础—-泛型】
初探Java类型擦除
本篇博客主要介绍了Java类型擦除的定义,详细的介绍了类型擦除在Java中所出现的场景。
SH的全栈笔记
2019/10/20
8990

相似问题

Java泛型类型擦除?

40

java泛型类型擦除

21

Java泛型类型擦除

11

Java泛型的类型擦除会导致全类型铸造吗?

44

Java泛型和类型擦除

51
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档