泛型擦除(Type Erasure)是 Java 编译器在编译期把泛型信息去掉以兼容旧版本 JVM 的机制,因此运行时往往拿不到泛型类型。要避免或“绕过”泛型擦除带来的问题,可以从设计、API 使用、工具手段三个层面入手。
典型问题:
List<String> list = new ArrayList<>();
// 运行时无法知道 list 是 List<String>
class Box<T> {
T value;
void print() {
// 运行时不知道 T 是什么
}
}
把泛型类型作为参数传入:
public <T> T parse(String json, Class<T> clazz) {
return Gson.fromJson(json, clazz);
}
调用:
User user = parse(json, User.class);
✅ 适合:JSON、反射、序列化
Class<T> 或 Type 保存泛型class Box<T> {
private Class<T> type;
Box(Class<T> type) {
this.type = type;
}
void print() {
System.out.println(type);
}
}
这是 Gson / Jackson 常用方式:
Type type = new TypeToken<List<String>>() {}.getType();
List<String> list = gson.fromJson(json, type);
原理:
✅ 适合:复杂泛型(List<Map<String, User>>)
class StringBox extends Box<String> {
}
此时:
getClass().getGenericSuperclass()
可拿到 String
T[] array = (T[]) new Object[size];
⚠️ 只能妥协使用,不推荐长期方案
ImmutableList<String> list = ImmutableList.of("a", "b");
reified 泛型inline fun <reified T> parse(json: String): T {
return Gson().fromJson(json, T::class.java)
}
Manifest / TypeTag✅ 不要在运行时依赖泛型做逻辑判断
✅ 泛型只用于编译期类型安全
✅ 需要类型信息时,显式传入 Class<T>
✅ 复杂泛型用 TypeToken
泛型擦除不可消除,但可以通过“把类型信息当参数传递”来规避。
如果你有具体场景(如 Spring、MyBatis、JSON、反射),我可以给你更针对性的解决方案。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。