366 words
2 minutes
反序列化与序列化
反序列化与序列化基础
先写一个Person类
public class Person implements java.io.Serializable{ private String name; private int age;
public Person() {
} public Person(String name, int age) { this.name = name; this.age = age; }
@Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }}再写一个SerializationTest
import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;
public class SerializationTest { public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); }
public static void main(String[] args) throws Exception { Person person = new Person("aa", 22); System.out.println(person); // SerializationTest.serialize(person); }}这是一个非常硬核且关键的 Java 机制问题!
简单的回答是:这是 Java 序列化规范的强制规定。JVM 在反序列化时,只认 private 签名的 readObject 方法。如果是 public,它就不认了,直接忽略你的代码。
让我们深入到底层,看看为什么会这样:
1. “魔法方法”的严格签名
在 Java 的 Serializable 接口定义中,readObject 被设计为一个回调方法(Callback)。
当 ObjectInputStream 试图反序列化一个对象时,它会通过**反射(Reflection)**机制去检查这个类有没有定义一个“特殊”的方法来处理反序列化逻辑。
Java 官方文档和源码对这个“特殊”方法的签名要求极其严格,必须一字不差:
Java
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException;注意那个 private。
2. 为什么 public 不行?
当你把它改成 public void readObject(...) 时:
- 反射查找失败(或被跳过):
ObjectInputStream在内部逻辑中(具体是在ObjectStreamClass