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

如何用泛型实现通用JSON导入方法?遇类型转换异常求助

问题原因解析
  • 类型擦除导致解析失败:Java泛型在运行时会擦除类型信息,你使用DataItems<T>.class时,实际传递给Gson的是DataItems.class,Gson无法识别T的具体类型(比如House),所以会把JSON数组中的对象默认解析成LinkedTreeMap,强转成House自然抛出ClassCastException。
  • 数字类型默认解析为Double:Gson在没有明确类型约束时,会把JSON中的整数解析为Double类型,这就是int类型变成Double的原因。
  • 字段不匹配:你的JSON里字段是id,但House类里对应的字段是number,这会导致该字段无法被正确赋值。
修复方案

要让Gson正确解析泛型类型,需要通过TypeToken保留泛型的类型信息,同时修正字段匹配问题:

1. 修正House类的字段映射

要么把House类的字段名改成id,要么用@SerializedName注解做字段映射:

public class House { 
    @SerializedName("id") // 映射JSON中的id字段到number
    int number; 
    String name; 
}

2. 修改导入方法,传递目标类型Class

这是最可靠的方案,直接让方法接收目标类型的Class对象,构造明确的泛型类型:

private <T> List<T> importFromJSON(Class<T> clazz) { 
    try(FileInputStream fileInputStream = context.openFileInput(fileName);
        InputStreamReader streamReader = new InputStreamReader(fileInputStream)){
        Gson gson = new Gson(); 
        // 构造DataItems<T>的具体类型,避免类型擦除
        Type dataItemsType = TypeToken.getParameterized(DataItems.class, clazz).getType();
        DataItems<T> dataItems = gson.fromJson(streamReader, dataItemsType); 
        return dataItems.getList(); 
    } catch (IOException ex){ 
        ex.printStackTrace(); 
    } 
    return null; 
}

调用方式

直接传入House.class,无需强转:

List<House> houseList = importFromJSON(House.class);
House house = houseList.get(0); // 直接使用,不会抛出类型转换异常

可选方案:保留DataItems参数(不推荐)

如果一定要保留原方法的参数形式,可以通过反射获取传入对象的泛型类型,但这种方式依赖传入对象的泛型信息未被擦除,可靠性较低:

private <T> List<T> importFromJSON(DataItems<T> dataItems) { 
    try(FileInputStream fileInputStream = context.openFileInput(fileName);
        InputStreamReader streamReader = new InputStreamReader(fileInputStream)){
        Gson gson = new Gson(); 
        // 通过反射获取泛型参数类型
        Type superType = dataItems.getClass().getGenericSuperclass();
        if (superType instanceof ParameterizedType) {
            Type[] actualTypes = ((ParameterizedType) superType).getActualTypeArguments();
            if (actualTypes.length > 0) {
                Type dataItemsType = TypeToken.getParameterized(DataItems.class, actualTypes[0]).getType();
                dataItems = gson.fromJson(streamReader, dataItemsType); 
                return dataItems.getList(); 
            }
        }
    } catch (IOException ex){ 
        ex.printStackTrace(); 
    } 
    return null; 
}

调用方式

需要传入带泛型信息的匿名内部类实例(避免类型擦除):

DataItems<House> dataItems = new DataItems<House>() {}; // 匿名内部类保留泛型信息
List<House> houseList = importFromJSON(dataItems);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 01:55:20