Obwohl es möglich ist, ein Lambda in Java 8 zu serialisieren , ist es stark davon abgeraten ; selbst die Serialisierung von inneren Klassen wird abgeraten . Der Grund dafür ist, dass Lambdas auf einer anderen JRE nicht richtig deserialisiert werden können. Bedeutet dies jedoch nicht, dass ein Weg ist, ein Lambda sicher zu serialisieren?
Sagen wir zum Beispiel, ich definiere eine Klasse in etwa so:
%Vor%Wenn ich eine Instanz der Klasse so deklariere, sollte ich sie nicht serialisieren:
%Vor%Aber was wäre, wenn ich eine Instanz der Klasse so machen würde:
%Vor% %Vor% Wäre das jetzt sicher zu serialisieren? Mein Instinkt sagt, dass ja, es sollte sicher sein, da es keinen Grund gibt, dass Interfaces in java.util.function
anders als irgendeine andere zufällige Schnittstelle behandelt werden sollte. Aber ich bin immer noch vorsichtig.
Es hängt davon ab, welche Art von Sicherheit Sie wollen. Es ist nicht so, dass serialisierte Lambdas nicht zwischen verschiedenen JREs geteilt werden können. Sie haben eine gut definierte persistente Repräsentation, die SerializedLambda
. Wenn Sie lernen, wie es funktioniert, werden Sie feststellen, dass es auf dem Vorhandensein der definierenden Klasse beruht, die eine spezielle Methode haben wird, die das Lambda rekonstruiert.
Was es unzuverlässig macht, ist die Abhängigkeit von compilerspezifischen Artefakten, z. die synthetische Zielmethode, die einen generierten Namen hat, so einfache Änderungen wie das Einfügen eines anderen Lambda-Ausdrucks oder das Neukompilieren der Klasse mit einem anderen Compiler können die Kompatibilität zu existierenden serialisierten Lambda-Ausdrücken zerstören.
Die Verwendung von manuell geschriebenen Klassen ist jedoch nicht dagegen immun. Ohne eine explizit deklarierte serialVersionUID
berechnet der Standardalgorithmus eine ID durch Hashing-Klassen-Artefakte, einschließlich private
und synthetische Einsen, die eine ähnliche Compiler-Abhängigkeit hinzufügen. Das Minimum, um zuverlässige persistente Formulare zu erhalten, besteht darin, ein explizites serialVersionUID
zu deklarieren.
Oder Sie wenden sich an die robusteste mögliche Form:
%Vor% Beim Serialisieren dieser Konstante werden neben dem Klassennamen (und der Tatsache, dass es sich natürlich um ein enum
handelt) keine Eigenschaften der tatsächlichen Implementierung und ein Verweis auf den Namen der Konstanten gespeichert. Bei der Deserialisierung wird die tatsächliche eindeutige Instanz dieses Namens verwendet.
Beachten Sie, dass serialisierbare Lambda-Ausdrücke Sicherheitsprobleme verursachen können weil sie eine alternative Möglichkeit eröffnen, ein Objekt zu erreichen, das es ermöglicht, die Zielmethoden aufzurufen. Dies gilt jedoch für alle serialisierbaren Klassen, da alle in Ihrer Frage gezeigten Varianten und diese Antwort das gezielte Deserialisieren eines Objekts ermöglichen, das das Aufrufen der gekapselten Operation ermöglicht. Aber bei expliziten serialisierbaren Klassen ist sich der Autor normalerweise dieser Tatsache bewusst.
Tags und Links java java-8 lambda serialization