温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何避免泛型擦除问题

发布时间:2026-09-30 18:33:37 来源:亿速云 阅读:89 作者:小樊 栏目:编程语言

泛型擦除(Type Erasure)是 Java 编译器在编译期把泛型信息去掉以兼容旧版本 JVM 的机制,因此运行时往往拿不到泛型类型。要避免或“绕过”泛型擦除带来的问题,可以从设计、API 使用、工具手段三个层面入手。


一、理解问题本质

典型问题:

List<String> list = new ArrayList<>();
// 运行时无法知道 list 是 List<String>
class Box<T> {
    T value;
    void print() {
        // 运行时不知道 T 是什么
    }
}

二、常用避免 / 绕过方案

1️⃣ 使用类型令牌(Type Token)

把泛型类型作为参数传入:

public <T> T parse(String json, Class<T> clazz) {
    return Gson.fromJson(json, clazz);
}

调用:

User user = parse(json, User.class);

✅ 适合:JSON、反射、序列化


2️⃣ 使用 Class<T> 或 Type 保存泛型

class Box<T> {
    private Class<T> type;

    Box(Class<T> type) {
        this.type = type;
    }

    void print() {
        System.out.println(type);
    }
}

3️⃣ 使用匿名内部类 + 反射获取泛型(TypeToken)

这是 Gson / Jackson 常用方式:

Type type = new TypeToken<List<String>>() {}.getType();
List<String> list = gson.fromJson(json, type);

原理:

  • 匿名类在编译时会保留父类泛型信息

✅ 适合:复杂泛型(List<Map<String, User>>)


4️⃣ 在类定义时固定泛型(避免擦除)

class StringBox extends Box<String> {
}

此时:

getClass().getGenericSuperclass()

可拿到 String


5️⃣ 使用数组代替泛型(有限场景)

T[] array = (T[]) new Object[size];

⚠️ 只能妥协使用,不推荐长期方案


6️⃣ 使用运行时安全容器(Guava / Apache)

ImmutableList<String> list = ImmutableList.of("a", "b");

7️⃣ Java 以外的选择

  • Kotlin:reified 泛型
inline fun <reified T> parse(json: String): T {
    return Gson().fromJson(json, T::class.java)
}
  • Scala:Manifest / TypeTag

三、设计层面避免泛型擦除问题

✅ 不要在运行时依赖泛型做逻辑判断
✅ 泛型只用于编译期类型安全
✅ 需要类型信息时,显式传入 Class<T>
✅ 复杂泛型用 TypeToken


四、总结一句话

泛型擦除不可消除,但可以通过“把类型信息当参数传递”来规避。

如果你有具体场景(如 Spring、MyBatis、JSON、反射),我可以给你更针对性的解决方案。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手