Hintergrund:
Java unterstützt von Anfang an den Mechanismus der Serialisierung von Objekten über das Interface Serializable. Manchmal ist es notwendig, den Zustand eines Objekts zu speichern, aber nicht alle Felder sollten serialisiert werden – zum Beispiel könnten sie sicherheitsrelevant sein oder dynamisch berechnet werden. Für solche Fälle wurde der Modifikator transient erfunden.
Problem:
Wenn man ein Objekt vollständig serialisiert, ohne die Besonderheiten einzelner Felder zu berücksichtigen, kann es zu einer Offenlegung privater oder nicht serialisierbarer Daten kommen. Darüber hinaus kann die Serialisierung und Deserialisierung großer oder temporärer Felder (zum Beispiel von Streams, Verbindungen zur Datenbank) zu Fehlern oder einer Verschlechterung der Leistung führen.
Lösung:
Verwenden Sie den Modifikator transient für Felder, die beim Speichern des Objekts nicht serialisiert werden sollen. Solche Felder werden von dem Serialisierungsmechanismus einfach ignoriert, und bei der Deserialisierung erhalten sie Standardwerte (zum Beispiel null für Referenztypen oder 0 für Zahlen).
Beispielcode:
import java.io.*; class User implements Serializable { private String username; private transient String password; // Wird nicht serialisiert! public User(String username, String password) { this.username = username; this.password = password; } }
Wesentliche Merkmale:
Kann ein statisches Feld transient sein?
Antwort: Man kann ein Feld als static transient deklarieren, aber es macht keinen Sinn: Statische Felder werden ohnehin nicht serialisiert, da sie der Klasse und nicht dem Objekt angehören.
Kann man vollständige Kontrolle über die Serialisierung von transient-Feldern haben?
Antwort: Ja, indem man die Methoden private void writeObject(ObjectOutputStream out) und private void readObject(ObjectInputStream in) implementiert, kann man bei Bedarf sogar transient Felder selbst serialisieren.
Beispielcode:
private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); // out.writeObject(password); // falls es notwendig ist, das transient-Feld explizit zu serialisieren }
Was passiert mit einem final transient Feld nach der Deserialisierung?
Antwort: final transient-Felder erhalten ebenfalls Standardwerte (in der Regel null oder null), aber danach können sie ohne spezielle Tricks nicht mehr geändert werden, was oft zu Bugs führt.
Ein Objekt mit dem transient-Feld DatabaseConnection wurde serialisiert. Nach der Deserialisierung versuchten wir, Methoden dieser Verbindung aufzurufen – wir erhielten eine NullPointerException.
Vorteile:
Nachteile:
Ein Benutzerobjekt mit transient-Passwort wurde serialisiert, bei der Deserialisierung haben wir in readObject das Passwort vom Benutzer angefordert oder die Verbindung wiederhergestellt.
Vorteile:
Nachteile: