java泛型擦除是编译器将类型参数替换为object或上界类型并插入强制转换,jvm运行时无泛型信息;故无法new t[]、instanceof list,反射也拿不到实际类型参数。

Java泛型擦除不是“删除”,而是编译器在生成字节码前,把所有
javac怎么擦:看字节码最真实
泛型信息只活在源码和编译期,javac一过,就只剩原始类型。用javap -c反编译就能验证:
-
public T get()编译后变成public Object get(),返回值是areturn(Object引用返回) - 调用方拿到
Object后,编译器悄悄插一句checkcast #String——这就是你写list.get(0)却不用手动强转的原因 -
Box<integer></integer>和Box<string></string>的getClass()完全相同,因为运行时只有Box一个类
为什么不能 new T[10] 或 instanceof List
这些操作依赖运行时类型信息,但擦除后根本不存在List<string></string>这个类型——JVM只认List。
-
new T[10]❌ 编译报错:类型参数在运行时是未知的,数组创建需要具体组件类型 -
if (list instanceof List<string>)</string>❌ 编译不通过:泛型类型不可作为instanceof右操作数 - 想绕过?只能用
list instanceof List && !list.isEmpty() && list.get(0) instanceof String——但这是业务逻辑判断,不是类型检查
擦除带来的坑:反射拿不到泛型实际类型
你用field.getGenericType()能拿到java.lang.reflect.ParameterizedType,但调用getActualTypeArguments()返回的仍是Class>,不是String.class。
立即学习“Java免费学习笔记(深入)”;
- 原因:泛型类型参数在字节码里只存于
Signature属性(仅供编译器/IDE用),Class对象本身不携带运行时泛型实例信息 - workaround:靠构造函数传入
Class<t></t>,比如new GenericArray<string>(String.class, 5)</string> - Spring、MyBatis 等框架正是靠这种“类型令牌”+反射+字节码分析(如
ASM)来还原泛型上下文
真正难的不是理解“擦除”,而是意识到:所有你以为在运行时能拿到的泛型类型,其实都是编译器帮你记在源码注释、方法签名或调试信息里的幻觉——JVM眼里,只有Object和强制转换指令。










