JAVA序列化ID有什么用?

本文介绍了JAVA序列化的作用,包括为什么需要序列化、序列化ID的重要性、哪些场景需要序列化,以及讨论了服务间信息交互是否应该使用序列化,并提出了替代方案——使用JSON字符串进行数据传递。

上周一个安卓的兄弟问到了我这个问题,今天我也把这个给写一下分享给大家

JAVA中通常会看到如下代码片断

    import java.io.Serializable; 
    public class A implements Serializable { 
        private static final long serialVersionUID = 1L; 
    }

下面我为序列化提出一些大家通常会疑惑的问题,并做出解答:
什么是序列化类?
序列化类是可以被在网络上传输的(或者也可以被序列化到本地磁盘并生成.ser就文件),并且可以被接收方反序列化

为什么传输的类要被序列化呢?
其实也并不是所有的类都要被序列化,我们看一下JAVA源码

private void writeObject0(Object obj, boolean unshared) throws IOException {
      ...
    if (obj instanceof String) { 
        writeString((String) obj, unshared);
    } else if (cl.isArray()) { 
        writeArray(obj, desc, unshared);
    } else if (obj instanceof Enum) {
        writeEnum((Enum) obj, desc, unshared);
    } else if (obj instanceof Serializable) {
        writeOrdinaryObject(obj, desc, unshared);
    } else {
        if (extendedDebugInfo) {
            throw new NotSerializableException(cl.getName() + "\n"
                    + debugInfoStack.toString());
        } else {
            throw new NotSerializableException(cl.getName());
        }
    }
    ...  }

字符串,数组,枚举这些类型是不需要序列化的,但是除此之外如果不实现Serializable接口就会报NotSerializableException异常

什么是序列化ID呢?
虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID = 1L)
所以反序列化时serialVersionUID也要一致。

什么场景需要序列化?
两个客户端 A 和 B 试图通过网络传递对象数据,A 端将对象 C 序列化为二进制数据再传给 B,B 反序列化得到 C。 若者是序列化到磁盘中,再反序列化到内存。

服务间信息交互用序列化好吗?
我觉得是不好的,并且通常我禁止这样的形为,原因是它提升了服务间的懒依和耦合,理由如下:
1、现在服务间的沟通越来越频繁
2、各服务的团队一般是独立的
3、所以如果用对象序列化的方式,各服务自己的内容变动可能会影响其它服务的正常运行
4、增加了沟通成本和未知性,比如,当我要改变一个DTO时,我得去询问有没有别的服务调用了我,假设我没有所有团队都问到的话就可能会有遗漏,事实上即使我问到了也不一定能得到肯定的答案

更极端一点的,我们甚至规定能走异步通迅的就走异步通讯,这方案几乎被确定为我们的一项开发原则

服务间交互用什么来代替
把一个MAP或对象转为JSON字符串,要什么数据就传什么数据,字符串不需要序列化ID的,内容变动对双方没什么影响,只要不删除依懒方所需要的业务字段就可以。

<think>好的,我现在需要处理用户关于Java中JSON序列化与反序列化的问题。用户提到了之前的引用内容,涉及泛型擦除和Jackson库的使用。首先,我需要确认用户的主要需求是了解实现方法及应用场景。 首先,我应该概述JSON序列化和反序列化的基本概念,说明它们在数据传输和存储中的作用。然后,针对Java中的具体实现,可能需要提到常用的库,比如Jackson、Gson和Fastjson。用户提供的引用中提到了Jackson,所以需要重点讲解Jackson的使用方法,包括基本对象转换、泛型处理以及多态类型处理。 用户的问题里还提到了泛型擦除的问题,引用[1]中的例子说明在反序列化时如何保留类型信息,这里需要解释TypeReference的用法。另外,引用[2]涉及多态类型的处理,需要介绍Jackson的@JsonTypeInfo注解,这部分也要详细说明。 接下来,应用场景方面,应该包括API通信、数据持久化、配置文件、分布式系统等,这些都是常见的用途。需要确保每个场景都简明扼要,并且和实现方法相关联。 在组织回答时,按照用户的要求,结构要清晰,分步骤说明实现方法,然后列举应用场景。同时,要注意使用正确的LaTeX格式,行内公式用$...$,独立公式用$$...$$,但在这个问题中可能涉及代码示例较多,数学公式可能较少,需要检查是否有需要用到的地方。 需要验证Jackson的代码示例是否正确,比如ObjectMapper的用法,TypeReference的实例化方式,以及多态注解的使用。确保代码示例与引用内容一致,并且语法正确。 最后,生成相关问题,确保问题与主题相关,能够引导用户进一步学习,比如性能优化、库的选择比较、异常处理等。要避免重复用户已提到的内容,比如泛型擦除的问题已经讨论过,可能不需要再作为问题提出。 总结步骤: 1. 介绍JSON序列化/反序列化的概念和用途。 2. 分点讲解实现方法,包括基本对象、泛型处理、多态处理。 3. 每个方法下提供代码示例,并引用用户提供的参考资料。 4. 列举应用场景,每个场景简短说明。 5. 生成相关问题,确保覆盖更多相关知识点。 6. 检查LaTeX格式和代码块是否符合要求,确保没有使用错误语法。</think>### Java JSON序列化与反序列化实现方法及应用场景 #### 一、JSON序列化与反序列化的作用 JSON序列化Java对象转换为JSON字符串,便于网络传输或存储;反序列化则将JSON字符串还原为Java对象,用于数据解析[^1]。核心应用场景包括: - **API通信**:RESTful接口的请求/响应数据交互 - **数据持久化**:将对象存储为JSON格式文件或数据库字段 - **分布式系统**:微服务间消息传递 #### 二、实现方法 ##### 1. 基础对象转换(以Jackson为例) ```java ObjectMapper mapper = new ObjectMapper(); // 序列化 String json = mapper.writeValueAsString(user); // 反序列化 User user = mapper.readValue(json, User.class); ``` *说明*:需保证Java类有无参构造器,字段有getter/setter方法[^2]。 ##### 2. 泛型类型处理 解决类型擦除问题时,使用`TypeReference`保留泛型信息: ```java List<User> users = mapper.readValue(json, new TypeReference<List<User>>(){}); ``` *原理*:通过匿名子类保存泛型类型参数,运行时通过反射获取类型信息[^1]。 ##### 3. 多态类型处理 使用`@JsonTypeInfo`注解实现多态序列化: ```java @JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type") @JsonSubTypes({ @Type(value = Dog.class, name = "dog"), @Type(value = Cat.class, name = "cat") }) public abstract class Animal {} ``` 反序列化时会根据`type`字段自动匹配子类[^2]。 #### 三、应用场景对比 | 场景 | 序列化需求 | 反序列化难点 | |------------------|------------------------------|-------------------------| | API接口开发 | 过滤敏感字段(`@JsonIgnore`) | 数据校验与类型转换 | | 缓存存储 | 压缩空格减少体积 | 兼容历史数据结构 | | 消息队列通信 | 添加时间戳元数据 | 处理多版本消息格式 | #### 四、性能优化建议 1. 复用`ObjectMapper`实例(线程安全) 2. 预编译`JavaType`提升泛型处理速度 3. 启用`Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER`应对特殊字符 $$T_{\text{parse}} = k \times n \log n \quad (\text{n为JSON节点数})$$
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值