2014-06-10 13 views
6

Cosa succede durante la serializzazione in java, se due rifrazioni di oggetti puntano allo stesso oggetto serializzabile? Gli oggetti serializzabili vengono salvati due volte?
ad esempio:Cosa succede durante la serializzazione in java, se due rifrazioni di oggetti puntano allo stesso oggetto serializzabile?

class King implements java.io.Serializable { 
     private String name="Akbar"; 
    } 

    class Kingdom implements java.io.Serializable { 
     King goodKing=new King(); 
     King badKing=goodKing; 
    } 

    public class TestSerialization { 
     public static void serializeObject(String outputFileName, 
              Object serializableObject) throws IOException { 
      FileOutputStream fileStream=new FileOutputStream(outputFileName); 
      ObjectOutputStream outStream=new ObjectOutputStream(fileStream); 
      outStream.writeObject(serializableObject); 
      outStream.close(); 
     } 

     public static void main(String[] args) { 
      Kingdom kingdom=new Kingdom(); 
      try { 
       TestSerialization.serializeObject("Kingdom1.out", kingdom); 
      }catch(IOException ex) { 
       ex.getMessage(); 
      } 
     } 
    } 

Ora, se lo stato solo un oggetto viene salvato sia per goodKing e badKing refrences o l'oggetto re vengono salvati due volte?

+1

Hai provato a salvare la classe con uno e due riferimenti e confrontato la dimensione del file del risultato? – Smutje

+1

Prova a deserializzare Kingdom e vedi se goodKing e badKing puntano allo stesso King. Se lo sono, quindi avere un Re in Kingdom1.out è sufficiente deserializzare il Regno. Da ciò, possiamo supporre che sia stato salvato solo uno stato dell'oggetto. – fajarkoe

+0

@Smutje Il file generato mostra sempre di essere di dimensione 1KB –

risposta

7

La documentazione per ObjectOutputStream dice cosa succede:

Il meccanismo di serializzazione di default per un oggetto scrive la classe dell'oggetto, la firma di classe, ed i valori di tutti i campi non transienti e non statici. I riferimenti ad altri oggetti (ad eccezione dei campi transitori o statici) fanno sì che anche questi oggetti vengano scritti. Più riferimenti a un singolo oggetto vengono codificati utilizzando un meccanismo di condivisione di riferimento in modo che i grafici degli oggetti possano essere ripristinati nella stessa forma di quando è stato scritto l'originale.

(corsivo mio)

Ad esempio, se si dispone di più riferimenti a un singolo oggetto, quando il grafico è ricostituita, si finisce con più riferimenti a una sola versione ricostituito di tale oggetto, non riferimenti a più istanze equivalenti di esso.

Ovviamente, se il contenitore che viene serializzato implementa un meccanismo diverso, il comportamento è dettato da quel meccanismo, non da quello predefinito.

Così, per esempio, se abbiamo Thing e Test:

Thing.java:

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

public class Thing implements Serializable { 
    private Map<String,String> map1; 
    private Map<String,String> map2; 

    public Thing() { 
     this.map1 = new HashMap(); 
     this.map2 = this.map1; // Referring to same object 
    } 

    public void put(String key, String value) { 
     this.map1.put(key, value); 
    } 

    public boolean mapsAreSameObject() { 
     return this.map1 == this.map2; 
    } 
} 

Test.java:

import java.io.*; 

public class Test implements Serializable { 

    public static final void main(String[] args) { 
     try 
     { 
      // Create a Thing 
      Thing t = new Thing(); 
      t.put("foo", "bar"); 

      // Write it out 
      ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("foo")); 
      os.writeObject(t); 
      os.close(); 
      os = null; 

      // Read it in 
      Thing t2; 
      ObjectInputStream is = new ObjectInputStream(new FileInputStream("foo")); 
      t2 = (Thing)is.readObject(); 
      is.close(); 
      is = null; 

      // Same underlying map for both properties? 
      System.out.println("t2.mapsAreSameObject? " + t2.mapsAreSameObject()); 
     } 
     catch (Exception e) 
     { 
      System.out.println("Exception: " + e.getMessage()); 
     } 
    } 
} 

e correre java Test, otteniamo:

t2.mapsAreSameObject? true

... perché entrambi i membri di Thing, map1 e map2 finiscono per puntare a una singola istanza HashMap.

+0

Intendi dire che indipendentemente dal no di rifrazioni a un singolo oggetto, solo una copia di quell'oggetto sarà salvata durante la serializzazione e durante la serializzazione, ogni rifrazione a quel singolo oggetto verrà ricostruita come nella classe originale. –

+0

@AmiteshRai: Giusto. O meglio, questo è quello che dice la documentazione. :-) E ancora, questo è con la serializzazione predefinita; se un contenitore implementa la propria serializzazione, potrebbe fare qualcos'altro (anche se fare qualcos'altro sarebbe strano e sorprendente). –

+0

@ T.J.Crowder - Non capisco bene ... Perché i riferimenti dovrebbero apparire durante la serializzazione ?. La serializzazione è più o meno il dumping dell'oggetto. Quanti riferimenti puntano all'oggetto non dovrebbero avere importanza. destra? – TheLostMind

Problemi correlati