【问题标题】:Custom Serialization using ReadObject and WriteObject使用 ReadObject 和 WriteObject 的自定义序列化
【发布时间】:2019-01-29 10:32:15
【问题描述】:

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

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

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

线程“主”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;
    }   
}

【问题讨论】:

  • 你能分享整个课程代码吗..
  • 由于网络限制,我无法访问它..您可以在这里添加它..
  • class Employee 实现 Serializable{ private String name;私人年龄; private void readObject(ObjectInputStream ois) 抛出 IOException,ClassNotFoundException{ ois.defaultReadObject();员工 emp = (Employee)ois.readObject(); emp.toString(); } private void writeObject(ObjectOutputStream oos) 抛出 IOException,ClassNotFoundException{ oos.defaultWriteObject();员工 emp = new Employee("summit",10); oos.writeObject(emp); } public Employee(){ } public Employee(String name, int age){ this.name = name; this.age = 年龄; } }
  • 能否请您以正确的格式添加它..因为代码很难以这种方式弄清楚

标签: java serialization java-custom-serialization


【解决方案1】:

这里发生的是“Employee”类是可序列化的。而且你已经在其中覆盖了writeObject 方法。

现在在这个overridden 方法中,您再次创建Employee 对象的实例并调用ooswriteObject 方法。

序列化逻辑检查添加的对象是否可序列化。如果是,则序列化,否则抛出NotSerializable异常。

这里,要添加的对象是Serializable。因此它去序列化它并发现这个Object 覆盖了writeObject 方法。所以它调用了那个方法。

现在它再次进入您覆盖的方法逻辑并再次调用相同的方法

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

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

【讨论】:

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

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

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

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

在您的 Employee 类中,您将覆盖 writeObject 方法,因此,每当您尝试以 Employee 作为参数调用 ObjectOutputStream.writeObject 时,将调用您被覆盖的方法。 现在,在 Employee 类中重写的 writeObject 中,您再次以 Employee 作为参数调用 ObjectOutputStream.writeObject( oos.writeObject(emp);),因此,writeObject 类的 writeObject 方法被递归调用(使用 new Employee 对象每次),你会得到 stackoverflow 错误。

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

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

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

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

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

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

【讨论】:

  • 序列化与对象的创建有何关系?无论我传递什么都应该被保存,无论是新对象还是现有对象?
  • 实际上我想了解为什么当我将此对象传递给 writeObject 方法时它不会递归调用:oos.defaultWriteObject(); oos.writeObject(this);
猜你喜欢
  • 2015-08-18
  • 2011-08-20
  • 1970-01-01
  • 2013-01-22
  • 1970-01-01
  • 1970-01-01
  • 2019-11-19
  • 2018-01-05
  • 1970-01-01
相关资源
最近更新 更多