这是我的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,依此类推,则递归算法可能必须深入到导致堆栈溢出的地步。

如果那是引起您问题的原因,则应编写自己的readObjectwriteObject,如果可能的话,应避免这种递归构建。

10-05 22:55