泛型类获取实际类型对象及fromJson报ClassCastException原因
问题:LinkedHashMap无法转为QueryOrderInfo对象的原因分析
我遇到如下报错:Caused by: java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.test.QueryOrderInfo
场景是需要将JSON字符串bizContent解析为QueryOrderInfo对象。
更新说明:新增fromJson2()方法后可以正常运行,但疑惑为什么fromJson()方法会抛出异常。
代码示例
主方法代码
public static void main(String[] args) { BaseResponse<QueryOrderInfo> queryOrderInfoBaseResponse = null; try { queryOrderInfoBaseResponse = new ObjectMapper().readValue("{\"returnCode\":\"SUCCESS\",\"biz_content\":\"{\\\"mchReserved\\\":\\\"1\\\",\\\"cmbOrderId\\\":\\\"900119022715203210134445\\\",\\\"dscAmt\\\":\\\"0\\\",\\\"payType\\\":\\\"ZF\\\",\\\"orderId\\\":\\\"9001004180329103417277\\\",\\\"txnTime\\\":\\\"20190227152032\\\",\\\"merId\\\":\\\"3089991701207X7\\\",\\\"currencyCode\\\":\\\"156\\\",\\\"txnAmt\\\":\\\"1\\\",\\\"tradeState\\\":\\\"S\\\"}\",\"sign\":\"kGE7mwX/ubRlPsPZGNydjY3uCjILgGuxD4j1e/inyC/DlHn5o7LkISpmrH0YQvoZT6lyOxtr9uIkKnqVcTMZNYeYIBU+Tz8NRaPZHuFr/qQb0+fUgEgq5j9ovaFczAF8wrnEfIRYBEqp0ERtK7NG+X6eZLIr9nNVy31eKcnFx1tToJ/zPYN91GOKOtTrJaJrKeDY4+r3ctzsDhnD+TO2MX5zfvW0WLoUjvX5geiYLVpt022BiyxSJyOsrDS858RBmZ5FbVlYP0v/WqwX+J8VY1kDSLxvPtSZuPnsluJPXw6ccnYNH8dir0VgrYfrWRvnupctIm2elCmL7ES6KzDTGg==\",\"encoding\":\"UTF-8\",\"version\":\"0.0.1\",\"signMethod\":\"01\",\"respCode\":\"SUCCESS\"}", new TypeReference<BaseResponse<QueryOrderInfo>>() { }); QueryOrderInfo queryOrderInfo = queryOrderInfoBaseResponse.fromJson(); QueryOrderInfo queryOrderInfo2 = queryOrderInfoBaseResponse.fromJson2(QueryOrderInfo.class); } catch (JsonProcessingException e) { throw new RuntimeException(e); } }
BaseResponse类
@NoArgsConstructor @Data public class BaseResponse<T> { private String returnCode; @JsonProperty(value = "biz_content") private String bizContent; private String sign; private String encoding; private String version; private String signMethod; private String respCode; private String errCode; private String respMsg; public T fromJson() { try { return new ObjectMapper().readValue(this.bizContent, new TypeReference<T>() { }); } catch (JsonProcessingException e) { return null; } } public T fromJson2(Class<T> clazz) { try { return new ObjectMapper().readValue(this.bizContent, clazz); } catch (JsonProcessingException e) { return null; } } }
QueryOrderInfo类
@NoArgsConstructor @Data public class QueryOrderInfo { private String mchReserved; private String cmbOrderId; private String dscAmt; private String payType; private String orderId; private String txnTime; private String merId; private String currencyCode; private String txnAmt; private String tradeState; }
原因分析
核心问题是Java泛型的类型擦除机制:
- 编译时
BaseResponse<T>中的泛型参数T会被保留,但运行时JVM会擦除泛型信息,T会被替换为Object。这意味着fromJson()方法里的new TypeReference<T>() {}无法在运行时获取到具体的QueryOrderInfo类型,Jackson没有明确的目标类型信息,只能将JSON字符串解析为默认的LinkedHashMap对象。当你尝试把这个LinkedHashMap强转为QueryOrderInfo时,就会触发ClassCastException。 - 而
fromJson2(Class<T> clazz)方法直接传入了具体的Class对象,Jackson可以通过这个对象明确知道要解析的目标类型,因此能正确生成QueryOrderInfo实例,不会出现类型转换异常。
额外优化建议
- 避免在方法内重复创建
ObjectMapper实例,ObjectMapper是线程安全的,可以全局复用一个实例,提升性能。 - 如果想保留
fromJson()的写法,可以在BaseResponse初始化时传入TypeReference或Class对象并保存,这样运行时就能获取到具体类型信息。
内容的提问来源于stack exchange,提问作者Holinc
相关产品推荐
相关产品推荐

