用循环引用序列化对象

9lowa7mx  于 2021-06-27  发布在  Java
关注(0)|答案(1)|浏览(402)

我有两个简单的类,代表一个公共汽车站的类:

import java.util.List;

public class Stop {
    /**
     * lines operating this stop
     */
    public List<Line> lines;
    public String label;

    public Stop(String label, List<Line> lines) {
        this.label = label;
        this.lines = lines;
    }

    public String getLabel() {
        return label;
    }

    public List<Line> getLines() {
        return lines;
    }

    @Override
    public String toString() {
        return "Stop{" +
                "label='" + label + '\'' +
                '}';
    }
}

还有一个代表公交线路的班级:

import java.util.ArrayList;
import java.util.List;

public class Line {
    public String label;
    public int id;
    public List<Stop> stops;

    public Line(String label, int id, List<Stop> stops) {
        this.label = label;
        this.id = id;
        this.stops = stops;
    }

    public Line(String label, int id) {
        this(label, id, new ArrayList<>());
        System.out.println("used second constructor");
    }

    public String getLabel() {
        return label;
    }

    public int getId() {
        return id;
    }

    public List<Stop> getStops() {
        return stops;
    }

    @Override
    public String toString() {
        return "Line{" +
                "label='" + label + '\'' +
                ", id=" + id +
                ", stops=" + stops +
                '}';
    }
}

我不想用java.beans.xmlcodector序列化这些,然后用xmldecover反序列化。
在这种情况下(当行包含对其停止的引用时,反之亦然),反序列化失败。解码器忽略 Line 带附加 List<Stop> stops 参数并使用 Line(String label, int id) 构造函数,请留下以下消息:

java.lang.IllegalStateException: Could not add argument to evaluated element
Continuing ...

当我在课堂上完全删除操作行列表时 Stop ,反序列化工作正常。
我做错什么了?
主要类别:

import java.beans.DefaultPersistenceDelegate;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;

public class App {
    public static void main(String[] args) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try (XMLEncoder encoder = new XMLEncoder(baos)) {
            encoder.setPersistenceDelegate(Line.class, new DefaultPersistenceDelegate(new String[] {"label", "id", "stops"}));
            encoder.setPersistenceDelegate(Stop.class, new DefaultPersistenceDelegate(new String[] {"label", "lines"}));
            ArrayList<Stop> stops = new ArrayList<>();
            stops.add(new Stop("Porte Maillot", new ArrayList<>()));
            stops.add(new Stop("Auber", new ArrayList<>()));
            Line line = new Line("A", 0, stops);
            stops.get(0).lines.add(line);
            stops.get(1).lines.add(line);
            encoder.writeObject(line);
        }
        System.out.println("xml:");
        System.out.println(baos);
        try (XMLDecoder decoder = new XMLDecoder(new ByteArrayInputStream(baos.toByteArray()))){
            Line line = (Line) decoder.readObject();
            System.out.printf("line: %s\n", line);
        }
    }
}

控制台输出:

xml:
<?xml version="1.0" encoding="UTF-8"?>
<java version="15.0.1" class="java.beans.XMLDecoder">
 <object class="Line" id="Line0">
  <string>A</string>
  <int>0</int>
  <object class="java.util.ArrayList">
   <void method="add">
    <object class="Stop">
     <string>Porte Maillot</string>
     <object class="java.util.ArrayList">
      <void method="add">
       <object idref="Line0"/>
      </void>
     </object>
    </object>
   </void>
   <void method="add">
    <object class="Stop">
     <string>Auber</string>
     <object class="java.util.ArrayList">
      <void method="add">
       <object idref="Line0"/>
      </void>
     </object>
    </object>
   </void>
  </object>
 </object>
</java>

used second constructor
java.lang.IllegalStateException: Could not add argument to evaluated element
Continuing ...
line: Line{label='A', id=0, stops=[]}
j2datikz

j2datikz1#

循环引用导致xmldecoder无法处理的循环序列化。使其中一个引用成为临时引用并在反序列化时恢复它们可以解决这个问题,就像使用二进制序列化而不是xml序列化一样。

相关问题