序列化:序列化是指将对象的状态信息转换为可以存储或传输的形式的过程
反序列化:将序列化后的数据(即字节序列)恢复为原始对象的过程
测试代码:
package com.tan.redis.controller;
import java.io.*;
public class SerializationExample {
/**
* 序列化
* @param person
* @param fileName
*/
public static void serializePerson(Person person, String fileName) {
try (FileOutputStream fileOut = new FileOutputStream(fileName);
ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
out.writeObject(person);
System.out.println("序列化到:" + fileName);
} catch (IOException i) {
i.printStackTrace();
}
}
/**
* 反序列化
*/
public static Person deserializePersonFromFile(String fileName) {
Person person = null;
try (FileInputStream fileIn = new FileInputStream(fileName);
ObjectInputStream in = new ObjectInputStream(fileIn)) {
// 读取对象并强制转换为Person类型
person = (Person) in.readObject();
} catch (IOException | ClassNotFoundException e) {
// 处理异常,比如打印堆栈跟踪
e.printStackTrace();
}
return person;
}
public static void main(String[] args) {
Person person = new Person("Alice", 30);
String fileName = "person.ser";
serializePerson(person, fileName);
System.out.println("反序列化 = " + deserializePersonFromFile(fileName));
}
}
@AllArgsConstructor
@Data
class Person implements Serializable {
private static final long serialVersionUID = 1L; // 用于版本控制
private String name;
private int age;
// private Integer id;
// 自定义序列化方法
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject(); // 序列化当前对象的非瞬态和非静态字段
// 可以添加自定义序列化逻辑
System.out.println("Custom serialization logic for MySerializableObject");
}
// 自定义反序列化方法
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject(); // 反序列化当前对象的非瞬态和非静态字段
// 可以添加自定义反序列化逻辑
System.out.println("Custom deserialization logic for MySerializableObject");
}
}
注意点:
文心一言回答:
- 只有实现了
Serializable
接口的对象才能被序列化。 - 静态字段不会被序列化,因为序列化的是对象的状态,而静态字段属于类,不属于任何对象实例。
- 序列化可能会因为类的定义发生变化(如添加、删除或重命名字段)而变得不兼容。为了控制版本兼容性,可以在类定义中添加
serialVersionUID
字段(看自己测试的第二条看完看第三条,能自己测测更好)。 - 如果对象中包含了对其他对象的引用,并且这些对象也需要被序列化,那么这些对象也必须实现
Serializable
接口(或者有一个自定义的序列化逻辑,通过实现java.io.Externalizable
接口,我也没试过我也不懂)。 - 序列化过程中会调用对象的
writeObject
和readObject
方法(如果它们被重写,这俩方法在Serializable 接口的注释里),以及任何可序列化的父类或超类中的这些方法。这允许对象在序列化或反序列化时执行自定义逻辑。然而,通常情况下,你不需要直接重写这些方法,除非你有特殊的序列化需求。
自己测试的:
- 注意类型的改变后反序列化会失败,包括基本数据类型转成包装类型(如 int改为Integer)
- 如果版本不改变添加字段、删除字段和重命名字段,对反序列化没有影响,重命名字段只不过字段为null。
- 序列化基本数据类型的时候会使用基本数据类型的默认值