2016-09-26 48 views

回答

4

當您使用ObjectOutputStream序列化對象時,流將'記住'它已寫入的對象。當它必須再次寫入相同的對象時,它不會再寫入整個對象,而是寫入一個稱爲「後退引用」的標識符。

接收方ObjectInputStream也將跟蹤接收到的對象,並在讀取後退引用時返回它先前讀取的同一對象。

如在answer by CoronA中所述,這是用於序列化彼此指向的對象,還用於確保在序列化到另一個JVM時保留一個JVM中的身份相等性。

方法readUnshared(及其計數器部分writeUnshared)用於擺脫此行爲:它確保讀取(寫入)的對象將是唯一的(並且不會作爲反向引用重用)。這是相當先進的,我不記得曾經見過或曾經使用它,但是再次,我很少看到序列化的用法。

3

考慮:

class A { 
    B b; 
} 

class B { 
    String s; 
    A a; 
} 

及以下建築:

A a = new A(); 
a.b = new B(); 
b.a = a; 

如果這樣的遞歸結構是序列化和反序列化應該是功能上是相同的。 b.a不應該是A的任意實例,而應該是引用b的那個實例。

在這種情況下,b.a是反向引用,因爲A會在ObjectInputStream的B之前被讀取。

+0

這不是什麼回參考指的。它與循環引用無關,儘管它們將大大受益於後向引用。 – 4castle

+0

使用'writeUnshared'序列化一個像這樣的循環結構會拋出一個'StackOverflowException'。 – 4castle

+1

從我的角度來看,有幾種情況需要反向引用。循環引用是其中的一部分。是的 - writeUnshared可能會失敗,但在我寫這個答案的時候,沒有人提到readUnshared。 – CoronA

1

反向引用是對先前已寫入/讀取到流中的同一對象的引用。把它想象成一個指向流中前一個對象的指針。

反向引用很有用,因爲如果它在同一個流中被多次(反)序列化,並且在反序列化時還允許引用相等,它們將極大地減少對象的佔用空間。

使用反向引用:

Object obj = new Object(); 
obj == obj // true 
writeObject(obj); 
writeObject(obj); 
Object obj1 = readObject(); 
Object obj2 = readObject(); 
obj1 == obj2 // true 

如果我們不使用反向引用,最後的聲明將是false