Warum braucht Java eine serialisierbare Schnittstelle?
Lesezeit: 8 Minuten
Yoni Roit
Wir arbeiten intensiv mit der Serialisierung, und es ist eine Art Belastung, das Serializable-Tag für jedes von uns verwendete Objekt angeben zu müssen. Vor allem, 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?
Was ist, wenn Sie Ihr eigenes Objekt serialisierbar machen möchten? Oder habe ich etwas falsch verstanden?
– Joe Phillips
13. Januar 09 um 22:57 Uhr
Ich bekomme immer noch NotSerializableException, weil alle Felder meiner Objekte serialisierbar sein müssen
– Yoni Roit
13. Januar 09 um 23:01 Uhr
Stimme Pop Catalin und Dmitry voll und ganz zu: „Dieser serialisierbare Trick ist nur eine weitere falsche Entscheidung, die vor ein oder zwei Jahrzehnten getroffen wurde“. Es spielt keine Rolle, wie gefährlich die Serialisierung sein kann. Und es ist nicht wahr, dass, da die Deklaration explizit ist, „Sie wissen, dass Sie besonders aufpassen müssen“: Jeder, der es braucht, setzt zuerst „implementiert“ Sachen und denkt dann über die Auswirkungen nach, wenn etwas schief gelaufen ist. Es hätte alles klarer sein können, wenn sie uns eine “Unserialisierbare” Schnittstelle gegeben hätten, die auf spezielle Fälle angewendet werden kann.
– Jack
16. Januar 17 um 14:41 Uhr
Die Serialisierung ist mit Fallstricken behaftet. Die automatische Serialisierungsunterstützung dieses Formulars macht die Interna der Klasse zu einem Teil der öffentlichen API (weshalb javadoc Ihnen die anhaltende Unterrichtsformen).
Für eine langfristige Persistenz muss die Klasse in der Lage sein, dieses Formular zu decodieren, was die Änderungen, die Sie am Klassendesign vornehmen können, einschränkt. Dies bricht die Kapselung.
Die Serialisierung kann auch zu Sicherheitsproblemen führen. Indem sie jedes Objekt, auf das sie verweist, serialisieren kann, kann eine Klasse auf Daten zugreifen, zu denen sie normalerweise nicht in der Lage wäre (durch Analysieren der resultierenden Bytedaten).
Es gibt andere Probleme, wie zum Beispiel die serialisierte Form innerer Klassen, die nicht gut definiert sind.
Alle Klassen serialisierbar zu machen, würde diese Probleme verschärfen. Kasse Effektive zweite Ausgabe von Javainsbesondere Punkt 74: Implementieren Sie Serializable mit Bedacht.
Dies ist eindeutig die bessere Antwort. Ich bin enttäuscht, dass die ausgewählte Antwort dies nicht ist. Es scheint, als hätte der Posting die Agenda “Ich bin verärgert, weil ich Dinge für serialisierbar erklären muss” im Hinterkopf gewählt. Es ist ein Beispiel dafür, dass jemand Rad freigeben und die Sicherheits- und Design-Lektionen nicht beachten möchte, die bereits in der Vergangenheit gelernt wurden.
– gbtimmon
9. Juli 12 um 17:30 Uhr
@McDowell was meinst du mit persistenter Form von Klassen? Ich bin diesem Link gefolgt, verstehe aber nicht, was du meinst? kannst du das bitte erklären?
– Aussenseiter
22. August 12 um 7:36 Uhr
@Geek – Die serialisierte Form des URL-Typs (zum Beispiel) definiert, welche privaten Felder der Typ haben muss und in welcher Reihenfolge sie deklariert werden müssen.
– McDowell
22. August 2012 um 08:05 Uhr
@McDowell Warum spielt die Reihenfolge eine Rolle?
– Aussenseiter
22. August 2012 um 08:15 Uhr
@McDowell Hallo. Ich bin der ursprüngliche Verfasser dieser Frage vor 4 Jahren und habe Ihre Antwort gerade als akzeptiert ausgewählt, wenn sie etwas bedeutet. Ich denke, Ihre Antwort ist wirklich die bessere, und ich war damals wahrscheinlich zu unreif, um das so zu sehen. Jetzt reparieren 🙂
– Yoni Roit
6. März 13 um 19:55 Uhr
Ich denke, sowohl Java- als auch .Net-Leute haben es diesmal falsch gemacht, es wäre besser gewesen, alles standardmäßig serialisierbar zu machen und stattdessen nur die Klassen zu markieren, die nicht sicher serialisiert werden können.
Zum Beispiel ist in Smalltalk (einer Sprache, die in den 70er Jahren entwickelt wurde) 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 wenige davon nicht.
Das Markieren eines Objekts als serialisierbar (mit einer Schnittstelle) macht dieses Objekt nicht auf magische Weise serialisierbar. es war die ganze Zeit serialisierbares 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, dass die Serialisierung so ist, wie sie jetzt ist.
Ich denke, es war entweder eine schlechte Entscheidung der Designer oder die Serialisierung war ein nachträglicher Einfall, oder die Plattform war nie bereit, die Serialisierung standardmäßig für alle Objekte sicher und konsistent durchzuführen.
Beim Entwerfen und Implementieren einer Klasse müssen Sie besonders darauf achten, dass Instanzen auf vernünftige Weise serialisiert werden. Die serialisierbare Schnittstelle bedeutet eigentlich: “Ich als Programmierer habe die Konsequenzen der Serialisierung verstanden und erlaube der JVM, dies zu serialisieren”
– Rolf Rander
14. Januar 09 um 12:11 Uhr
@Rolf Rander: Meistens brauchen Sie sich überhaupt nicht darum zu kümmern, markieren Sie einfach die Klasse serialisierbar. Wenn die Serialisierung standardmäßig für alle Objekte aktiviert gewesen wäre, wäre die Denkweise jedes Entwicklers auch anders gewesen, es wäre etwas Natürliches gewesen, eine Klasse serialisierbar zu machen …
– Pop Katalin
14. Januar 09 um 12:51 Uhr
Es hätte der Liste guter Klassendesigns ein weiteres Anliegen hinzugefügt, wie zum Beispiel sicherzustellen, dass Sie keine Speicherlecks haben. Dennoch erfordert ein gutes Klassendesign immer mehr, dass Ihre Klassen serialisierbar sind, wenn dies möglich ist.
– Pop Katalin
14. Januar 09 um 14:52 Uhr
@StaxMan, weil es sehr kostspielig sein kann, später zu erkennen, dass Sie eine Klasse serialisieren müssen und dies nicht können. Es ist einer der Fälle, in denen sich ein geringer zusätzlicher Aufwand auszahlt. Dies gilt insbesondere, wenn Sie eine Bibliothek schreiben und jemand anderes sie ohne den Quellcode verwenden wird
– Pop Katalin
1. September 2009 um 19:37 Uhr
Ich stimme dieser Antwort vollkommen zu. In vielen Sprachen ist standardmäßig alles serialisierbar. Und eigentlich das gleiche mit JVM, weil es einfach ist, Reflection zu verwenden, um auf jedes Klassenmitglied zuzugreifen, egal ob es privat ist oder nicht. Dies Serializable Trick ist nur eine weitere falsche Entscheidung, die vor ein oder zwei Jahrzehnten getroffen wurde, und eine weitere Ergänzung des Ärgers beim Umgang mit reinem Java, wie einige Fehler bei der Erfassung und Verarbeitung von Zeichenfolgen in der Standardbibliothek. Glücklicherweise gibt es Kryo, aber es ist eine Abhängigkeit und man muss es zuerst finden. So hätte die eingebaute Serialisierung erfolgen sollen.
– Dmitri
7. August 14 um 20:08 Uhr
Nicht alles ist wirklich serialisierbar. Nehmen Sie zum Beispiel eine Netzwerk-Socket-Verbindung. Sie könnten die Daten/den Zustand Ihres Socket-Objekts serialisieren, aber die Essenz einer aktiven Verbindung würde verloren gehen.
Dies wäre mein Problem, und wenn ich nicht schlau genug wäre, um zu versuchen, Socket zu serialisieren, würde ich meinen Fehler während des Debuggens finden. Jetzt bin ich jedoch in einer Situation, in der ich die Java-Serialisierung überhaupt nicht verwenden kann, weil die Klasse eines Drittanbieters Serializable ohne guten Grund nicht implementiert.
– Yoni Roit
13. Januar 09 um 23:05 Uhr
Es gibt ein paar anständige Möglichkeiten, diesen Fall zu handhaben, z. B. das Schreiben einer serialisierbaren Wrapper-Klasse, die weiß, wie die Schlüsseldaten der Drittanbieterklasse gelesen und geschrieben werden. Machen Sie die umschlossene Instanz transient und überschreiben Sie writeObject und readObject.
– Greg-Fall
13. Januar 09 um 23:56 Uhr
Können Sie von den erforderlichen Objekten in Ihrer API erben und diese Klassen serialisieren?
– Joel Coehoorn
14. Januar 09 um 0:31 Uhr
@Joel: Es ist eine gute Idee, aber immer noch ein Hack. Ich denke, diese ganze Sache ist nur ein weiterer Kompromiss, der schief gelaufen ist. Danke für deine Kommentare.
– Yoni Roit
14. Januar 09 um 10:35 Uhr
Dies ist eines dieser seltenen Beispiele, die zeigen, dass alles, was wir wirklich brauchen, ist implements NotSerializable 🙂
– Rob Grant
27. November 13 um 17:08 Uhr
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 seiner Standardimplementierung. Daher ist es wie Freundschaft in C++ standardmäßig deaktiviert, auch wenn es etwas kostet, Dinge serialisierbar zu machen.
Die Serialisierung fügt Einschränkungen und potenzielle Probleme hinzu, 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 nicht triviale Klassen gesehen habe, bei denen die Standard-Serialisierung das tut, was ich will. Insbesondere bei komplexen Datenstrukturen. Der Aufwand, den Sie aufwenden würden, um die Klasse ordnungsgemäß serialisierbar zu machen, stellt die Kosten für das Hinzufügen der Schnittstelle in den Schatten.
Für einige Klassen, insbesondere solche, die etwas Physischeres wie eine Datei, einen Socket, einen Thread oder eine DB-Verbindung darstellen, macht es absolut keinen Sinn, Instanzen zu serialisieren. Für viele andere kann die Serialisierung problematisch sein, weil sie Eindeutigkeitseinschränkungen zerstört oder Sie einfach dazu zwingt, sich mit Instanzen verschiedener Versionen einer Klasse zu befassen, was Sie möglicherweise nicht möchten.
Es wäre wohl besser gewesen, alles standardmäßig serialisierbar zu machen und Klassen über eine Schlüsselwort- oder 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.
Milhous
Ich denke, das war, um sicherzustellen, dass Sie als Programmierer wissen, dass Ihr Objekt serialisiert werden kann.
cic
Anscheinend war in einigen Vorentwürfen alles serialisierbar, aber aus Sicherheits- und Korrektheitsbedenken endete das endgültige Design, wie wir alle wissen.
Was ist, wenn Sie Ihr eigenes Objekt serialisierbar machen möchten? Oder habe ich etwas falsch verstanden?
– Joe Phillips
13. Januar 09 um 22:57 Uhr
Ich bekomme immer noch NotSerializableException, weil alle Felder meiner Objekte serialisierbar sein müssen
– Yoni Roit
13. Januar 09 um 23:01 Uhr
Stimme Pop Catalin und Dmitry voll und ganz zu: „Dieser serialisierbare Trick ist nur eine weitere falsche Entscheidung, die vor ein oder zwei Jahrzehnten getroffen wurde“. Es spielt keine Rolle, wie gefährlich die Serialisierung sein kann. Und es ist nicht wahr, dass, da die Deklaration explizit ist, „Sie wissen, dass Sie besonders aufpassen müssen“: Jeder, der es braucht, setzt zuerst „implementiert“ Sachen und denkt dann über die Auswirkungen nach, wenn etwas schief gelaufen ist. Es hätte alles klarer sein können, wenn sie uns eine “Unserialisierbare” Schnittstelle gegeben hätten, die auf spezielle Fälle angewendet werden kann.
– Jack
16. Januar 17 um 14:41 Uhr