【发布时间】:2021-01-04 14:05:26
【问题描述】:
我有 2 个简单的类,代表一个公共汽车站的类:
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.XMLEncoder 序列化这些,然后使用 XMLDecoder 反序列化。
在这种情况下(当行保持对它的停止的引用时,反之亦然),反序列化失败。解码器忽略带有附加 List<Stop> stops 参数的 Line 构造函数并使用 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=[]}
【问题讨论】:
-
循环引用会导致循环序列化,例如“A 包含 B 包含 A 包含 B ...”。要打破这一点,您需要将其中一个引用设为瞬态或将它们标记为被序列化忽略并在反序列化时恢复它们(例如,当将一行添加到停止时,您也将停止添加到该行)。跨度>
-
@Thomas 所以没有办法反序列化具有循环引用的实例而不保持其中一个是瞬态的并稍后同步它们?
-
好吧,我不知道有什么工具可以开箱即用地进行 XML 序列化(Java 的标准二进制序列化机制应该能够处理它)。编写 XML 或 JSON 等文本的序列化程序需要一些帮助来确定如何处理(和中断)循环。
-
好的,谢谢,我试试二进制序列化。
标签: java xml serialization xml-deserialization