java泛型擦除导致序列化时类型丢失,需用typereference显式传递泛型结构;避免raw type反序列化;redis和spring cache中应手动解析;多态场景需启用jackson类型识别;推荐用具体dto替代泛型响应体。

Java 中对象序列化时泛型擦除导致类型丢失,本质是运行时无法还原 List<user></user> 这类结构中的 User 信息——JVM 只知道它是 List,序列化框架(如 Jackson、Gson)若不额外提示,就会默认用 LinkedHashMap 填充元素,最终引发 ClassCastException 或空指针。
用 TypeReference 显式传递完整泛型结构
这是最常用也最稳妥的方式。Jackson 和 Gson 都依赖它在反序列化时“找回”被擦除的类型参数。
- Jackson 示例:
objectMapper.readValue(json, new TypeReference<list>>() {})</list> - Gson 示例:
gson.fromJson(json, new TypeToken<list>>() {}.getType())</list> - 关键点:必须写成匿名子类形式(末尾的
{}),否则getGenericSuperclass()拿不到泛型签名 - 适用于任意嵌套结构,比如
Map<string list>></string>也能准确还原
避免直接用 raw type 或 Class 做反序列化
像 objectMapper.readValue(json, List.class) 或 gson.fromJson(json, List.class) 是典型错误写法——它只告诉框架“这是一个 List”,但没说“里面装的是什么”。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 结果就是所有元素变成
LinkedHashMap,后续调用user.getName()会直接抛异常 - RedisTemplate 中尤其常见:不要
redisTemplate.opsForValue().get(key)后强转,应先取 String 再用 ObjectMapper 按需解析 - Spring Cache 场景下,
@Cacheable返回值若含泛型,建议配合CacheResolver自定义反序列逻辑,而非依赖自动推断
对多态对象启用 Jackson 类型识别
如果泛型容器里存的是不同子类(如 List<person></person> 包含 Student 和 Teacher),光靠 TypeReference 不够,还需让 JSON 带上类型标记。
- 配置 ObjectMapper:
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL) - 序列化后 JSON 会多出
@class字段,例如:{"@class":"com.example.Student","name":"张三","grade":95} - 反序列化时 Jackson 就能按标记实例化对应子类,而不是统一变成
Person或LinkedHashMap - 注意:该机制对
final类或未注册的子类无效,必要时可配合@JsonSubTypes显式声明
用具体 DTO 替代泛型响应体
对于固定结构的业务场景(如统一错误响应),与其反复处理泛型擦除,不如定义明确的非泛型子类。
- 例如把
Response<list>></list>改为UserListResponse extends Response<list>></list> - 反序列化时直接传
UserListResponse.class,框架可通过继承关系推断内部泛型 - 更进一步,可将泛型字段(如
details)改为具体类型:private List<validationerror> details;</validationerror>,避免运行时解析歧义
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










