为何ObjectMapper用无具体类的TypeReference可反序列化为Book?
Jackson匿名TypeReference反序列化Book的原理解析
这段代码能成功把字符串反序列化为Book对象,核心在于Java匿名内部类的泛型信息保留机制,以及Jackson对该信息的读取逻辑:
1. 编译时的泛型类型推断与保留
你写的new TypeReference<>() {}是创建了TypeReference的匿名子类,而非直接实例化TypeReference本身。编译阶段,编译器会根据变量声明final Book book的类型,自动推断出TypeReference的泛型实参为Book,并把这个具体的泛型类型信息写入到匿名子类的字节码Signature属性中——这部分信息不会被Java的泛型类型擦除完全清除。
2. Jackson如何获取目标类型
Jackson的readValue方法接收TypeReference参数后,会通过以下步骤拿到具体的反序列化类型:
- 调用
TypeReference.getType()方法,通过反射获取匿名子类的父类(即TypeReference<Book>) - 解析父类的泛型参数,提取出具体的
Book类型 - 基于
Book类型完成后续的反序列化逻辑
3. 为什么有的文章说会抛出异常
那些文章里的场景通常是以下两种:
- 直接实例化
TypeReference而非创建匿名子类:比如new TypeReference<>()(没有加{}),这种情况下没有子类来保留泛型信息,Jackson无法获取具体类型,会抛出异常 - 泛型类型无法在编译时确定:比如把这段代码放到泛型方法中,泛型参数是动态的(比如
<T> T deserialize(String str)),此时编译器无法推断出TypeReference的具体泛型实参,字节码中没有保留对应的类型信息,Jackson自然无法完成反序列化,也会抛出异常
而你的代码中,泛型类型Book是编译时明确的,匿名子类又保留了这个信息,所以能成功运行。
内容的提问来源于stack exchange,提问作者Leos Literak
相关产品推荐
相关产品推荐

