自定义序列化使用ReadObject和WriteObject

3

我正在尝试使用WriteObject方法编写POJO类的实例。当我编写以下代码时:

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

它的运行很好,但是当我尝试创建一个新的本地对象并将其传递给writeObject方法时,它会出现失败:

Exception in thread "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;
    }   
}

请问您能否分享整个类的代码? - codeLover
代码链接:https://drive.google.com/file/d/1rq6nW0XICDnRFXRp9Hanc14lonK21eiU/view?usp=sharing - amit kumar
class Employee实现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; } } - amit kumar
你能否请以适当的格式添加它?因为这种方式下代码很难理解。 - codeLover
我无法格式化评论,所以将其添加到帖子本身中。 - amit kumar
显示剩余2条评论
2个回答

0
这里发生的是“Employee”类被序列化。而你已经在其中覆盖了“writeObject”方法。
现在在这个覆盖的方法中,你又创建了一个“Employee”对象的实例,并调用了“oos”的“writeObject”方法。
序列化逻辑检查正在添加的对象是否可序列化。如果是,则将其序列化,否则抛出“NotSerializable”异常。
这里,正在添加的对象是可序列化的。因此它会序列化它,并发现这个“Object”已经覆盖了“writeObject”方法。所以它调用那个方法。
现在再次进入你的覆盖方法逻辑,并再次执行相同的方法调用。
oos.defaultWriteObject(); 
Employee emp = new Employee("sumit",10); 
oos.writeObject(emp);

循环继续,导致StackOverflow错误,因为它一遍又一遍地递归调用而没有中断。


实际上,我想了解为什么当我将此对象传递给writeObject方法时,它不会递归调用: oos.defaultWriteObject(); oos.writeObject(this); - amit kumar
序列化与对象的创建有什么关系?无论是新对象还是现有对象,我传递的任何内容都应该被保存,对吗? - amit kumar
因为当你使用 this 时,你基本上是传递了在第一次调用 writeObject 方法时传递的相同对象,很可能是在 public static void main() 中。但是使用其他代码时,你又创建了同一类的新对象/引用,导致递归。 - Ashishkumar Singh
如果您将writeObject代码移动到邮件类中,则错误应该会消失。因为现在Employee类没有覆盖writeObject,所以它只会被调用一次。 - Ashishkumar Singh

0
这是因为你在Employee类中覆盖了writeObject方法。因此,当你创建Employee对象并尝试使用writeObject方法将其写入时,它会递归调用并导致StackOverflow错误。
但是,当你不写Employee对象时,代码能够正常执行。
--根据评论所请求的澄清进行编辑
在你的Employee类中,你正在覆盖writeObject方法,因此,无论何时,你尝试使用ObjectOutputStream.writeObject并将Employee作为参数进行调用时,你的覆盖方法都会被调用。 现在,在你覆盖的Employee类的writeObject中,你又调用了ObjectOutputStream.writeObject( oos.writeObject(emp);)带有Employee作为参数,因此,Employee类的writeObject方法会被递归调用(每次调用时使用新的Employee对象),导致stackoverflow错误。

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

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

使用引用共享机制对单个对象进行多次引用编码,以便在恢复对象图形时与原始写入时的形状相同。

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

Employee emp = new Employee("sumit",10);
oos.writeObject(emp);
oos.writeObject(emp);

例如,如果您在同一对象上多次调用writeObject,它只会被调用一次。

序列化与对象的创建有什么关系?无论是新对象还是现有对象,我传递的任何内容都应该被保存,对吗? - amit kumar
实际上,我想了解为什么当我将此对象传递给writeObject方法时,它不会递归调用:oos.defaultWriteObject(); oos.writeObject(this); - amit kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接