Serializacja to mechanizm przekształcania obiektu w strumień bajtów w celu późniejszego przechowywania lub przesyłania. W Javie serializacja pojawiła się wraz z platformą w wersji 1.1 jako część API, z uwagi na popularność aplikacji rozproszonych i potrzebę wymiany danych między nimi. To rozwiązanie pozwala upraszczać przesyłanie złożonych grafów obiektów między JVM i przechowywanie ich stanu, czyniąc proces przezroczystym dla programisty.
Problem serializacji polega na tym, że należy ściśle przestrzegać integralności danych, utrzymywać wersjonowanie klas i poprawnie obsługiwać złożone struktury (np. grafy z cyklicznymi odniesieniami). Nie wszystkie obiekty są serializowane (np. strumienie, gniazda, zasoby OS), a serializacja wymaga szczególnej uwagi na bezpieczeństwo.
Rozwiązanie zrealizowano za pomocą interfejsu Serializable:
import java.io.*; class Person implements Serializable { private static final long serialVersionUID = 1L; private String name; private transient int age; // nie jest serializowane public Person(String name, int age) { this.name = name; this.age = age; } }
Za pomocą ObjectOutputStream i ObjectInputStream obiekt można zapisać do pliku i przywrócić:
Person p = new Person("Alice", 30); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser")); oos.writeObject(p); // serializacja ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser")); Person restored = (Person) ois.readObject();
Kluczowe cechy:
Serializable.transient nie są serializowane.Czy można serializować obiekt z nieodpowiednim polem, nawet jeśli nie jest używane?
Odpowiedź: Jeśli pole jest oznaczone jako transient, nie jest serializowane w ogóle, a proces nie zakończy się wyjątkiem, nawet jeśli jego typ nie implementuje Serializable. Jeśli pole jest nieodpowiednie i nie jest transient, zostanie rzucony wyjątek NotSerializableException.
Czy pole statyczne jest serializowane, jeśli klasa implementuje Serializable?
Odpowiedź: Nie, pola statyczne nie są serializowane, ponieważ należą do klasy, a nie do instancji. Tylko stan instancji jest zachowywany.
Co się stanie, jeśli zmienisz strukturę klasy po serializacji (na przykład dodasz lub usuniesz pole)?
Odpowiedź: Jeśli określisz wersję serialVersionUID, a struktura zmieniła się w sposób niezgodny, podczas deserializacji pojawi się InvalidClassException. Aby zapewnić zgodność, używa się wskazówek serializacyjnych i ręcznego zarządzania serialVersionUID.
Inżynierowie postanowili serializować obiekt, nie dodając serialVersionUID i nie ogłaszając pól, które odnoszą się do zasobów OS, jako transient. Po aktualizacji aplikacji i klasy wystąpił InvalidClassException, a obiekt stracił integralność, a deserializacja przestała działać.
Zalety:
Wady:
Dla serializacji zrealizowano przenośną klasę z wyraźnym serialVersionUID, wszystkie pola-zasoby zostały ogłoszone jako transient, a ręczna serializacja kontroluje kluczowe momenty.
Zalety:
Wady: