Подтвердить что ты не робот

Отправка того же, но измененного объекта поверх ObjectOutputStream

У меня есть следующий код, который показывает ошибку или недоразумение с моей стороны.

Я отправил тот же список, но был изменен над ObjectOutputStream. Один раз как [0] и другие как [1]. Но когда я его прочитал, я получаю [0] дважды. Я думаю, что это связано с тем, что я отправляю один объект и ObjectOutputStream должен каким-то образом кэшировать их.

Является ли эта работа такой, какой она есть, или мне нужно указать ошибку?

import java.io.*;
import java.net.*;
import java.util.*;

public class OOS {

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                try {
                    ServerSocket ss = new ServerSocket(12344);
                    Socket s= ss.accept();

                    ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
                    List same = new ArrayList();
                    same.add(0);
                    oos.writeObject(same);
                    same.clear();
                    same.add(1);
                    oos.writeObject(same);

                } catch(Exception e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();

        Socket s = new Socket("localhost", 12344);
        ObjectInputStream ois = new ObjectInputStream(s.getInputStream());

        // outputs [0] as expected
        System.out.println(ois.readObject());

        // outputs [0], but expected [1]
        System.out.println(ois.readObject());
        System.exit(0);
    }
}
4b9b3361

Ответ 1

В потоке есть ссылочный граф, поэтому объект, который отправляется дважды, не даст двух объектов на другом конце, вы получите только один. И отправка одного и того же объекта дважды по отдельности даст вам один и тот же экземпляр дважды (каждый с теми же данными - это то, что вы видите).

См. метод reset(), если вы хотите reset график.

Ответ 2

Макс правильный, но вы также можете использовать:

public void writeUnshared(Object obj);

См. комментарий ниже для caveat

Ответ 3

ObjectOutputStream кэширует экземпляры, которые он отправляет по проводу (не обязательно лучший дизайн tbh). Но в любом случае вам нужно reset выходные потоки между вызовами, если вы планируете использовать его для (повторного) отправки одного и того же экземпляра объекта.

public void reset() throws IOException

Reset будет игнорировать состояние любых объектов, уже записанных в поток. Состояние reset будет таким же, как новый ObjectOutputStream. Текущая точка в потоке отмечена как reset, поэтому соответствующая ObjectInputStream будет reset в той же точке. Объекты, ранее записанные в поток, не будут упоминаться как уже находящиеся в потоке. Они снова будут записаны в поток.

Ответ 4

Что вы, возможно, захотите:

ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
List same = new ArrayList();
same.add(0);
oos.writeObject(same);
oos.flush();  // flush the stream here
same.clear();
same.add(1);
oos.writeObject(same);

В противном случае один и тот же объект будет дважды сброшен, когда поток будет закрыт или его буфер закончится.

Просто FYI, когда вы десериализуете объекты, скажем o1 и o2, o1 != o2.