使用JAXB unmarshaller时,我遇到了有关AtomicInteger的问题。我有以下示例代码,我试图从xml文件解组MyTree。我使用AtomicInteger为每个Vertex创建一个唯一的id。解组MyTree时,它会在创建边时增加。如果我在topexList中有三个顶点,在myTree.xml中有edgeList中的两个边,则在解组后创建一个新顶点的nextID将创建8而不是4.因为对于每个边,它为sourceVertex和targetVertex添加一个顶点。你能帮我弄清楚我做错了什么吗?我该如何克服这个问题。非常感谢。 (我是JAVA和JAXB的新手)
JAXBContext context= JAXBContext.newInstance(MyTree.class);
Unmarshaller unmarshaller= context.createUnmarshaller();
MyTree newTree= (MyTree) unmarshaller.unmarshal(new File("MyTree.xml"));
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class MyTree{
ArrayList<Vertex> vertexList =new ArrayList<Vertex>();
ArrayList<Edge> edgeList = new ArrayList<Edge>();
public MyTree() {
}
...
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Vertex{
public int vertexId;
private static AtomicInteger nextId = new AtomicInteger(0);
public Vertex() {
this.vertexId=nextId.incrementAndGet();
}
...
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Edge {
private Vertex sourceVertex;
private Vertex targetVertex;
private EdgeType edgeType;
public Edge () {
}
...
}
enum EdgeType
{
White,
Red,
Blue;
}
答案 0 :(得分:0)
很难从你提供的代码中看出实际的最佳解决方案,但你可以这样做:
据我所知,有两种方法可以通过构造函数或反序列化来创建Vertex
,后者通过过于频繁地调用构造函数来创建问题。因此,将id管理删除到另一个类,并在您确定需要时仅请求ID。
首先,您需要将代码重构为构造函数,而不是递增计数器。所以
@XmlRootElement
class Vertex {
private int vertexId;
public Vertex() { // initialize without incrementing the counter
}
}
将id管理移至单独的类。例如
class VertexManager {
// Singleton
private static VertexManager INSTANCE;
private VertexManager() { }
public static VertexManager getInstance() {
if (INSTANCE == null) { INSTANCE = new VertexManager(); }
return INSTANCE;
}
// keep track of the ids
private AtomicInteger currentId = new AtomicInteger();
// create new vertex
public static Vertex create() {
Vertex created = new Vertex();
register(created);
return created;
}
// add previously created vertex
public void register(Vertex v) {
int id = currentId.incrementAndGet();
v.setId(id);
}
}
现在你所有的当前代码都依赖于构造函数递增它,你必须确保所有这些地方都使用VertexManager#create()
代替!我建议将Vertex
构造函数设置为private以在使用它时引发编译器错误,然后在更改它们之后重置。
您的反序列化完成时可以使用的register
方法;在读取树之后,所有Vertex
es都是稳定的 - 但是它们仍然需要分配它们的ID。所以
JAXBContext context= JAXBContext.newInstance(MyTree.class);
Unmarshaller unmarshaller= context.createUnmarshaller();
MyTree newTree= (MyTree) unmarshaller.unmarshal(new File("MyTree.xml"));
newTree.getVertices().forEach(v -> VertexManager.getInstance().register(v));