Java中与Serializable接口相关的一些方法执行顺序

自定义 writeObject 方法和 readObject 方法

如果在实现Serializable接口的类中自定义 writeObject 方法和 readObject 方法,则不会调用默认的方法:

package serializable;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;


public class Student implements Serializable {
    private static final long serialVersionUID = 140932343675039705L;

    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString(){
        return "学生:" + name;
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        System.out.println("readObject exec...");
    }

    private void writeObject(ObjectOutputStream out) throws IOException{
        System.out.println("writeObject exec...");
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student student = new Student();
        student.setName("小明");
        String filePath = "/Users/dcc/Downloads/student";
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filePath));
        out.writeObject(student);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
        Student student1 = (Student) in.readObject();
        System.out.println(student1);
    }

}

程序输出结果:

writeObject exec...
readObject exec...
学生:null

因为在 writeObject 方法中只打印了日志,没有序列化 name 字段,所以 readObject 方法没有反序列化出 name.可以在自定义的writeObject 方法和 readObject 方法中调用默认方法:

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        System.out.println("readObject exec...");
    }

    private void writeObject(ObjectOutputStream out) throws IOException{
        out.defaultWriteObject();
        System.out.println("writeObject exec...");
    }

修改之后 name 字段序列化和反序列化均成功,程序输出:

writeObject exec...
readObject exec...
学生:小明

writeReplace 方法和 readResolve 方法

writeReplace 方法可以替换序列化的对象;readResolve 方法是替换反序列化的对象:

看如下代码:

package serializable;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;


public class Student implements Serializable {
    private static final long serialVersionUID = 140932343675039705L;

    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString(){
        return "学生:" + name;
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        System.out.println("readObject exec...");
    }

    private void writeObject(ObjectOutputStream out) throws IOException{
        out.defaultWriteObject();
        System.out.println("writeObject exec...");
    }

    private Object writeReplace() throws ObjectStreamException{
        System.out.println("writeReplace exec...");
        return this;
    }

    private Object readResolve() throws ObjectStreamException{
        System.out.println("readResolve exec...");
        return this;
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student student = new Student();
        student.setName("小明");
        String filePath = "/Users/dcc/Downloads/student";
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filePath));
        out.writeObject(student);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
        Student teacher = (Student) in.readObject();
        System.out.println(teacher);
    }

}

程序运行结果:

writeReplace exec...
writeObject exec...
readObject exec...
readResolve exec...
学生:小明

可以看出:writeReplace 方法是在 writeObject 方法之前执行;readResolve 方法是在 readResolve 方法之后执行。

修改上面的代码:

package serializable;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;


public class Teacher implements Serializable {
    private static final long serialVersionUID = 4644753740588166024L;

    private String teacherNo;

    public Teacher(String teacherNo) {
        this.teacherNo = teacherNo;
    }

    @Override
    public String toString() {
        return "老师:" + teacherNo;
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        System.out.println("Teacher readObject exec...");
    }

    private void writeObject(ObjectOutputStream out) throws IOException{
        out.defaultWriteObject();
        System.out.println("Teacher writeObject exec...");
    }
}
public class Student implements Serializable {
    private static final long serialVersionUID = 140932343675039705L;

    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString(){
        return "学生:" + name;
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        System.out.println("readObject exec...");
    }

    private void writeObject(ObjectOutputStream out) throws IOException{
        out.defaultWriteObject();
        System.out.println("writeObject exec...");
    }

    private Object writeReplace() throws ObjectStreamException{
        System.out.println("writeReplace exec...");
        return new Teacher("007");
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student student = new Student();
        student.setName("小明");
        String filePath = "/Users/dcc/Downloads/student";
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filePath));
        out.writeObject(student);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
        Student student1 = (Student) in.readObject();
        System.out.println(student1);
    }

}

程序输出:

writeReplace exec...
Teacher writeObject exec...
Teacher readObject exec...
Exception in thread "main" java.lang.ClassCastException: serializable.Teacher cannot be cast to serializable.Student
	at serializable.Student.main(Student.java:57)

可以看到序列化的小明同学Student对象已经被writeReplace方法替换成了Teacher对象,而且执行的是Teacher类中定义的 writeObject 方法和 readObject 方法。

反序列化处代码修改:

ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
        Teacher teacher = (Teacher) in.readObject();
        System.out.println(teacher);

程序输出结果:

writeReplace exec...
Teacher writeObject exec...
Teacher readObject exec...
老师:007

我们在Student 类中增加 readResolve 方法:

    private Object readResolve() throws ObjectStreamException{
        System.out.println("readResolve exec...");
        return new Teacher("001");
    }

此时反序列化得到的老师对象仍是“老师:007”而不是“老师:001”,因为反序列化出的是Teacher对象,不会调用Student的readResolve 方法。

我们接着在Teacher类中添加 readResolve 方法:

private Object readResolve() throws ObjectStreamException{
        System.out.println("Teacher readResolve exec...");
        return new Teacher("001");
    }

此时序列化得到的老师对象才是“老师:001”。

我们把Student和Teacher类中的writeObject 方法、 readObject 方法、writeReplace 方法和、readResolve 方法四种方法都补齐,看一下调用顺序:

package serializable;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;


public class Teacher implements Serializable {
    private static final long serialVersionUID = 4644753740588166024L;

    private String teacherNo;

    public Teacher(String teacherNo) {
        this.teacherNo = teacherNo;
    }

    @Override
    public String toString() {
        return "老师:" + teacherNo;
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        System.out.println("Teacher readObject exec...");
    }

    private void writeObject(ObjectOutputStream out) throws IOException{
        out.defaultWriteObject();
        System.out.println("Teacher writeObject exec...");
    }

    private Object writeReplace() throws ObjectStreamException {
        System.out.println("Teacher writeReplace exec...");
        return this;
    }

    private Object readResolve() throws ObjectStreamException{
        System.out.println("Teacher readResolve exec...");
        return new Teacher("001");
    }
}
package serializable;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;

public class Student implements Serializable {
    private static final long serialVersionUID = 140932343675039705L;

    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString(){
        return "学生:" + name;
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        System.out.println("readObject exec...");
    }

    private void writeObject(ObjectOutputStream out) throws IOException{
        out.defaultWriteObject();
        System.out.println("writeObject exec...");
    }

    private Object writeReplace() throws ObjectStreamException{
        System.out.println("writeReplace exec...");
        return new Teacher("007");
    }

    private Object readResolve() throws ObjectStreamException{
        System.out.println("readResolve exec...");
        return new Teacher("001");
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student student = new Student();
        student.setName("小明");
        String filePath = "/Users/dcc/Downloads/student";
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filePath));
        out.writeObject(student);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
        Teacher teacher = (Teacher) in.readObject();
        System.out.println(teacher);
    }

}

程序输出结果:

writeReplace exec...
Teacher writeReplace exec...
Teacher writeObject exec...
Teacher readObject exec...
Teacher readResolve exec...
老师:001

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值