2012-09-09 10 views
11

Sto scrivendo un piccolo programma basato su socket. Sto usando una classe ModelEvent per passare informazioni attraverso il socket. all'interno di ModelEvent, c'è una variabile obect di tipo (Object).Presa Java/serializzazione, l'oggetto non verrà aggiornato

L'oggetto stesso è un array 2D con alcuni valori.

object[1][2] = 2; 
ModelEvent event = new ModelEvent("allo", object); 
dispatchEvent(event); 

object[2][3] = 2; 
ModelEvent event2 = new ModelEvent("you", object); 
dispatchEvent(event2); 

Supponiamo che l'oggetto array è riempito con il valore 1. Il primo evento (evento) viene ricevuto dal client e il dato è giusto. Il secondo evento inviato nonostante i dati non è corretto. I suoi dati sono gli stessi della prima spedizione. lo "allo" e "tu" è vedere se non sto leggendo lo stesso evento due volte e la risposta non lo è. La stringa è giusta, ma l'oggetto no, evento se è stato aggiornato. I iterare attraverso la matrice prima di inviare il secondo evento per vedere se è aggiornato sul lato server, e lo è. Ma dal lato client, rimane lo stesso del primo invio, anche se l'evento stesso viene modificato.

+0

Come stai leggendo sul lato client? –

+0

ObjectInputStream.readObject e l'ho lanciato – maniak

risposta

20

Vedere ObjectOutputStream.reset.

Reset ignorerà lo stato di qualsiasi oggetto già scritto nello stream. Lo stato viene reimpostato per essere uguale a un nuovo ObjectOutputStream. Il punto corrente nel flusso viene contrassegnato come ripristinato, quindi il corrispondente ObjectInputStream verrà ripristinato nello stesso punto. Gli oggetti precedentemente scritti nello stream non verranno indicati come già presenti nello stream. Saranno nuovamente scritti nel flusso.

/* prevent using back references */ 
output.reset(); 
output.writeObject(...); 

ripristino di chiamata prima di scrivere lo stesso oggetto per garantire il suo stato aggiornato è serializzato. In caso contrario, verrà utilizzato semplicemente uno riferimento posteriore per l'oggetto precedentemente scritto con il suo stato obsoleto.

Oppure, è possibile utilizzare alternativamente ObjectOutputStream.writeUnshared come segue.

Scrive un oggetto "non condiviso" su ObjectOutputStream. Questo metodo è identico a writeObject, ad eccezione del fatto che scrive sempre l'oggetto dato come un nuovo oggetto univoco nello stream (al contrario di un riferimento all'indietro che punta a un'istanza serializzata in precedenza).

particolare:

  • Scopo scritta tramite writeUnshared è sempre serializzato nello stesso modo di un oggetto appena appare (un oggetto che non è stato scritto nel flusso ancora), indipendentemente dal fatto che il l'oggetto è stato scritto in precedenza.

  • Se writeObject viene utilizzato per scrivere un oggetto che è stato precedentemente scritto con writeUnshared, l'operazione writeUnshared precedente viene considerata come se fosse una scrittura di un oggetto separato. In altre parole, ObjectOutputStream non genererà mai riferimenti di ritorno ai dati oggetto scritti dalle chiamate a writeUnshared.

Mentre crei un oggetto tramite writeUnshared sé non garantire un riferimento unico all'oggetto quando viene deserializzare, permette un singolo oggetto da definire più volte in un flusso, in modo che più chiamate a readUnshared by il ricevitore non entrerà in conflitto.Si noti che le regole descritte sopra si applicano solo all'oggetto di livello base scritto con e non a qualsiasi oggetto secondario referenziato in modo transitorio nel grafico dell'oggetto da serializzare.

output.writeUnshared(...); 

Nota è buona norma Coppia questo con ObjectInputStream.readUnshared.

Legge un oggetto "non condiviso" da ObjectInputStream. Questo metodo è identico a readObject, tranne per il fatto che impedisce le chiamate successive a readObject e readUnshared di restituire ulteriori riferimenti all'istanza deserializzata ottenuta tramite questa chiamata.

In particolare:

  • Se readUnshared è chiamato a deserializzare un back-di riferimento (la rappresentazione corrente di un oggetto che è stato scritto in precedenza per il flusso), un ObjectStreamException saranno gettati
  • If readUnshared rendimenti con successo, quindi qualsiasi tentativo successivo di deserializzare i riferimenti di ritorno allo stream handle deserializzato da readUnshared causerà il lancio di ObjectStreamException.

La deserializzazione di un oggetto tramite readUnshared invalida l'handle di flusso associato all'oggetto restituito. Si noti che questo di per sé non garantisce sempre che il riferimento restituito da readUnshared sia univoco; l'oggetto deserializzato può definire un metodo readResolve che restituisce un oggetto visibile ad altre parti oppure readUnshared può restituire un oggetto Class o una costante enum ottenibile altrove nello stream o tramite mezzi esterni. Se l'oggetto deserializzato definisce un metodo readResolve e l'invocazione di tale metodo restituisce una matrice, quindi readUnshared restituisce un clone superficiale di tale matrice; questo garantisce che l'oggetto array restituito è univoco e non può essere ottenuto una seconda volta da una chiamata di readObject o readUnshared su ObjectInputStream, anche se il flusso di dati sottostante è stato manipolato.

obj = input.readUnshared(); 
+1

Voglio baciarti adesso! * no homo * Grazie. Giusto per capire, quando un oggetto viene inviato due volte allo stream, ricorda il suo stato precedente e usa quello vecchio? – maniak

+0

Sì, lo fa :)! Penso che sia per ragioni di prestazioni, ma non si adatta all'utilizzo che vuoi fare di esso. – Flawyte

3

non vedo il codice dispatchEvent, ma da quello che hai scritto Suppongo che il seguente: si scrive lo stesso oggetto (solo il suo stato cambiato), questo significa che scriverà solo il riferimento due volte . puoi vedere i documenti di output output di java (per le prestazioni).

si dovrebbe usare writeUnshared(), che creerà un nuovo oggetto su ogni scrittura

vedo reset è stato suggerito, questo si arriva allo stesso risultato, ma ha impatto sulle prestazioni.

+0

+1 per sottolineare l'impatto sulle prestazioni. Stavo modificando la mia risposta per includere 'writeUnshared' mentre hai postato. – oldrinb

+1

-1 per "impatto sulle prestazioni". L'unica differenza tra writeUnshared() e reset()/writeObject() è che nel primo caso gli oggetti referenziati possono ancora essere inviati come handle.Questa è una differenza * funzionale * importante, e potrebbe non essere affatto ciò che l'OP vuole. Ridurre tutto ciò a un semplice "impatto sulle prestazioni" è completamente errato e completamente fuorviante. – EJP