2014-06-10 7 views
6

Was passiert während der Serialisierung in Java, wenn zwei References auf dasselbe serialisierbare Objekt zeigen? Werden die serialisierbaren Objekte zweimal gespeichert?
zum Beispiel:Was passiert während der Serialisierung in Java, wenn zwei References auf dasselbe serialisierbare Objekt verweisen?

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

Nun, ob nur ein Objekt Zustand für beide gespeichert goodKing und badKing refrences oder das Objekt König zweimal gerettet werden?

+1

Haben Sie versucht, die Klasse mit ein und zwei Referenzen zu speichern und die Dateigröße des Ergebnisses verglichen? – Smutje

+1

Versuchen Sie, Königreich zu deserialisieren, und sehen Sie, ob GoodKing und BadKing auf den gleichen König zeigen. Wenn das der Fall ist, genügt es, ein Königreich in Kingdom1.out zu haben, um das Königreich zu deserialisieren. Daraus können wir erraten, dass nur ein Objektstatus gespeichert ist. – fajarkoe

+0

@Smutje Die generierte Datei zeigt immer die Größe 1KB –

Antwort

7

Die Dokumentation für ObjectOutputStream sagt, was passiert:

Der Standard Serialisierungsmechanismus für ein Objekt schreibt die Klasse des Objekts, der Klassensignatur und die Werte aller nicht-flüchtig und nicht-statische Felder. Verweise auf andere Objekte (außer in transienten oder statischen Feldern) bewirken, dass diese Objekte auch geschrieben werden. Mehrere Verweise auf ein einzelnes Objekt werden mithilfe eines Verweisfreigabemechanismus codiert, sodass Diagramme von Objekten in derselben Form wiederhergestellt werden können, in der das Original geschrieben wurde.

(Hervorhebung von mir)

Eg, wenn Sie mehrere Verweise auf ein einzelnes Objekt haben, wenn der Graph wieder hergestellt ist, können Sie mit mehreren Verweisen auf eine einzige rekonstituiert Version dieses Objekts am Ende, nicht Verweise auf mehrere gleichwertige Instanzen davon.

Natürlich, wenn der serialisierte Container einen anderen Mechanismus implementiert, wird das Verhalten von diesem Mechanismus diktiert, nicht der Standard.

So zum Beispiel, wenn wir Thing und Test haben:

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

Und laufen java Test, erhalten wir:

t2.mapsAreSameObject? true

... weil beide Thing Mitglieder, map1 und map2 am Ende auf eine einzige HashMap Instanz zeigen.

+0

Sie wollen sagen, dass unabhängig von der Anzahl der References zu einem einzelnen Objekt nur eine Kopie dieses Objekts während der Serualisierung gespeichert wird und während der Serialisierung jeder Verweis auf dieses einzelne Objekt wieder wie in der ursprünglichen Klasse rekonstruiert wird. –

+0

@AmiteshRai: Richtig. Oder besser gesagt, das sagt die Dokumentation. :-) Und wieder, das ist mit Standard-Serialisierung; Wenn ein Container seine eigene Serialisierung implementiert, könnte er etwas anderes tun (obwohl etwas anderes seltsam und überraschend wäre). –

+0

@ T.J.Crowder - Ich verstehe nicht ganz .. Warum würden Referenzen während der Serialisierung ins Bild kommen ?. Serialisierung ist mehr oder weniger Dumping das Objekt. Wie viele Referenzen auf das Objekt zeigen, sollte keine Rolle spielen. Recht? – TheLostMind

Verwandte Themen