手记

IO流(3) - 序列化和反序列化

对象的序列化/反序列化

对象序列化,就是将Object转换成byte序列,反之叫做对象的反序列化。

序列化流(ObjectOutputStream),是一个过滤流 --> writeObject,

反序列化流(ObjectInputStream) --> readObject.

序列化接口(Serializable)

对象必须实现序列化接口才能进行序列化,否则将出现NoSerializableException异常。此接口没有任何方法,只是一个标准。

创建一个Person.java实体类:

public class Person implements Serializable {
    private String name;
    private Integer age;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

写一个对象流测试类:

public class ObjectTest {
    public static void main(String[] args) throws IOException {
        String file = "F:\\Code\\JavaSE\\obj.txt";
        // 对象序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        Person student = new Person("张三", 22);
        oos.writeObject(student);
        oos.flush();
        oos.close();

        try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
            Person per = (Person) ois.readObject();
            System.out.println(per);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

输出结果:

Person{name='张三', age=22}

在进行对象序列化操作时,并不希望所有的变量都进行序列化操作,这时可以在变量前加上transient关键字,使得该变量不进行序列化操作,并不是说不做JVM默认的序列化就不能序列化了,也可以自己完成这个变量的序列化。

Person.java中给age变量前面加上transient关键字,添加以下两种方法:

private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
    s.defaultWriteObject(); //把JVM能默认序列化的元素进行序列化操作
    s.writeObject(age); //被transient修饰的变量,自己完成序列化操作
}

private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
    s.defaultReadObject(); //把JVM能默认反序列化的元素进行反序列化操作
    this.age = (Integer) s.readObject();//自己完成age的反序列化操作
}

加上这两个方法后,即使变量前有transient关键字修饰,也可以进行序列化/反序列化操作。

分析ArrayList源码中序列化和反序列化的问题

序列化中,子类和父类之间的调用:一个类实现了序列化接口,继承它的子类都能够进行序列化操作。

序列化显式创建对象,需要递归调用父类方法。

对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被调用。

0人推荐
随时随地看视频
慕课网APP