3
public static void main(String[] args) throws Exception {
    Socket socket = new Socket("127.0.0.1", 2345);

    ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
    Map<Integer, Integer> testMap = new HashMap<Integer, Integer>();

    testMap.put(1,1);
    oos.writeObject(testMap);
    oos.flush();

    testMap.put(2,2);
    oos.writeObject(testMap);
    oos.flush();

    oos.close();
}


public static void main(String[] args) throws Exception {
    ServerSocket ss = new ServerSocket(2345);
    Socket s = ss.accept();
    ObjectInputStream ois = new ObjectInputStream(s.getInputStream());

    System.out.println((HashMap<Integer, Integer>) ois.readObject());
    System.out.println((HashMap<Integer, Integer>) ois.readObject());

    ois.close;
}

上記のコードは2つのファイルからのものです。それらを実行すると、コンソールは同じ結果を出力します。

{1=1}
{1=1}

これはどのように起こりますか?

4

2 に答える 2

6

ObjectOutputStreamは、すでに書き込んだオブジェクトを記憶しており、書き込みを繰り返すと、ポインターのみが出力されます(内容は出力されません)。これはオブジェクトのアイデンティティを保持し、循環グラフに必要です。

つまり、ストリームに含まれるものは基本的に次のとおりです。

  • 内容が{1:1}のHashMap A
  • ポインタ:「HashMapAagain」

ケースでは、新しいHashMapインスタンスを使用する必要があります。

于 2012-05-30T02:58:39.493 に答える
2

ティロがすでに言ったように、はObjectOutputStreamそれがすでに書いたもののキャッシュを保持します。彼が提案するように新しいマップを使用するか、キャッシュをクリアすることができます。

の呼び出しObjectOutputStream.resetの間に呼び出すとwriteObject、キャッシュがクリアされ、最初に期待した動作が得られます。

public static void main(String[] args) throws IOException,
        ClassNotFoundException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
        HashMap<Integer, Integer> foo = new HashMap<>();
        foo.put(1, 1);
        oos.writeObject(foo);
        // oos.reset();
        foo.put(2, 2);
        oos.writeObject(foo);
    }

    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    try (ObjectInputStream ois = new ObjectInputStream(bais)) {
        System.out.println(ois.readObject());
        System.out.println(ois.readObject());
    }
}
于 2012-05-30T03:02:41.320 に答える