Czy wiesz do czego służy serializacja obiektów w języku Java? Wiesz w ogóle, że jest taki termin 😉? Jeżeli drapiesz się po głowie, to czytaj uważnie 📖. Nie piszę, że jest to podstawa w rozumieniu języka, natomiast przechowywanie danych w celu zapisu i odczytu może być ciekawym eksperymentem. To co, przekonałem do zmiany decyzji 😄?
CZYM JEST SERIALIZACJA OBIEKTÓW W JĘZYKU JAVA?
Jak co artykuł, przejdę najpierw to czystej teorii. "Serializacja" to inaczej przekształcanie obiektów w czysty strumień bajtów chronionych przed zewnętrzną edycją. Kolokwialnie pisząc, przypomina to takie "zmielenie" obiektów, w których dane składowe są zabezpieczane i przechowywane w odrębnym pliku na dysku 💾. Java udostępnia taki system "zamrażania" i odtwarzania danych składowych obiektów, ale w taki sposób, żeby móc zrekonstruować stan obiektu sprzed zapisu.
Zanim jednak rozpoczniemy ukazanie przykładu, chcę jeszcze napisać jedną przestrogę: serializacja obiektów powinna być wykorzystywana wtedy i tylko wtedy, gdy jesteśmy święcie przekonani, że dane będą obsługiwane wyłącznie przez Javę. Jeżeli jest inaczej, stanie się to bezużyteczne i konieczne będzie użycie środka zastępczego w postaci eksportu do pliku tekstowego, ponieważ żaden inny język "nie rozumie" działania serializacji języka Java.
Jest multum zastosowań serializacji. Gry to pierwszy przykład jaki się idealnie nasuwa na użycie tego systemu 😁. Nikt z nas nie chce przechodzić ciągle tego samego etapu po wielu godzinach walki z wrogami lub rozgryzania wyjątkowo skomplikowanej zagadki. Czasy NESa się skończyły, teraz każda produkcja musi mieć system zapisu i odczytu ☺️. Jakieś konfiguracje aplikacji to również jest coś, co powinno być zapisywane.
KOD ŹRÓDŁOWY
Rzućmy okiem na prosty przykład serializacji. Mamy klasę "Point", którą chcemy serializować. Reprezentuje ona punkt na dwuwymiarowym układzie współrzędnych:
import java .io.Serializable;
public class Point implements Serializable {
private static final long serialVersionUID = 13L;
private final int x, y;
public Point() {
this(0, 0);
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "(" + x + ", " + y + ")";
}
}
Zauważ dwa ważne elementy tej klasy.
Po pierwsze, interfejs "Serializable". Serializacja obiektów w języku Java wymaga jego wstawienia. Jest to jeden z nielicznych interfejsów, które nie wymagają jakichkolwiek implementacji metod. Stosuje się go w celu uprzedzenia kompilatora, że taki manewr ma być dopuszczony dla klasy. To jest specyficzny interfejs, który jedynie odblokowuje możliwość serializacji, a sam nie posiada żadnych metod do przesłonięcia! Traktuj go bardziej jak oznaczenie. On jest "przepustką" do serializowania klasy i MUSI być wstawiony, aby doszło do tego procesu.
Drugim ważnym składnikiem jest stała o nazwie "serialVersionUID". Jest to specjalna dana składowa typu "long" z modyfikatorami "private static final" jako stała statyczna. ARCYWAŻNA RZECZ, bez której możesz sobie "narobić bidy" jak będziesz chciał(a) później deserializować (czyli odtwarzać) zapisane dane obiektu, a Ty zdążyłeś(-aś) już zmodyfikować dane składowe w klasie. Szczegóły są w odrębnym artykule.
A teraz popatrz na klasę, która uruchamia cały proceder:
import java .io.*;
public class Serialization {
private final Point pointA = new Point(2, 1);
private final Point pointB = new Point(8, 6);
private final Point pointC = new Point(14, 13);
public Serialization() {
try {
serialize();
} catch (Exception e) {
e.printStackTrace();
}
}
private void serialize() throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("save.data");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(pointA);
objectOutputStream.writeObject(pointB);
objectOutputStream.writeObject(pointC);
objectOutputStream.close();
}
}
Wypunktujmy sobie przebieg:
- Utwórz obiekt, który ma być poddany serializacji danych,
- Osadź blok kodu dotyczącego serializacji w blok "try-catch", ponieważ są to operacje "ryzykowne" i proces może się wysypać,
- Zdefiniuj zmienną typu "FileOutputStream" podając jako parametr ścieżkę do pliku razem z rozszerzeniem, do którego będą wrzucone dane,
- Zdefiniuj zmienną typu "ObjectOutputStream" podając jako parametr wcześniej utworzony obiekt typu "FileOutputStream",
- Wywołaj metodę "writeObject" ze strumienia wyjściowego obiektów podając wewnątrz nawiasów obiekt, który chcemy przechować,
- Wywołaj metodę "close" zamykającą strumień.
Serializacja obiektów w języku Java ma ten duży plus, że zapobiega zewnętrznej edycji danych. Poniżej możesz zobaczyć obrazek ukazujący jak wygląda plik z danymi przechowujący "zmielone" obiekty poddane serializacji.
Tak wyglądają "zmielone" dane składowe obiektów przechowujące wartości chronione przed edycją z zewnątrz.
Wpis "pl.jasonxiii.serialization" odnosi się do nazwy pakietu, do którego wrzuciłem wszystkie klasy. Słowo kluczowe "throws" pozwala "przerzucić" odpowiedzialność przechwycenia wyjątku na metodę wywołującą, artykuł na ten temat został już opublikowany.
Serializacja obiektów polega na przetworzeniu ("zmieleniu") obiektu na strumień bajtów. W języku Java czyni się to poprzez użycie metody "writeObject" z klasy "ObjectOutputStream".
To wszystko na chwilę obecną, i tak zbyt poważnie to już wygląda 🙂.