2008-09-26 2 views
18

У меня есть следующий код, который показывает ошибку или недоразумение с моей стороны.Отправка того же, но измененного объекта над 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); 
    } 
} 

ответ

24

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

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

-3

То, что вы, вероятно, хотите есть:

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.

+0

Нет, это не помогло, Макс был прав, используйте reset() – Pyrolistical 2008-09-27 01:24:56

+0

Это не сработает. `flush()` не обладает магическими свойствами, приписываемыми ему здесь. – EJP 2017-12-12 07:17:56

6

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

public void writeUnshared(Object obj); 

Смотрите комментарии ниже предостережение

+2

Это будет работать в этом случае, но, как правило, вызывает очень странные ошибки. Любой написанный компонент будет по-прежнему использоваться совместно. Так, например, если список выше был завернут с Collections.synchronizedList, проблема осталась бы. writeUnshared не очень полезен. – 2008-09-27 14:15:08

0

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

public void reset() throws IOException 

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

Смежные вопросы