当前位置 > it书童 > java > 正文

java对象引用的序列化

java it书童 2020-12-02 22:06:48 0赞 0踩 815阅读 0评论

如果某个类的成员变量的类型不是基本类型或String类型,而是另一个引用类型,那么这个引用类必须是可序列化的,否则拥有该类型成员变量的类也是不可序列化的

如果多次请同一个对象序列化,java只会储存一个对象,后续的都只是存储一个编号,具体的序列化算法如下:

  • 所有保存到磁盘中的对象都有一个序列化编号

  • 当程序试图序列化一个对象时,程序将先检查该对象是否已经被序列化过,只有该对象从未(在本次虚拟机中)被序列化过,系统才会将该对象转换成字节序列并输出

  • 如果某个对象已经序列化过,程序将只是直接输出一个序列化编号,而不是再次重新序列化该对象

Person 类

@Data
public class Person implements Serializable {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

Teacher 类拥有 Person 类实例

@Data
public class Teacher implements Serializable {
    private String name;
    private Person student;

    public Teacher(String name, Person student) {
        this.name = name;
        this.student = student;
    }
}

将 Teacher 类多次序列化

public class WriteTeacher {
    public static void main(String[] args) {
        try (
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("teacher.txt"));
        ) {
            Person per = new Person("孙悟空", 2500);
            Teacher t1 = new Teacher("唐僧", per);
            Teacher t2 = new Teacher("菩提祖师", per);
            // 将对象写入输出流
            oos.writeObject(t1);
            oos.writeObject(t2);
            oos.writeObject(per);
            oos.writeObject(t2);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

问题来了,序列化的四个对象中,Person 对象是不是同一个?

public class ReadTeacher {
    public static void main(String[] args) {
        try (
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("teacher.txt"));
        ){
            Teacher t1 = (Teacher) ois.readObject();
            Teacher t2 = (Teacher) ois.readObject();
            Person p = (Person) ois.readObject();
            Teacher t3 = (Teacher) ois.readObject();
            System.out.println("t1 的 student 引用和 p 是否相同 " + (t1.getStudent() == p));
            System.out.println("t2 的 student 引用和 p 是否相同 " + (t2.getStudent() == p));
            System.out.println("t2 和 t3 是否是同一个对象:" + (t2 == t3));
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

如图,序列化一个对象多次,只会保存一次

因为 Java 的序列化机制,我们要注意以下场景:如果多次序列化同一个Java对象时,只有第一次序列化时才会把该Java对象转换成字节序列并输出,这样可能引起一个潜在的问题——当程序序列化一个可变对象时,只有第一次使用writeObject()方法输出时才会将该对象转换成字节序列并输出,当程序再次调用writeObject()方法时,程序只是输出前面的序列化编号,即使后面该对象的实例变量值已被改变,改变的实例变量值也不会被输出

关于我
一个文科出身的程序员,追求做个有趣的人,传播有价值的知识,微信公众号主要分享读书思考心得,不会有代码类文章,非程序员的同学请放心订阅
转载须注明出处:https://www.itshutong.com/articles/929