Wir arbeiten intensiv mit der Serialisierung und die Angabe eines serialisierbaren Tags für jedes von uns verwendete Objekt ist eine Art Belastung. Besonders wenn es sich um eine Klasse von Drittanbietern handelt, die wir nicht wirklich ändern können.
Die Frage ist: Da Serializable eine leere Schnittstelle ist und Java nach dem Hinzufügen eine robuste Serialisierung bietet implements Serializable
- warum haben sie nicht alles serialisierbar gemacht und das war's?
Was vermisse ich?
java
serialization
Yoni Roit
quelle
quelle
Antworten:
Die Serialisierung ist mit Fallstricken behaftet. Automatische Serialisierung Unterstützung dieser Form macht die Klasse Interna Teil der öffentlichen API (weshalb javadoc Sie gibt beharrte Formen der Klassen ).
Für eine langfristige Persistenz muss die Klasse in der Lage sein, dieses Formular zu dekodieren, wodurch die Änderungen, die Sie am Klassendesign vornehmen können, eingeschränkt werden. Dies unterbricht die Kapselung.
Die Serialisierung kann auch zu Sicherheitsproblemen führen. Durch die Serialisierung eines Objekts, auf das verwiesen wird, kann eine Klasse auf Daten zugreifen, auf die sie normalerweise nicht zugreifen kann (durch Parsen der resultierenden Byte-Daten).
Es gibt andere Probleme, wie zum Beispiel, dass die serialisierte Form der inneren Klassen nicht genau definiert ist.
Die Serialisierbarkeit aller Klassen würde diese Probleme verschlimmern. Schauen Sie sich Effective Java Second Edition an , insbesondere Punkt 74: Serializable mit Bedacht implementieren .
quelle
Ich denke, sowohl Java- als auch .NET-Leute haben diesmal etwas falsch gemacht. Es wäre besser gewesen, alles standardmäßig serialisierbar zu machen und nur die Klassen zu markieren, die stattdessen nicht sicher serialisiert werden können.
In Smalltalk (einer Sprache, die in den 70er Jahren erstellt wurde) ist beispielsweise jedes Objekt standardmäßig serialisierbar. Ich habe keine Ahnung, warum dies in Java nicht der Fall ist, wenn man bedenkt, dass die überwiegende Mehrheit der Objekte sicher serialisiert werden kann und nur einige von ihnen nicht.
Das Markieren eines Objekts als serialisierbar (mit einer Schnittstelle) macht dieses Objekt nicht auf magische Weise serialisierbar, es war die ganze Zeit serialisierbar . Es ist nur so, dass Sie jetzt etwas ausgedrückt haben, das das System selbst hätte finden können, also sehe ich keinen wirklich guten Grund dafür Serialisierung ist so wie sie jetzt ist.
Ich denke, es war entweder eine schlechte Entscheidung der Designer oder die Serialisierung war ein nachträglicher Gedanke, oder die Plattform war nie bereit, standardmäßig alle Objekte sicher und konsistent zu serialisieren.
quelle
Serializable
Trick ist nur eine weitere falsche Entscheidung, die vor ein oder zwei Jahrzehnten getroffen wurde, und eine weitere Ergänzung zum Ärger beim Umgang mit reinem Java, wie einige Fehler bei der Sammlung und Zeichenfolgenverarbeitung in der Standardbibliothek. Glücklicherweise gibt es Kryo, aber es ist Abhängigkeit und man muss es zuerst finden. So hätte die eingebaute Serialisierung erfolgen sollen.Nicht alles ist wirklich serialisierbar. Nehmen Sie zum Beispiel eine Netzwerk-Socket-Verbindung. Sie könnten die Daten / den Status Ihres Socket-Objekts serialisieren, aber das Wesentliche einer aktiven Verbindung würde verloren gehen.
quelle
implements NotSerializable
:)Die Hauptaufgabe von Serializable in Java besteht darin, alle anderen Objekte standardmäßig nicht serialisierbar zu machen. Die Serialisierung ist ein sehr gefährlicher Mechanismus, insbesondere in der Standardimplementierung. Daher ist es wie die Freundschaft in C ++ standardmäßig deaktiviert, auch wenn es ein wenig kostet, Dinge serialisierbar zu machen.
Durch die Serialisierung werden Einschränkungen und potenzielle Probleme hinzugefügt, da die Strukturkompatibilität nicht gewährleistet ist. Es ist gut, dass es standardmäßig deaktiviert ist.
Ich muss zugeben, dass ich nur sehr wenige nichttriviale Klassen gesehen habe, in denen die Standardserialisierung das tut, was ich will. Insbesondere bei komplexen Datenstrukturen. Der Aufwand für die ordnungsgemäße Serialisierung der Klasse erhöht also die Kosten für das Hinzufügen der Schnittstelle.
quelle
Für einige Klassen, insbesondere für Klassen, die etwas Physikalischeres wie eine Datei, einen Socket, einen Thread oder eine DB-Verbindung darstellen, ist es absolut sinnlos, Instanzen zu serialisieren. Für viele andere kann die Serialisierung problematisch sein, da sie die Eindeutigkeitsbeschränkungen aufhebt oder Sie einfach dazu zwingt, sich mit Instanzen verschiedener Versionen einer Klasse zu befassen, die Sie möglicherweise nicht möchten.
Möglicherweise war es besser, alles standardmäßig serialisierbar zu machen und Klassen über ein Schlüsselwort oder eine Markierungsschnittstelle nicht serialisierbar zu machen - aber diejenigen, die diese Option verwenden sollten, würden wahrscheinlich nicht darüber nachdenken. So wie es ist, wenn Sie Serializable implementieren müssen, wird Ihnen dies durch eine Ausnahme mitgeteilt.
quelle
Ich denke, das war, um sicherzustellen, dass Sie als Programmierer wissen, dass Ihr Objekt serialisiert werden kann.
quelle
Anscheinend war in einigen vorläufigen Entwürfen alles serialisierbar, aber aus Sicherheits- und Korrektheitsgründen endete das endgültige Design, wie wir alle wissen.
Quelle: Warum müssen Klassen Serializable implementieren, um in einen ObjectOutputStream geschrieben zu werden? .
quelle
Wenn Sie explizit angeben müssen, dass Instanzen einer bestimmten Klasse serialisierbar sind, müssen Sie darüber nachdenken, ob Sie dies zulassen sollten. Für einfache Wertobjekte ist die Serialisierung trivial, aber in komplexeren Fällen müssen Sie die Dinge wirklich durchdenken.
Indem Sie sich nur auf die Standard-Serialisierungsunterstützung der JVM verlassen, setzen Sie sich allen möglichen bösen Versionsproblemen aus.
Einzigartigkeit, Verweise auf "echte" Ressourcen, Timer und viele andere Arten von Artefakten sind KEINE Kandidaten für die Serialisierung.
quelle
Lesen Sie dies, um die Serializable-Schnittstelle zu verstehen und zu verstehen, warum wir nur wenige Klassen serialisierbar machen sollten. Außerdem sollten wir darauf achten, wo das vorübergehende Schlüsselwort verwendet wird, falls wir nur wenige Felder aus dem Speichervorgang entfernen möchten.
http://www.codingeek.com/java/io/object-streams-serialization-deserialization-java-example-serializable-interface/
quelle
Nun, meine Antwort ist, dass dies keinen guten Grund hat. Und aus Ihren Kommentaren kann ich ersehen, dass Sie das bereits gelernt haben. Andere Sprachen versuchen gerne, alles zu serialisieren, was nicht auf einen Baum springt, nachdem Sie bis 10 gezählt haben. Ein Objekt sollte standardmäßig serialisierbar sein.
Sie müssen also grundsätzlich alle Eigenschaften Ihrer Drittanbieter-Klasse selbst lesen. Oder, wenn dies eine Option für Sie ist: dekompilieren, das verdammte Schlüsselwort dort einfügen und neu kompilieren.
quelle
Es gibt einige Dinge in Java, die einfach nicht serialisiert werden können, weil sie laufzeitspezifisch sind. Dinge wie Streams, Threads, Laufzeit usw. und sogar einige GUI-Klassen (die mit dem zugrunde liegenden Betriebssystem verbunden sind) können nicht serialisiert werden.
quelle
Obwohl ich den Punkten in anderen Antworten hier zustimme, besteht das eigentliche Problem in der Deserialisierung: Wenn sich die Klassendefinition ändert, besteht ein echtes Risiko, dass die Deserialisierung nicht funktioniert. Niemals vorhandene Felder zu ändern, ist für den Autor einer Bibliothek eine ziemlich große Verpflichtung! Die Aufrechterhaltung der API-Kompatibilität ist eine mühsame Aufgabe.
quelle
Eine Klasse, die für eine Datei oder ein anderes Medium beibehalten werden muss, muss eine serialisierbare Schnittstelle implementieren, damit JVM die Serialisierung des Klassenobjekts ermöglichen kann. Warum die Objektklasse nicht serialisiert wird, muss keine der Klassen die Schnittstelle implementieren, schließlich serialisiert JVM die Klasse nur, wenn ich ObjectOutputStream verwende bedeutet, dass das Steuerelement immer noch in meinen Händen liegt, damit die JVM serialisiert werden kann.
Der Grund, warum die Objektklasse standardmäßig nicht serialisierbar ist, liegt darin, dass die Klassenversion das Hauptproblem darstellt. Daher muss jede Klasse, die an Serialisierung interessiert ist, explizit als serialisierbar markiert werden und eine Versionsnummer serialVersionUID angeben.
Wenn serialVersionUID nicht angegeben wird, erhalten wir beim Deserialisieren des Objekts unerwartete Ergebnisse. Aus diesem Grund löst JVM InvalidClassException aus, wenn serialVersionUID nicht übereinstimmt. Daher muss jede Klasse eine serialisierbare Schnittstelle implementieren und eine serialVersionUID bereitstellen , um sicherzustellen, dass die an beiden Enden dargestellte Klasse identisch ist.
quelle