Java Serializable(シーケンス化)


コンセプト
オブジェクトをストリームに書き込むプロセスはシーケンス化(Serilization)プロセスであり,オブジェクトをストリームから読み出すプロセスを逆シーケンス化(Deserialization)プロセスと呼ぶ.ストリームに書かれているのはオブジェクトのコピーであり、元のオブジェクトはJVMに残っていることを指摘してください.
シーケンス化による深いレプリケーション
Java言語でオブジェクトを深くコピーすると、オブジェクトにSerializableインタフェースを実装させ、オブジェクト(実際にはオブジェクトのコピー)をストリームに書き、ストリームから読み出すことでオブジェクトを再構築することができます.
public class SerializableTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Teacher t = new Teacher();
        t.setAge(30);
        t.setName("Teacher Wang");
        Student s = new Student();
        s.setAge(20);
        s.setName("Student Li");
        s.setTeacher(t);    
        //   
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ObjectOutputStream output = new ObjectOutputStream(out);
        output.writeObject(s);
        //    
        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
        ObjectInputStream input = new ObjectInputStream(in);
        Student stu = (Student)input.readObject();
        Teacher t2 = new Teacher();
        t2.setAge(60);
        t2.setName("Teacher Zhang");
        s.setTeacher(t2);
        System.out.println(s.getTeacher().getAge());
        System.out.println(s.getTeacher().getName());
        System.out.println(stu.getTeacher().getAge());
        System.out.println(stu.getTeacher().getName());
    }
}
class Student implements Serializable {
    private static final long serialVersionUID = 1L;
    private int age;
    private String name;
    private Teacher teacher;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Teacher getTeacher() {
        return teacher;
    }
    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }
}
class Teacher implements Serializable {
    private static final long serialVersionUID = 1L;
    private int age;
    private String name;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

印刷結果:60 Teacher Li 30 Teacher Wang
説明
1.オブジェクトがシーケンス化されると、オブジェクトの非静的メンバー変数(静的メンバー変数はクラスに属する)のみが保存され、メンバーメソッドと静的メンバー変数は保存されません.2.オブジェクトのメンバー変数がオブジェクトである場合、そのオブジェクトのデータメンバーも保存されます.3.シーケンス可能なオブジェクトにシーケンス不可能なオブジェクトへの参照が含まれている場合、シーケンス化操作全体が失敗し、NotSerializableExceptionが放出されます.このシーケンス不可能な参照をtransientとマークすると、オブジェクトはシーケンス化されます.
Serializableインタフェースを実装するクラスにおけるserialVersionUIDの問題について
  • シーケンス化されたオブジェクトをハードディスク(HDD)に保存した後、クラスのfieldを変更し(追加、減少、改名)、逆シーケンス化するとExceptionが発生し、互換性の問題が発生します.
  • しかしserialVersionUIDが同じである場合、異なるfieldはtypeのデフォルト値で逆シーケンス化され、これは互換性の問題を避けることができる.