– Pamiętasz, że dzisiaj badaliśmy zapisywanie obiektów do pliku i ich odczytywanie z pliku?

– Tak, właśnie zapisaliśmy je do strumienia wyjściowego i odczytaliśmy ze strumienia wejściowego.

– Dobra robota, Amigo! Dobrze słyszeć, że zwracasz uwagę na te szczegóły. Czy byłbyś w stanie dokończyć pisanie kodu tak, aby zapisywał dane do pliku i odczytywał z niego?

– Co dokończyć?! Zadeklarować FileInputStream i FileOutputStream i przekazać je do metod save i load. Nie ma tutaj niczego skomplikowanego. Super proste.

– Cieszę się razem z Tobą. Teraz nowy temat: serializacja.

Serializacja to prawie to samo, co przed chwilą zrobiliśmy, ale jest znacznie fajniejsza i wbudowana bezpośrednio w maszynie Java. Maszyna Java może przechowywać i ładować swoje obiekty. Nie potrzebuje nawet metod save i load, aby to zrobić: Wszystkie obiekty są przechowywane wewnątrz maszyny Java i ma do nich pełny dostęp.

Po prostu pobieramy obiekt, zapisujemy go do strumienia i odczytujemy ze strumienia:

Kod
public static void main(String[] args) throws Exception
{
 Cat cat = new Cat();

 //Zapisz kota do pliku
 FileOutputStream fileOutput = new FileOutputStream("cat.dat");
 ObjectOutputStream outputStream = new ObjectOutputStream(fileOutput);
 outputStream.writeObject(cat);
 fileOutput.close();
 outputStream.close();

 //Załaduj kota z pliku
 FileInputStream fiStream = new FileInputStream("cat.dat");
 ObjectInputStream objectStream = new ObjectInputStream(fiStream);
 Object object = objectStream.readObject();
 fiStream.close();
 objectStream.close();

 Cat newCat = (Cat)object;
}

– To wszystko?

– Dokładnie. Istnieje bardzo duży i skomplikowany mechanizm serializacji, który pozwala nam zapisywać w strumieniu i odczytywać ze strumienia prawie każdy typ danych.

– Prawie każdy. A zatem nie całkowicie dowolny typ danych?

– Zgadza się, tak naprawdę nie wszystkie obiekty stwarzają możliwość ich zapisania. Niektóre obiekty nie przechowują wszystkich swoich danych wewnętrznie. Zamiast tego, odwołują się one jedynie do innych obiektów i/lub źródeł danych. Na przykład, konsola (System.in), strumień wejściowy (InputStream) i inne.

Dlatego też projektanci Javy stworzyli specjalny marker interfejsu Serializable. Nazywa się go markerem, ponieważ nie zawiera on żadnych danych i metod. Używa się go tylko do „tagowania” lub „oznaczania” klas. Jeśli uważamy, że nasza klasa przechowuje wszystkie swoje dane wewnętrznie, to możemy je oznaczyć tak: implementuje Serializable.

Oto przykład «cat» z obsługą serializacji:

Kod
class Cat implements Serializable
{
 public String name;
 public int age;
 public int weight;
}

Kiedy próbujemy serializować (zapisać) obiekt, maszyna Java sprawdza, czy obsługuje on serializację: Czy implementuje on interfejs Serializable? Jeśli tak, to zapisuje obiekt. Jeśli nie, to wyrzuca wyjątek, aby wskazać, że serializacja jest niemożliwa.
W tym miejscu musisz zrozumieć, że serializowalny obiekt musi składać się wyłącznie z serializowalnych obiektów.

– Cóż, ma to sens. Nie możesz zapisać całości bez zapisania jej części.

– Dokładnie.

– A co z int, String i ArrayList?

– Wszystkie one obsługują serializację. Projektanci Javy specjalnie zadbali o to, by tak się stało. Nie powinno tu być żadnych problemów.

Co więcej, typ obiektu jest zapisywany, gdy obiekt jest serializowany. Teraz możesz zapisać odwołanie do obiektu Cat w zmiennej Object. Wszystko zostanie poddane procesowi serializacji i deserializacji.

– Deserializacji?

Deserializacja jest procesem odwrotnym do serializacji: odczytywanie i rekonstrukcja obiektu ze strumienia/pliku.

– Aha, w takim razie nie mam więcej pytań.