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

#java #sockets #client

#java #io #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<Integer> same = new ArrayList<Integer>();
                    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);
    }
}
  

Ответ №1:

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

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

Ответ №2:

Значение Max верно, но вы также можете использовать:

 public void writeUnshared(Object obj);
  

Смотрите Комментарий ниже для предостережения

Комментарии:

1. Это будет работать в этом случае, но обычно вызывает действительно странные ошибки. Любой записанный объект компонента все равно будет использоваться совместно. Так, например, если приведенный выше список был обернут коллекциями. synchronizedList, проблема останется. writeUnshared не очень полезен.