Java-Serialisierung: readObject() vs. readResolve()

Lesezeit: 6 Minuten

Benutzer-Avatar
Futter

Das Buch Effektives Java und andere Quellen liefern eine ziemlich gute Erklärung, wie und wann man die verwendet readObject() -Methode beim Arbeiten mit serialisierbaren Java-Klassen. Das readResolve() Die Methode hingegen bleibt ein wenig rätselhaft. Grundsätzlich erwähnen alle Dokumente, die ich gefunden habe, entweder nur eines der beiden oder beide nur einzeln.

Unbeantwortete Fragen sind:

  • Was ist der Unterschied zwischen den beiden Methoden?
  • Wann soll welche Methode eingesetzt werden?
  • Wie sollte readResolve() verwendet werden, insbesondere in Bezug auf die Rücksendung, was?

Ich hoffe, Sie können etwas Licht in diese Angelegenheit bringen.

  • Beispiel aus dem JDK von Oracle: String.CaseInsensitiveComparator.readResolve()

    – Kevinarpe

    6. Januar 2018 um 11:26 Uhr


readResolve wird verwendet für ersetzen das aus dem Stream gelesene Objekt. Die einzige Verwendung, die ich je dafür gesehen habe, ist das Erzwingen von Singletons. Wenn ein Objekt gelesen wird, ersetzen Sie es durch die Singleton-Instanz. Dadurch wird sichergestellt, dass niemand durch Serialisieren und Deserialisieren des Singletons eine weitere Instanz erstellen kann.

  • Es gibt eine Reihe von Möglichkeiten für bösartigen Code (oder sogar Daten), um dies zu umgehen.

    – Tom Hawtin – Angelleine

    22. Juli 2009 um 21:33 Uhr

  • Josh Bloch spricht über die Bedingungen, unter denen dies in effektivem Java 2nd ed bricht. Punkt 77. Er erwähnt dies in diesem Vortrag, den er vor einigen Jahren in Google IO gehalten hat (manchmal gegen Ende des Vortrags): youtube.com/watch?v=pi_I7oD_uGI

    – calvinkrishy

    18. September 2010 um 3:26 Uhr


  • Ich finde diese Antwort etwas unzureichend, da sie nicht erwähnt wird transient Felder. readResolve wird verwendet für Lösung das Objekt, nachdem es gelesen wurde. Ein Beispiel für die Verwendung ist vielleicht ein Objekt, das einen Cache enthält, der aus vorhandenen Daten neu erstellt werden kann und nicht serialisiert werden muss; die zwischengespeicherten Daten können deklariert werden transient und readResolve() kann es nach der Deserialisierung neu erstellen. Für solche Dinge ist diese Methode da.

    – Jason C

    6. Mai 2015 um 2:33 Uhr

  • @JasonC dein Kommentar “Solche Dinge [transient handling] sind, was diese Methode ist für” ist irreführend. Siehe das Java-Dokument für Serializable: es heißt “Klassen, die a bezeichnen müssen Ersatz Wenn eine Instanz davon aus dem Stream gelesen wird, sollte dies implementiert werden [readResolve] besondere Methode…”.

    – Opher

    12. Oktober 2016 um 12:30 Uhr

  • Die readResolve-Methode kann auch in einem Eckfall verwendet werden, in dem angenommen wird, dass Sie viele Objekte serialisiert und in der Datenbank gespeichert haben. Wenn Sie diese Daten zu einem späteren Zeitpunkt in ein neues Format migrieren möchten, können Sie dies ganz einfach in der readResolve-Methode erreichen.

    – Nilesh Rajani

    20. Mai 2018 um 12:26 Uhr

Benutzer-Avatar
Tom Hawtin – Tackline

Artikel 90, Effektives Java, 3. Auflage umfasst readResolve und writeReplace für serielle Proxys – ihre Hauptverwendung. Die Beispiele schreiben nicht aus readObject und writeObject Methoden, weil sie die Standard-Serialisierung zum Lesen und Schreiben von Feldern verwenden.

readResolve wird nach gerufen readObject zurückgekehrt ist (umgekehrt writeReplace wird vorher aufgerufen writeObject und wahrscheinlich auf einem anderen Objekt). Das Objekt, das die Methode zurückgibt, ersetzt this Objekt, das an den Benutzer von zurückgegeben wird ObjectInputStream.readObject und alle weiteren Rückverweise auf das Objekt im Stream. Beide readResolve und writeReplace kann Objekte des gleichen oder unterschiedlichen Typs zurückgeben. Das Zurückgeben desselben Typs ist in einigen Fällen nützlich, in denen Felder vorhanden sein müssen final und es ist entweder Abwärtskompatibilität erforderlich oder Werte müssen kopiert und/oder validiert werden.

