2008-09-26 16 views
18

Tengo el siguiente código que muestra un error o un malentendido de mi parte.Enviando el mismo objeto pero modificado sobre ObjectOutputStream

Envié la misma lista, pero modificada sobre un ObjectOutputStream. Una vez como [0] y otra como [1]. Pero cuando lo leo, obtengo [0] dos veces. Creo que esto se debe al hecho de que estoy enviando el mismo objeto y ObjectOutputStream debe almacenarlos en caché de alguna manera.

¿Es este trabajo como debería, o debería presentar un error?

 
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); 
    } 
} 

Respuesta

24

La corriente tiene un gráfico de referencia, por lo que un objeto que se envía dos veces no dará dos objetos en el otro extremo, no harán más que una. Y enviar el mismo objeto dos veces por separado le dará la misma instancia dos veces (cada una con la misma información, que es lo que está viendo).

Consulte el método de restauración() si desea restablecer el gráfico.

-3

Lo que probablemente quiere decir:

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); 

De lo contrario el mismo objeto se vaciarán dos veces cuando la corriente está cerrado o su buffer se agota.

Solo FYI, cuando deserializa los objetos en, digamos o1 y o2, o1 != o2.

+0

No, eso no lo resolvió, Max tenía razón, use reset() – Pyrolistical

+0

Esto no funciona. 'flush()' no tiene las propiedades mágicas que se le atribuyen aquí. – EJP

6

Max es correcta, pero también se puede utilizar:

public void writeUnshared(Object obj); 

Véase el comentario a continuación para salvedad

+2

Eso funcionará en este caso, pero generalmente causará errores realmente extraños. Cualquier objeto componente escrito aún será compartido. Entonces, por ejemplo, si la lista de arriba estaba envuelta con Collections.synchronizedList, el problema permanecería. writeUnshared no es muy útil. –

0

Los cachés ObjectOutputStream casos que envía a través del cable (no necesariamente el mejor diseño TBH). Pero en cualquier caso, debe restablecer las secuencias de salida entre llamadas si planea usarla para (re) enviar la misma instancia de objeto.

public void reset() throws IOException 

Restablecer ignorará el estado de los objetos ya escritos en la secuencia. El estado se restablece para que sea el mismo que el nuevo ObjectOutputStream. El punto actual en la secuencia se marca como reinicio por lo que el ObjectInputStream correspondiente se reiniciará en el mismo punto. Los objetos previamente escritos en la secuencia no se mencionarán como que ya están en la secuencia. Se escribirán en la corriente de nuevo.

+0

Es el único diseño posible dado el objetivo de diseño de preservar gráficos de objetos. – EJP

+0

Plagiado de [aquí] (https://stackoverflow.com/a/8956926/207421). – EJP

Cuestiones relacionadas