Java泛型在编译期被擦除,类型参数替换为上界(默认Object),导致运行时无法获取泛型信息,但字段、方法签名等声明处的泛型可通过反射有限获取。

Java泛型在编译期会被擦除,也就是说,泛型信息不会保留到运行时。类型擦除后,所有泛型参数都被替换为它们的上界(通常是 Object),而泛型类或方法在字节码中表现为“原始类型”。这不是简单的语法糖,而是 JVM 层面不支持泛型的直接体现。
泛型类的类型擦除规则
泛型类在编译后,其类型参数被擦除,类本身退化为原始类型:
- 如
List→ 编译后等价于List(即List的原始形式) -
class Box→ 擦除为{ T value; } class Box { Number value; },因为T的上界是Number - 若无显式上界(如
),默认上界为Object,所以T全部替换成Object
泛型方法的类型擦除转换
泛型方法同样经历擦除,但需注意桥接方法(bridge method)的生成:
-
→ 编译后变为T getValue() { ... } Object getValue() - 若该方法被子类重写(如子类声明
),编译器会自动生成一个桥接方法:String getValue() Object getValue(),内部调用String getValue(),以保证多态正确性 - 桥接方法对开发者透明,但可通过反射观察到(如
getDeclaredMethods()中能看到两个同名方法)
类型擦除带来的限制与应对
由于运行时泛型信息不存在,以下操作无法直接进行:
系统采用VS2008+Sql2005开发适用于中小型的酒店管理,全部采用三层架构,ASP.NET开发,运用CSS加DIV的界面布局,完整的源代码和数据库设计,是你不可多得的参考资料。 有客房管理、房间类型管理、入住和退房管理等简单功能HotelManager为网站目录DB_51aspx下为Sql2005数据库,附加即可(Sql2000格式数据库转换后稍后发布)
立即学习“Java免费学习笔记(深入)”;
- 不能用
new T()实例化泛型类型(编译错误)→ 可传入Class参数,通过clazz.getDeclaredConstructor().newInstance() - 不能使用
instanceof T(T是类型变量)→ 只能判断擦除后的上界,如obj instanceof List - 不能定义
throw new T()或catch (T e)→ 异常类型必须是具体类 - 数组创建受限:不能写
new T[10]→ 可改用new Object[10]并强制转型(带 unchecked 警告),或用ArrayList
运行时获取泛型信息的例外情况
虽然泛型被擦除,但部分结构仍保留签名信息,可通过反射有限访问:
- 字段、方法参数、返回值上的泛型类型可用
Field.getGenericType()、Method.getGenericReturnType()等获取Type对象 - 仅限“声明位置”保留的信息,例如
private List中的items; List可反射读出;但局部变量或方法调用处的List不可查 - 泛型超类/接口(如
class MyList extends ArrayList)可通过getGenericSuperclass()获取实际类型参数
基本上就这些。类型擦除是 Java 泛型的设计取舍,它保证了与旧版本的二进制兼容,也带来了一些编码约束。理解擦除时机和表现,有助于写出更健壮、可调试的泛型代码。










