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问题

  1. 如果你将序列化后的对象存到硬盘上面,可是后来你更改了类的field(增加、减少或改名),当你反序列化时,就会出现Exception,这样就会造成不兼容性的问题。
  2. 但当serialVersionUID相同时,它就会将不一样的field以type的缺省值反序列化,这个可以避开不兼容性的问题。

你可能感兴趣的:(总结)