Java中的序列化(Serialization)和反序列化(Deserialization)是用于在对象之间进行数据传输和持久化的机制。序列化是将对象转换为字节流的过程,而反序列化则是将字节流重新转换为对象的过程。
序列化的原理:
1. 将对象转换为字节流: 在序列化过程中,Java虚拟机会将对象的状态(即成员变量的值)转换为字节流。这涉及将对象的类、成员变量及其值写入到输出流中。
2. 保存对象状态: 序列化后的字节流包含了对象的类信息以及成员变量的值,可以被保存到文件、数据库或通过网络传输。
3. 对象的版本控制: 序列化机制允许开发者在对象的类发生变化时控制版本信息,以确保反序列化过程的兼容性。
反序列化的原理:
1. 从字节流中恢复对象: 在反序列化过程中,Java虚拟机会从输入流中读取字节,并将其转换回对象的状态。这涉及根据字节流中的类信息重新创建对象,并设置其成员变量的值。
2. 验证类的兼容性: 在反序列化过程中,Java虚拟机会验证字节流中的类信息与当前类是否兼容,以确保反序列化的对象与序列化时的类是一致的。
一个简单案例:
假设有一个简单的Java类Person:
import java.io.Serializable;
public class Person implements Serializable { //person示例
private String name;
private int age;
public Person(String name, int age) { //构造函数
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
序列化示例:
import java.io.*;
public class SerializationDemo { //序列化示例
public static void main(String[] args) {
Person person = new Person("Alice", 30); //创建一个person对象
try {
FileOutputStream fileOut = new FileOutputStream("person.ser"); //创建文件输出流对象, 用于将序列化后的字节流保存在person.ser文件中
ObjectOutputStream out = new ObjectOutputStream(fileOut); //创建对象输出流对象, 用于将对象序列化为字节流 --> 使用文件输出流对象fileOut将序列化后的字节流保存在person.ser文件中
out.writeObject(person); //指定将person对象序列化
out.close(); //关闭对象输出流对象
fileOut.close(); //关闭文件输出流对象
System.out.println("Serialized data is saved in person.ser"); //输出提示序列化结束
} catch (IOException e) {
e.printStackTrace(); //报错提示
}
}
}
反序列化示例:
import java.io.*; public class DeserializationDemo { //反序列化示例 public static void main(String[] args) { Person person = null; //声明一个person对象 try { FileInputStream fileIn = new FileInputStream("person.ser"); // 创建一个文件输入流对象, 用于从序列化后的字节流文件person.ser中读取字节数据 ObjectInputStream in = new ObjectInputStream(fileIn); // 创建对象输入流对象,使用文件输入流对象fileIn从序列化后的字节流文件person.ser中读取字节数据 ---> 将读取的字节数据还原为对象 person = (Person) in.readObject(); // 将反序列化返回的对象转换为person对象格式 in.close(); // 关闭对象输入流对象 fileIn.close(); // 关闭文件输入流对象 } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); // 报错提示 } // Accessing the deserialized object if (person != null) { // 输出person System.out.println("Name: " + person.getName()); System.out.println("Age: " + person.getAge()); } } }
在这个示例中,Person对象被序列化并保存到文件person.ser中,然后从文件中读取并反序列化为一个新的Person对象。
至于反序列化漏洞,请移步另一篇文章 初步认识Java反序列化漏洞