2016-09-26 2 views
6

Speziell im Zusammenhang mit readUnshared() Methode von ObjectInputStream, Was bedeutet eine "Zurück-Referenz"?Was ist eine Rückwärtsreferenz in Java?

I kam über den Begriff in diesem

Wenn readUnshared ein Rückverweis deserialisieren genannt wird (der Strom Darstellung eines Objekts, das auf den Strom zuvor geschrieben wurde), wird ein ObjectStreamException sein geworfen.

Ref: https://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html#readUnshared()

Antwort

4

Wenn Sie Objekte mit einer ObjectOutputStream serialisieren, "erinnert" sich der Stream daran, welche Objekte er bereits geschrieben hat. Wenn das gleiche Objekt erneut geschrieben werden muss, wird das gesamte Objekt nicht erneut geschrieben, stattdessen wird eine Kennung geschrieben, die als "Rückverweis" bezeichnet wird.

Das empfangende ObjectInputStream wird auch verfolgen, welche Objekte empfangen wurden, und wird - beim Lesen einer Rückverweisliste - das gleiche Objekt zurückgeben, das es zuvor gelesen hat. Wie in der answer by CoronA10 erläutert, wird dies - unter anderem - zum Serialisieren von Objekten verwendet, die zueinander zeigen, aber auch um sicherzustellen, dass die Identitätsgleichheit in einer JVM bei der Serialisierung zu einer anderen JVM erhalten bleibt.

Verfahren readUnshared (und sein Gegenstück writeUnshared) verwendet werden, von diesem Verhalten zu lösen: Es stellt sicher, dass das Objekt lesen (geschrieben) eindeutig sein wird (und nicht als Rückverweis wiederverwendet). Das ist ziemlich weit fortgeschritten und ich kann mich nicht erinnern, es jemals gesehen oder benutzt zu haben, aber andererseits sehe ich selten die Verwendung von Serialisierung überhaupt.

3

Bedenken Sie:

class A { 
    B b; 
} 

class B { 
    String s; 
    A a; 
} 

und folgenden Aufbau:

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

Wenn eine solche rekursive Struktur serialisiert und deserialisiert sollte es funktionell gleich sein. b.a sollte nicht eine beliebige Instanz von A sein, sondern genau diejenige, die auf b verweist.

In diesem Fall ist b.a die Rückreferenz, da A vor B im ObjectInputStream gelesen werden würde.

+0

Darauf bezieht sich eine Rückverweisung nicht.Es hat nichts mit Zirkelverweisen zu tun, obwohl sie sehr von Rückreferenzen profitieren würden. – 4castle

+0

Das Serialisieren einer kreisförmigen Struktur wie dem mit 'writeUnshared' würde eine' StackOverflowException' auslösen. – 4castle

+1

Aus meiner Sicht gibt es mehrere Szenarien, in denen Rückreferenzen benötigt werden. Und Zirkelverweise sind ein Teil von ihnen. Ja - writeUnshared wird wahrscheinlich fehlschlagen, aber zu der Zeit, als ich diese Antwort schrieb, erwähnte niemand readUnshared. – CoronA

1

Eine Rückreferenz ist eine Referenz auf ein identisches Objekt, das bereits zuvor in den Stream geschrieben/gelesen wurde. Stellen Sie sich das wie einen Zeiger auf ein vorheriges Objekt im Stream vor.

Rückverweise sind nützlich, da sie den Footprint des Objekts stark reduzieren, wenn es mehrmals im selben Stream (de) serialisiert wird, und auch eine Referenzgleichheit beim Deserialisieren ermöglicht.

Mit Rückverweise:

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

Wenn wir nicht wieder Verweise verwendet wurden, würde die Endabrechnung false sein.