Ciężko pracujemy nad serializacją i konieczność określenia znacznika Serializable na każdym używanym przez nas obiekcie jest pewnym obciążeniem. Zwłaszcza, gdy jest to klasa zewnętrzna, której tak naprawdę nie możemy zmienić.
Pytanie brzmi: ponieważ Serializable jest pustym interfejsem, a Java zapewnia solidną serializację po dodaniu implements Serializable
- dlaczego nie uczyniły wszystkiego możliwym do serializacji i to wszystko?
czego mi brakuje?
java
serialization
Yoni Roit
źródło
źródło
Odpowiedzi:
Serializacja jest pełna pułapek. Obsługa automatycznej serializacji tego formularza sprawia, że elementy wewnętrzne klasy są częścią publicznego interfejsu API (dlatego javadoc udostępnia utrwalone formy klas ).
Aby zapewnić długotrwałą trwałość, klasa musi mieć możliwość dekodowania tego formularza, co ogranicza zmiany, które można wprowadzić w projekcie klasy. To przerywa hermetyzację.
Serializacja może również prowadzić do problemów z bezpieczeństwem. Dzięki możliwości serializacji dowolnego obiektu, do którego się odwołuje, klasa może uzyskać dostęp do danych, do których normalnie nie byłaby w stanie (poprzez analizę wynikowych danych bajtowych).
Istnieją inne problemy, takie jak serializowana forma klas wewnętrznych, która nie jest dobrze zdefiniowana.
Umożliwienie serializacji wszystkich klas zaostrzyłoby te problemy. Sprawdź Effective Java Second Edition , w szczególności Item 74: Implement Serializable rozsądnie .
źródło
Myślę, że tym razem zarówno Java, jak i .Net pomyliły się, lepiej byłoby uczynić wszystko domyślnie możliwym do serializacji i zamiast tego wystarczy zaznaczyć te klasy, których nie można bezpiecznie serializować.
Na przykład w Smalltalk (języku stworzonym w latach 70.) każdy obiekt jest domyślnie możliwy do serializacji. Nie mam pojęcia, dlaczego tak nie jest w Javie, biorąc pod uwagę fakt, że zdecydowana większość obiektów można bezpiecznie serializować, a tylko kilka z nich nie.
Oznaczenie obiektu jako możliwego do serializacji (za pomocą interfejsu) nie czyni tego obiektu w magiczny sposób możliwym do serializacji, był on możliwy do serializacji przez cały czas , po prostu teraz wyraziłeś coś, co system mógłby znaleźć samodzielnie, więc nie widzę żadnego dobrego powodu, aby serializacja jest taka, jaka jest teraz.
Myślę, że była to zła decyzja podjęta przez projektantów, albo serializacja była po namyśle, albo platforma nigdy nie była gotowa do domyślnej serializacji wszystkich obiektów w sposób bezpieczny i spójny.
źródło
Serializable
sztuczka to po prostu kolejna zła decyzja podjęta dekadę lub dwie temu i jeszcze jeden dodatek do irytacji podczas pracy z czystą Javą, jak niektóre błędy w zbieraniu i przetwarzaniu ciągów w standardowej bibliotece. Na szczęście istnieje Kryo, ale jest to zależność i trzeba ją najpierw znaleźć. W ten sposób powinna zostać wykonana wbudowana serializacja.Nie wszystko jest rzeczywiście możliwe do serializacji. Weźmy na przykład połączenie sieciowe. Możesz serializować dane / stan obiektu gniazda, ale istota aktywnego połączenia zostanie utracona.
źródło
implements NotSerializable
:)Główną rolą programu Serializable w Javie jest domyślne uniemożliwienie wszystkim innym obiektom serializacji. Serializacja to bardzo niebezpieczny mechanizm, zwłaszcza w domyślnej implementacji. Dlatego, podobnie jak przyjaźń w C ++, jest ona domyślnie wyłączona, nawet jeśli jej serializowanie kosztuje trochę.
Serializacja dodaje ograniczenia i potencjalne problemy, ponieważ zgodność struktury nie jest zapewniona. Dobrze, że jest domyślnie wyłączone.
Muszę przyznać, że widziałem bardzo niewiele nietrywialnych klas, w których standardowa serializacja robi to, co chcę. Zwłaszcza w przypadku złożonych struktur danych. Tak więc wysiłek, który trzeba poświęcić na poprawne serializowanie klasy, przewyższa koszt dodania interfejsu.
źródło
W przypadku niektórych klas, szczególnie tych, które reprezentują coś bardziej fizycznego, jak plik, gniazdo, wątek lub połączenie z bazą danych, serializowanie wystąpień nie ma absolutnie sensu. Dla wielu innych serializacja może być problematyczna, ponieważ niszczy ograniczenia związane z unikalnością lub po prostu zmusza do radzenia sobie z wystąpieniami różnych wersji klasy, czego możesz nie chcieć.
Prawdopodobnie lepiej byłoby uczynić wszystko domyślnie możliwym do serializacji i uczynić klasy nieserializowalnymi za pomocą słowa kluczowego lub interfejsu znacznika - ale wtedy ci, którzy powinni używać tej opcji, prawdopodobnie nie pomyśleliby o tym. Tak jest, jeśli musisz zaimplementować Serializable, zostaniesz o tym poinformowany przez wyjątek.
źródło
Myślę, że chodziło o to, abyś jako programista wiedział, że Twój obiekt może zostać zserializowany.
źródło
Najwyraźniej wszystko można było serializować w niektórych wstępnych projektach, ale ze względu na bezpieczeństwo i poprawność ostateczny projekt zakończył się, jak wszyscy wiemy.
Źródło: dlaczego klasy muszą implementować Serializable, aby można je było zapisać w ObjectOutputStream? .
źródło
Konieczność wyraźnego stwierdzenia, że instancje określonej klasy są serializowalne, język zmusza do przemyślenia, jeśli powinieneś na to zezwolić. W przypadku prostych obiektów wartości serializacja jest banalna, ale w bardziej złożonych przypadkach trzeba naprawdę przemyśleć sprawę.
Po prostu polegając na standardowej obsłudze serializacji JVM, narażasz się na wszelkiego rodzaju nieprzyjemne problemy z wersjonowaniem.
Wyjątkowość, odniesienia do „rzeczywistych” zasobów, liczników czasu i wielu innych typów artefaktów NIE są kandydatami do serializacji.
źródło
Przeczytaj to, aby zrozumieć interfejs Serializable Interface i dlaczego powinniśmy uczynić tylko kilka klas Serializable, a także zadbać o to, gdzie użyć słowa kluczowego transient na wypadek, gdybyśmy chcieli usunąć kilka pól z procedury przechowywania.
http://www.codingeek.com/java/io/object-streams-serialization-deserialization-java-example-serializable-interface/
źródło
Cóż, odpowiadam, że nie bez powodu. Z twoich komentarzy widzę, że już się tego nauczyłeś. Inne języki szczęśliwie próbują serializować wszystko, co nie przeskakuje na drzewo po policzeniu do 10. Obiekt powinien domyślnie być serializowalny.
Zasadniczo musisz samodzielnie przeczytać wszystkie właściwości swojej klasy zewnętrznej. Lub, jeśli to dla ciebie opcja: dekompiluj, umieść tam słowo kluczowe i przekompiluj.
źródło
W Javie są pewne rzeczy, których po prostu nie można serializować, ponieważ są one specyficzne dla środowiska wykonawczego. Rzeczy takie jak strumienie, wątki, środowisko uruchomieniowe itp., A nawet niektóre klasy GUI (które są połączone z podstawowym systemem operacyjnym) nie mogą być serializowane.
źródło
Chociaż zgadzam się z punktami przedstawionymi w innych odpowiedziach tutaj, prawdziwym problemem jest deserializacja: jeśli zmieni się definicja klasy, istnieje realne ryzyko, że deserializacja nie zadziała. Nigdy nie modyfikowanie istniejących pól jest dość dużym zobowiązaniem dla autora biblioteki! Utrzymanie zgodności z interfejsem API i tak jest wystarczającym obowiązkiem.
źródło
Klasa, która musi zostać utrwalona w pliku lub innym nośniku, musi implementować interfejs Serializable, aby maszyna JVM mogła umożliwić serializację obiektu klasy. Dlaczego klasa Object nie jest serializowana, żadna z klas nie musi implementować interfejsu, w końcu JVM serializuje klasę tylko wtedy, gdy używam ObjectOutputStream, co oznacza, że kontrola jest nadal w moich rękach, aby pozwolić JVM na serializację.
Powodem, dla którego klasa Object nie jest domyślnie serializowalna, jest fakt, że wersja klasy jest głównym problemem. Dlatego każda klasa, która jest zainteresowana serializacją, musi być jawnie oznaczona jako Serializable i podać numer wersji serialVersionUID.
Jeśli serialVersionUID nie zostanie podany, otrzymamy nieoczekiwane wyniki podczas deserialzowania obiektu, dlatego JVM zgłasza InvalidClassException, jeśli serialVersionUID nie pasuje. Dlatego każda klasa musi zaimplementować interfejs Serializable i zapewnić serialVersionUID, aby upewnić się, że klasa prezentowana na obu końcach jest identyczna.
źródło