– 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:
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:
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ń.
GO TO FULL VERSION