这是我的Java代码:
FileOutputStream fos = null;
ObjectOutputStream out = null;
try {
fos = new FileOutputStream(pathName);
out = new ObjectOutputStream(fos);
out.writeObject(index);
out.close();
fos.close();
} catch (IOException e) {
LogManager.writeLogToFile(e.getMessage());
e.printStackTrace();
}
索引是我自己的反向文档索引的一个实例。我已经在内存中建立了对象索引,但是当我将其传递给方法writeObject(index)时,出现错误StackOverflowError。我的问题是:为什么我在内存中建立了对象之后会发生此错误?
假设索引的数据结构如下:
class InvertedIndex{
private HashMap<String, PostList> index;
}
class PostList{
private int size;
private PostNode first;
}
class PostNode{
private String key;
private double weight;
private PostNode next;
}
为了避免递归调用,我覆盖了PostList的writeObject和readObject方法,因为它可能是一个很长的列表:
class PostList{
private void writeObject(ObjectOutputStream out) throws IOException{
PostNode temp = first;
while(temp != null){
out.writeObject(temp);
temp = temp.getNext();
}
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
in.defaultReadObject();
}
}
然后我有两个问题:
out.writeObject(temp);因为temp引用了下一个节点,所以当我编写temp时,也会发生递归调用。即使我用defaultWriteObject覆盖PostNode的writeObject方法,相同的情况也将继续。我对吗?如果是这样,我该怎么做才能避免此递归调用?
如何覆盖方法readObject()?
最佳答案
在不看到要序列化的类的情况下很难知道,但是我的猜测是对象图太复杂了。 Java的默认序列化机制通过对象图递归地工作。也就是说,如果您的对象A引用了B,并且您序列化了A,则必须走到B并对其进行序列化。如果B然后引用C,C引用D,依此类推,则递归算法可能必须深入到导致堆栈溢出的地步。
如果那是引起您问题的原因,则应编写自己的readObject
和writeObject
,如果可能的话,应避免这种递归构建。