Gebrauch von readResolve erzwingt die Singleton-Eigenschaft nicht.

Benutzer-Avatar
endlos

readResolve kann verwendet werden, um die Daten zu ändern, die durch die readObject-Methode serialisiert werden. Beispielsweise verwendet die xstream-API diese Funktion, um einige Attribute zu initialisieren, die nicht im zu deserialisierenden XML enthalten waren.

http://x-stream.github.io/faq.html#Serialisierung

  • XML und Xstream sind für eine Frage zur Java-Serialisierung nicht relevant, und die Frage wurde vor Jahren richtig beantwortet. -1

    – Benutzer207421

    5. Mai 2013 um 0:45 Uhr


  • Die akzeptierte Antwort besagt, dass readResolve verwendet wird, um ein Objekt zu ersetzen. Diese Antwort enthält die nützlichen zusätzlichen Informationen, die zum Ändern eines Objekts während der Deserialisierung verwendet werden können. XStream wurde als Beispiel angegeben, nicht als die einzig mögliche Bibliothek, in der das passiert.

    – Verdrahtet

    26. Februar 2014 um 1:00 Uhr

Benutzer-Avatar
Arjun Kumar

readObject() ist eine bestehende Methode in ObjectInputStream Klasse. Zum Zeitpunkt der Deserialisierung readObject() -Methode überprüft intern, ob das Objekt, das deserialisiert wird, dies hat readResolve() Methode implementiert. Wenn readResolve() -Methode existiert, wird sie aufgerufen

Eine Probe readResolve() Die Umsetzung sähe so aus

protected Object readResolve() {
  return INSTANCE:
}

Also die Absicht des Schreibens readResolve() -Methode soll sicherstellen, dass dasselbe Objekt zurückgegeben wird, das in JVM vorhanden ist, anstatt während der Deserialisierung ein neues Objekt zu erstellen.

readResolve ist für den Fall, dass Sie möglicherweise ein vorhandenes Objekt zurückgeben müssen, z. B. weil Sie nach doppelten Eingaben suchen, die zusammengeführt werden sollten, oder (z. B. in schließlich konsistenten verteilten Systemen), weil es sich um eine Aktualisierung handelt, die eintreffen kann, bevor Sie sich dessen bewusst sind alle älteren Versionen.

  • readResolve() war mir klar, aber ich habe immer noch einige unerklärliche Fragen im Kopf, aber Ihre Antwort hat gerade meine Gedanken gelesen, danke

    – Rajni Gangwar

    20. November 2017 um 17:31 Uhr

Benutzer-Avatar
Gemeinschaft

readResolve() stellt den Singleton-Vertrag während der Serialisierung sicher.
Bitte verweisen

  • readResolve() war mir klar, aber ich habe immer noch einige unerklärliche Fragen im Kopf, aber Ihre Antwort hat gerade meine Gedanken gelesen, danke

    – Rajni Gangwar

    20. November 2017 um 17:31 Uhr

Benutzer-Avatar
Omkar Shetkar

Wie bereits beantwortet, readResolve ist eine private Methode, die in ObjectInputStream beim Deserialisieren eines Objekts verwendet wird. Dies wird aufgerufen, kurz bevor die tatsächliche Instanz zurückgegeben wird. Im Falle von Singleton können wir hier die Rückgabe einer bereits vorhandenen Singleton-Instanzreferenz anstelle einer deserialisierten Instanzreferenz erzwingen. Ähnlich haben wir writeReplace für ObjectOutputStream.

Beispiel für readResolve:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class SingletonWithSerializable implements Serializable {
private static final long serialVersionUID = 1L;

public static final SingletonWithSerializable INSTANCE = new SingletonWithSerializable();

private SingletonWithSerializable() {
    if (INSTANCE != null)
        throw new RuntimeException("Singleton instance already exists!");
}

private Object readResolve() {
    return INSTANCE;
}

public void leaveTheBuilding() {
    System.out.println("SingletonWithPublicFinalField.leaveTheBuilding() called...");
}

public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
    SingletonWithSerializable instance = SingletonWithSerializable.INSTANCE;

    System.out.println("Before serialization: " + instance);

    try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file1.ser"))) {
        out.writeObject(instance);
    }

    try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("file1.ser"))) {
        SingletonWithSerializable readObject = (SingletonWithSerializable) in.readObject();
        System.out.println("After deserialization: " + readObject);
    }

}

}

Ausgabe:

Before serialization: com.ej.item3.SingletonWithSerializable@7852e922
After deserialization: com.ej.item3.SingletonWithSerializable@7852e922

1338550cookie-checkJava-Serialisierung: readObject() vs. readResolve()

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy