Java 类型擦除与桥接方法语法速查手册
Java 类型擦除与桥接方法语法速查手册 的完整教学讲解。
0. 本节阅读指引(先读这一节)
本篇是「类型擦除与桥接方法」语法速查手册,按需查阅。
零基础第一遍只读:类型擦除规则与桥接方法;反射获取泛型、泛型数组、可重写类型参数遇到再查。
前置:036 泛型详解。
类型擦除规则
基本写法:擦除为上界
// 源码:List<T> 字节码:List<Object>
// 源码:List<T extends Number> 字节码:List<Number>
// 编译后泛型类型参数被擦除
public class Box<T> {
private T value;
// 字节码中 value 类型为 Object
}
基本写法:擦除影响
// 运行时无法获取泛型类型参数
if (list instanceof List<String>) { } // 编译错误
// 不能 new 泛型类型
T t = new T(); // 编译错误
反射获取泛型
基本写法:获取字段泛型
<field>.getGenericType();
// 通过反射获取字段的参数化类型
Field f = Box.class.getDeclaredField("value");
Type t = f.getGenericType();
if (t instanceof ParameterizedType pt) {
Type[] args = pt.getActualTypeArguments();
}
基本写法:获取方法返回泛型
<method>.getGenericReturnType();
// 获取方法的泛型返回类型
Method m = clazz.getMethod("getList");
Type rt = m.getGenericReturnType();
基本写法:TypeToken 模式
// 通过子类保留泛型信息
Type type = new TypeToken<List<String>>() {}.getType();
// Gson 等库常用此模式
Type type = new TypeToken<Map<String, List<Integer>>>() {}.getType();
桥接方法
基本写法:桥接方法生成
// 子类覆盖泛型方法时编译器生成桥接方法
class StringBox extends Box<String> {
@Override public void set(String v) { super.set(v); }
// 编译器生成:public void set(Object v) { set((String) v); }
}
// 桥接方法保证多态正确
Box<String> b = new StringBox();
b.set("hi"); // 实际调用桥接方法
基本写法:识别桥接方法
<method>.isBridge();
// 反射判断是否桥接方法
for (Method m : StringBox.class.getMethods()) {
if (m.isBridge()) System.out.println(m);
}
泛型数组
基本写法:泛型数组限制
// 不能直接创建泛型数组
List<String>[] arr = new List<String>[10]; // 编译错误
// 通过原始类型或 Array.newInstance 创建
List<?>[] arr = new List<?>[10];
基本写法:Array.newInstance
Array.newInstance(<类型>, <长度>);
// 反射创建泛型数组
T[] arr = (T[]) Array.newInstance(componentType, 10);
可重写类型参数
基本写法:保留泛型信息的类
// 通过 Class 对象保留类型
public class TypedBox<T> {
private final Class<T> type;
public TypedBox(Class<T> type) { this.type = type; }
public T cast(Object o) { return type.cast(o); }
}
// 运行时仍可使用类型
TypedBox<String> b = new TypedBox<>(String.class);
String s = b.cast("hello");