使用ReadObject和WriteObject的自定义序列化

时间:2018-08-23 05:53:44

标签: java serialization java-custom-serialization

我正在尝试使用WriteObject方法编写pojo类的实例。当我写这样的代码时:

    private void writeObject(ObjectOutputStream oos) throws IOException,ClassNotFoundException{ 
    oos.defaultWriteObject();    
    oos.writeObject(this);
}

它可以正常工作,但是当我尝试创建一个新的本地对象并将其传递给writeObject方法时,它会失败并显示

  

线程“ main”中的异常java.lang.StackOverflowError

有人可以解释为什么它不断递归地调用一次writeObject方法吗?

class Employee implements Serializable{
    private String name;
    private int age;
    private void readObject(ObjectInputStream ois) throws IOException,ClassNotFoundException{
        ois.defaultReadObject();
        Employee emp = (Employee)ois.readObject();
        emp.toString();
    }
    private void writeObject(ObjectOutputStream oos) throws IOException,ClassNotFoundException{
        oos.defaultWriteObject();
        Employee emp = new Employee("sumit",10);
        oos.writeObject(emp);
    }
    public Employee(){

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

2 个答案:

答案 0 :(得分:0)

这里发生的是'Employee'类是可序列化的。并且您已经覆盖了其中的writeObject方法。

现在,在此overridden方法中,您将再次创建Employee对象的实例并调用writeObject的{​​{1}}方法。

序列化逻辑检查要添加的对象是否可序列化。如果是,则对其进行序列化,否则将引发oos异常。

在这里,要添加的对象是NotSerializable。因此,它进行了序列化,并发现此Serializable的{​​{1}}方法已被覆盖。因此它调用了该方法。

现在再次转到您重写的方法逻辑,并再次执行相同的方法

Object

并且循环继续,导致writeObject错误,因为它以递归的方式反复调用它而不会中断

答案 1 :(得分:0)

这是因为您在writeObject类中覆盖了Employee方法。因此,当您创建Employee对象并尝试使用writeObject方法编写该对象时,将递归调用该对象,从而导致StackOverflow错误。

但是,当您不编写Employee对象时,代码将正确执行。

---根据评论中的说明进行编辑

Employee类中,您正在覆盖writeObject方法,因此,每当尝试使用ObjectOutputStream.writeObject作为参数调用Employee时,您覆盖的方法将是调用。 现在,在writeObject类的覆盖的Employee中,您再次以Employee为参数调用ObjectOutputStream.writeObjectoos.writeObject(emp);),因此,{{1 }}类被递归调用(每次使用新的Employee对象 ),并且会出现 stackoverflow 错误。

现在,如果您尝试递归调用writeObject关键字,是因为您尝试使用Employee类的相同实例来调用this。根据下面提到的链接的ObjectOutputStream.writeObject文档:

https://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html

使用引用共享机制对单个对象的多个引用进行编码,以便可以将对象的图恢复为与原始图相同的形状。

实际上,如果您在主要方法中尝试以下代码:

Employee

即,如果您在同一对象上多次调用ObjectOutputStream.writeObject,则只会被调用一次。