You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gson泛型反序列化报错:LinkedTreeMap转MyClass类型转换异常

Gson泛型解析类型转换异常问题分析

问题代码

public static void main(String[] args) {
    String tr = "[{\"key\":\"foo\"}, {\"key\":\"shoe\"}]";

    List<MyClass> o = new Gson().fromJson(tr, getType());
    for (MyClass object : o) {
        System.out.println(object);
    }
}

public static <T extends MyClass> Type getType() {
    return new TypeToken<List<T>>() {
    }.getType();
}

public static class MyClass {
    private String key;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    @Override
    public String toString() {
        return "X{" +
                "key='" + key + '\'' +
                '}';
    }
}

抛出的异常

Exception in thread "main" java.lang.ClassCastException: class com.google.gson.internal.LinkedTreeMap cannot be cast to class org.example.Main$MyClass (com.google.gson.internal.LinkedTreeMap and org.example.Main$MyClass are in unnamed module of loader 'app')

问题原因

你对类型擦除的理解存在误区:虽然getType方法声明了<T extends MyClass>,但这个T的具体类型在运行时会被完全擦除,而且Gson的TypeToken无法从方法的泛型参数中获取到实际的类型信息。

当调用getType()时,编译器无法推断出T的具体类型(即使左边变量是List<MyClass>,这种上下文无法传递到泛型方法的类型参数中),最终T会被当作Object处理。TypeToken<List<T>>实际生成的是List<Object>的类型,Gson解析JSON数组时,因为不知道具体的元素类型,就会用默认的LinkedTreeMap来存储每个JSON对象,后续强转MyClass自然就会抛出类型转换异常。

解决方案

有几种常见的修复方式:

  • 直接在调用处创建TypeToken
    最直接的做法,把TypeToken的创建放在能明确指定泛型类型的地方:

    List<MyClass> o = new Gson().fromJson(tr, new TypeToken<List<MyClass>>(){}.getType());
    
  • 让getType方法接收Class<T>参数,动态生成参数化类型
    通过ParameterizedType手动构建List<T>的类型,避免依赖方法泛型参数的擦除:

    public static <T extends MyClass> Type getType(Class<T> clazz) {
        return new ParameterizedType() {
            @Override
            public Type[] getActualTypeArguments() {
                return new Type[]{clazz};
            }
    
            @Override
            public Type getRawType() {
                return List.class;
            }
    
            @Override
            public Type getOwnerType() {
                return null;
            }
        };
    }
    

    调用时传入MyClass.class:

    List<MyClass> o = new Gson().fromJson(tr, getType(MyClass.class));
    

内容的提问来源于stack exchange,提问作者Sudhanshu Bansal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 20:35:20