Java安全基础之Java序列化与反序列化
Java 的序列化(Serialization)是指将对象转换为字节序列的过程,而反序列化(Deserialization)则是将字节序列转换回对象的过程。
序列化和反序列化通常用于在网络上传输对象或者将对象持久化到文件系统中。
Java 提供了 java.io.Serializable
接口来支持对象的序列化和反序列化。如果一个类实现了 Serializable 接口,那么该类的对象就可以被序列化和反序列化。
ObjectInputStream 和 ObjectOutputStream
ObjectInputStream 和 ObjectOutputStream 是 Java 中用于序列化和反序列化对象的类,它们提供了将对象转换为字节流并将字节流转换回对象的功能。
-
ObjectOutputStream:用于将对象序列化为字节流,依赖于 writeObject() 方法。
-
ObjectInputStream:用于从字节流反序列化对象,依赖于 readObject() 方法。
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.ser"))) {
// 写入对象到文件
out.writeObject(myObject);
} catch (IOException e) {
e.printStackTrace();
}
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.ser"))) {
// 从文件中读取对象
MyObject myObject = (MyObject) in.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
java.io.Serializable
Serializable 这个接口本身并不包含任何方法,它只是一个空接口,其作用是告诉 Java 编译器,这个类的对象可以被序列化成字节流,也可以从字节流中反序列化成对象。
使用文件流进行序列化: 将对象序列化到文件中,使用 FileOutputStream 和 FileInputStream 进行读写操作。
import java.io.*;
public class SerializationExample {
public static void main(String[] args) {
try {
String obj = "serialization example";
// 序列化对象到文件
FileOutputStream fos = new FileOutputStream("object.ser");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(obj);
os.close();
//反序列化对象到文件
FileInputStream fis = new FileInputStream("object.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
String dobj = (String)ois.readObject();
System.out.print(dobj);
ois.close();
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
使用字节数组进行序列化: 还可以使用 ByteArrayOutputStream 和 ByteArrayInputStream 将对象序列化到字节数组中。
import java.io.*;
public class SerializationExample {
public static void main(String[] args) {
try {
String obj = "serialization example";
// 序列化对象到字节数组
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(byteArrayOutputStream);
os.writeObject(obj);
os.close();
// 从字节数组反序列化对象
byte[] byteArray = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
String dobj = (String) ois.readObject();
System.out.print(dobj);
ois.close();
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
除了可以将对象序列化到文件流和字节数组,还可以将对象序列化到网络流、缓存流等。除了 Java 原生的序列化方式外,还有一些第三方库可以进行对象的序列化,例如 JSON 序列化或者 XML 序列。
自定义序列化和反序列化
在 Java 中,可以通过实现 writeObject() 和 readObject() 方法来自定义序列化和反序列化过程,可以更灵活地控制对象在序列化和反序列化过程中的行为。
-
自定义序列化:private void writeObject(ObjectOutputStream oos)
-
自定义反序列化:private void readObject(ObjectInputStream ois)
例如:Person 类实现了 Serializable 接口
class Person implements Serializable {
private String name;
private transient int age; // transient 表示该字段不参与序列化
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 自定义序列化方法
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject(); // 默认序列化其他字段
// 手动序列化 age 字段
out.writeInt(age);
}
// 自定义反序列化方法
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject(); // 默认反序列化其他字段
// 手动反序列化 age 字段
age = in.readInt();
}
}
过在待序列化或反序列化的类中定义 readObject 和 writeObject 方法,就来实现自定义的序列化和反序列化操作。