2014-06-10 51 views
6

如果兩個對象引用指向相同的可序列化的Object,那麼在java中的序列化過程中會發生什麼? 可序列化的對象是否被保存兩次?
例如:如果兩個對象引用指向相同的可序列化對象,那麼在java中的序列化過程中會發生什麼?

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

現在,只有一個對象狀態是否被保存兩個goodKingbadKing refrences或國王對象獲取保存兩次?

+1

您是否嘗試用一個和兩個引用來保存類,並比較結果的文件大小? – Smutje

+1

嘗試反序列化王國,看看goodKing和badKing是否指向同一個國王。如果是的話,那麼在王國有一個國王就足夠使王國反序列化了。由此我們可以猜測只保存一個對象狀態。 – fajarkoe

+0

@Smutje生成的文件總是顯示大小爲1KB –

回答

7

ObjectOutputStream文檔說會發生什麼:

的默認序列化機制爲對象寫入對象的類,類簽名,和所有的非暫時的和非靜態字段的值。對其他對象(除了在瞬態或靜態字段中)的引用也會導致寫入這些對象。 使用引用共享機制對單個對象的多個引用進行編碼,以便可以將對象的圖形恢復到原始寫入時的相同形狀。

(我的重點)

例如,如果你有一個對象的多個引用,當圖被重組,你結束了該對象的一個​​重組版本的多個引用,沒有引用它的多個等價實例。

當然,如果被序列化的容器實現了不同的機制,那麼行爲就是由該機制決定的,而不是默認的機制。

因此,舉例來說,如果我們有ThingTest

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

和運行java Test,我們得到:

t2.mapsAreSameObject? true

...因爲Thing的成員map1map2最終都指向單個HashMap實例。

+0

你的意思是說,無論對單個對象沒有引用,在serualization和序列化期間只保存該對象的一個​​副本,每個對該單個對象的引用將按原始類重新構建。 –

+0

@AmiteshRai:對。或者說,這就是文檔所說的。 :-)再次,這是默認的序列化;如果一個容器實現了自己的序列化,它可以做其他事情(儘管做別的事情會是奇怪而令人驚訝的)。 –

+0

@ T.J.Crowder - 我不太明白..爲什麼在序列化過程中會引用圖片?序列化或多或少地傾倒對象。有多少參考文獻指向該對象應該沒有關係。對? – TheLostMind

相關問題