Jason. Cała informatyka w jednym miejscu!

Czy ktoś z Was wie do czego służy serializacja obiektów w języku Java? Wiecie w ogóle że jest taki termin ;)? Jeśli drapiecie się po głowie, to czytajcie uważnie. Nie mówię, ż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 :D?

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ś programy przechowujące konfigurację, to również jest czymś, co zwykle powinno być zapisywane.

PRZYKŁAD KODU ŹRÓDŁOWEGO

Nakłaniam do przykucia uwagi na poniższy kod źródłowy. Ostrzegam, że on jest dużo większy od większości prezentowanych przykładów ;):

KLASA "MAIN"

public class Main {
	public static void main(String[] args) {
		new Serialization();
	}
}

KLASA "SERIALIZATION"

import java .io.*;

public class Serialization {
	private static final String SAVE_FILENAME = "save.data";

	private final Point pa = new Point(), pb = new Point(8, 6), pc = new Point(14, 13);

	public Serialization() {
		try {
			serializePoints();
			//deserializePoints();
		} catch (Exception e) {
			e.printStackTrace();
		}

		printPoints();
	}

	private void serializePoints() throws IOException {
		FileOutputStream fos = new FileOutputStream(SAVE_FILENAME);
		ObjectOutputStream oos = new ObjectOutputStream(fos);

		oos.writeObject(pa);
		oos.writeObject(pb);
		oos.writeObject(pc);
		oos.close();
	}

	private void deserializePoints() throws IOException, ClassNotFoundException {
		FileInputStream fis = new FileInputStream(SAVE_FILENAME);
		ObjectInputStream ois = new ObjectInputStream(fis);

		pa = (Point)ois.readObject();
		pb = (Point)ois.readObject();
		pc = (Point)ois.readObject();

		ois.close();
	}

	private void printPoints() {
		PrintStream ps = System.out;

		ps.println(pa);
		ps.println(pb);
		ps.println(pc);
	}
}

KLASA "POINT"

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 + ")";
	}
}

Gdybyśmy czytali przepis pt: "serializacja obiektów krok po kroku", brzmiałby mniej więcej tak:

  1. Utwórz obiekt, który ma być poddany serializacji danych,
  2. Zaimplementuj do niego interfejs "Serializable" 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!
  3. Dodaj specjalną daną składową do klasy o nazwie "serialVersionUID" typu "long" z modyfikatorami "private static final" jako stała statyczna (ARCYWAŻNA RZECZ, szczegóły znajdują się w odrębnym artykule),
  4. Zdefiniuj metodę serializującą obiekty dodając słowo kluczowe "throws", a w niej:
    1. zmienną typu "FileOutputStream" podając nazwę pliku, do którego będą wrzucone dane,
    2. zmienną typu "ObjectOutputStream" podając wcześniej utworzony obiekt,
    3. wywołanie metody "writeObject" ze strumienia wyjściowego obiektów podając wewnątrz nawiasów obiekt, który chcemy przechować,
    4. wywołanie metody "close" zamykającej plik.
  5. Zdefiniuj metodę deserializującą (odczytującą) obiekty dodając słowo kluczowe "throws", a w niej:
    1. zmienną typu "FileInputStream" podając nazwę pliku, z którego dane będą wyjmowane,
    2. zmienną typu "ObjectInputStream" podając wcześniej utworzony obiekt,
    3. przypisanie do każdego z obiektów wartości z wywoływanej metody "readObject" zachowując taką samą kolejność i rzutując na odpowiednią klasę,
    4. wywołanie metody "close" zamykającej plik.
  6. Dodaj klauzulę "try-catch" przechwytującą wyjątki i zawrzyj odpowiednią metodę w zależności od tego, czy chcesz zapisać, czy odczytać z pliku. Serializacja obiektów korzysta z metod mogących zgłosić wyjątek. W przypadku zapisu, utwórz wpierw instancje obiektów, a potem wywołaj metodę serializującą. W przypadku odczytu, nie twórz nowych kopii i wywołaj od razu metodę deserializującą przypisującą referencje do obiektów.

Nie dostaliście oczopląsu :D? Mam taką nadzieję. Prościej się tego napisać już nie da, aby dało się to zaprogramować w obie strony. Serializacja obiektów ma ten duży plus, że zapobiega zewnętrznej edycji danych. Zostawiłem obrazek ukazujący jak wygląda plik z danymi przechowujący "zmielone" obiekty poddane serializacji.

Serializacja obiektów w języku Java na wyjściu

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. Nie jest tu uwzględniony, aby nie czynić całego kodu niepotrzebnie większego. Słowo kluczowe "throws" pozwala "przerzucić" odpowiedzialność przechwycenia wyjątku na metodę wywołującą, artykuł na ten temat został już opublikowany.


To wszystko na chwilę obecną, i tak zbyt poważnie to już wygląda :).

PODOBNE ARTYKUŁY