Java序列化

本文介绍了对象序列化在Java中的重要性,包括网络传输、持久化存储、进程间通信和对象复制的应用。主要讨论了通过JsonInclude注解和实现Serializable接口的两种实现序列化的方法。

对象序列化的目的就是将对象保存到磁盘中,或者允许再网络上直接传输对象。对象序列化机制允许把内存中的Java对象转换成与平台无关的二进制流,从而允许这种二进制流持久地保存在磁盘中,通过网络将这种二进制流传输到另一个网络节点中

为什么要对实体类实现序列化

  1. 网络传输:当需要在网络上发送对象数据时,例如在客户端和服务器之间进行通信,通过序列化可以将对象转换为字节流,在网络上传输效率高,并且确保数据的完整性。
    2. 持久化存储:当需要将对象永久保存到文件系统、数据库或缓存中时,可以使用序列化将对象保存为字节流,这样可以方便地进行存储和读取。
    3. 进程间通信:在多进程或分布式系统中,不同进程或节点之间需要传递数据,通过序列化可以简化数据传递的过程。
    4. 对象复制:有时候需要复制对象,通过序列化和反序列化可以快速实现对象的深拷贝

对实体类实现序列化的两种方法

方法一:@JsonInclude注解

@JsonInclude注解是jackSon中最常用的注解之一,是为实体类在接口序列化返回值时增加规则的注解

@JsonInclude(JsonInclude.Include.NON_EMPTY)

NON_EMPTY排除字段值为null、空字符串、空集合、空数组、Optional类型引用为空,AtomicReference类型引用为空
JsonInclude.Include.NON_EMPTY 那么这个就是根据规则NON_EMPTY将排除后的成员变量去进行序列化

方法二:让目标类实现Serializable接口

import java.io.Serializable;
 
public class MyClass implements Serializable {
    private int id;
    private String name;
    private transient String transientField; // This field won't be serialized
 
    // Constructors, getters, setters, and other methods
}
### 序列化的含义 序列化指将堆内存中的 Java 对象数据,通过某种方式存储到磁盘文件中,或者传递给其他网络节点(网络传输),即将对象转化为二进制,用于保存或网络传输。反序列化则是从 IO 流中恢复对象[^1][^4]。 ### 序列化的意义 序列化机制允许将实现序列化Java 对象转换为字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在[^1]。 ### 序列化的使用场景 所有可在网络上传输的对象都必须是可序列化的,比如 RMI(remote method invoke,即远程方法调用),传入的参数或返回的对象都是可序列化的,否则会出错;所有需要保存到磁盘的 Java 对象都必须是可序列化的。通常建议程序创建的每个 JavaBean 类都实现 Serializable 接口[^1]。 ### 序列化实现的方式 #### Serializable 接口 - **普通序列化**:实现 Serializable 接口后,可使用 ObjectOutputStream 将对象写入流,使用 ObjectInputStream 从流中读取对象。 ```java import java.io.*; class Person implements Serializable { String name; int age; public Person(String name, int age) { this.name = name; this.age = age; } } public class SerializationExample { public static void main(String[] args) { Person person = new Person("John", 30); try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) { oos.writeObject(person); } catch (IOException e) { e.printStackTrace(); } try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) { Person deserializedPerson = (Person) ois.readObject(); System.out.println(deserializedPerson.name + " " + deserializedPerson.age); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } } ``` - **成员是引用的序列化**:若类的成员是引用类型,该引用类型也必须是可序列化的,否则当前类无法实现序列化。 - **同一对象序列化多次的机制**:Java 序列化算法会保证同一对象多次序列化时,不会重复序列化对象的内容,而是只记录对象的引用。 - **Java 序列化算法潜在的问题**:例如序列化版本号不匹配、性能问题等。 - **可选的自定义序列化**:可通过实现 `writeObject` 和 `readObject` 方法来自定义序列化和反序列化过程。 #### Externalizable 接口 Externalizable 接口强制自定义序列化,需要实现 `writeExternal` 和 `readExternal` 方法。 ```java import java.io.*; class Employee implements Externalizable { String name; int id; public Employee() {} public Employee(String name, int id) { this.name = name; this.id = id; } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(name); out.writeInt(id); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name = (String) in.readObject(); id = in.readInt(); } } ``` ### 序列化版本号 serialVersionUID serialVersionUID 用于确保序列化和反序列化时类的版本一致性。若没有显式定义 serialVersionUID,Java 会根据类的结构自动生成一个。当类的结构发生变化时,可能会导致 serialVersionUID 改变,从而在反序列化时抛出 `InvalidClassException`。建议显式定义 serialVersionUID。 ```java import java.io.Serializable; class MyClass implements Serializable { private static final long serialVersionUID = 1L; // 类的成员和方法 } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值