JavaRush /Blog Java /Random-PL /Jak serializacja działa w Javie
ramhead
Poziom 13

Jak serializacja działa w Javie

Opublikowano w grupie Random-PL
W tym artykule wyjaśnimy, czym jest serializacja i jak działa w Javie. Jak działa serializacja w Javie — 1

Wstęp

Serializacja obiektów to zdolność obiektu do przechowywania pełnej kopii siebie i innych obiektów, do których się odwołuje, przy użyciu strumienia wyjściowego (na przykład do pliku zewnętrznego). W ten sposób obiekt można odtworzyć z serializowanej (zapisanej) kopii nieco później, jeśli zajdzie taka potrzeba. Serializacja obiektów, nowa funkcja wprowadzona w JDK 1.1, udostępnia funkcję konwertowania grup lub pojedynczych obiektów na strumień bitów lub tablicę bajtów w celu przechowywania lub transmisji przez sieć. Jak już wspomniano, dany strumień bitów lub tablicę bajtów można ponownie przekonwertować na obiekty Java. Dzieje się to głównie automatycznie dzięki klasom ObjectInputStreami ObjectOutputStream. Programista może zdecydować się na zaimplementowanie tej funkcjonalności poprzez implementację interfejsu Serializablepodczas tworzenia klasy. Proces serializacji jest również nazywany kierowaniem obiektów , natomiast deserializacja jest nazywana unmarshalingiem . Serializacja to mechanizm, który pozwala obiektowi zapisać kopię siebie i wszystkich innych obiektów, do których odwołuje się ten obiekt, w pliku zewnętrznym przy użyciu rozszerzenia ObjectOutputStream. Zapisywanymi obiektami mogą być struktury danych, diagramy, obiekty klas JFramelub dowolne inne obiekty, niezależnie od ich typu. Jednocześnie serializacja przechowuje informacje o typie obiektu, aby później, podczas deserializacji, informacja ta została wykorzystana do odtworzenia dokładnego typu obiektu. Zatem serializacja zapewnia następujące możliwości:
  • System przechowywania obiektów, czyli: zapisywania ich właściwości do pliku zewnętrznego, na dysk lub do bazy danych.
  • System zdalnego wywoływania procedur.
  • System dystrybucji obiektów np. w komponentach oprogramowania takich jak COM, COBRA.
  • System identyfikacji zmian danych zmiennych w czasie.
Aby w pełni zrozumieć koncepcję serializacji, musisz dobrze rozumieć dwa pozostałe pojęcia — trwałość obiektu i trwałość wątku. Tutaj porozmawiamy trochę o każdym z nich, aby zapamiętać. Pełne ich wyjaśnienie wymagałoby osobnego rozdziału poświęconego każdemu z tych pojęć.

Strumienie:

Każdy program musi zapisywać swoje dane w lokalizacji pamięci lub potoku i każdy program musi czytać dane z potoku lub lokalizacji pamięci. W Javie kanały, do których programy zapisują i z których odczytują dane, nazywane są strumieniami ( Stream) . Jak działa serializacja w Javie — 2
Rysunek 1. Graficzna reprezentacja wątków
Strumienie dzielą się głównie na dwa typy:
  • Klasy strumieni bajtów zwane *Streams
  • Klasy strumieni znaków zwane *Reader i *Writer
Każdy strumień zapisu danych zawiera zestaw metod zapisu. Odpowiednio każdy wątek odczytu danych ma podobny zestaw metod odczytu. Po utworzeniu wątku należy wywołać wszystkie te metody.

Trwałość

Trwałość obiektu to zdolność obiektu do życia, czyli innymi słowy „przetrwania” wykonania programu. Oznacza to, że każdy obiekt utworzony w czasie wykonywania jest niszczony przez moduł oczyszczający JVM, gdy obiekt ten nie jest już używany. Jeśli jednak zostanie zaimplementowane API trwałości, obiekty te nie zostaną zniszczone przez scavenger JVM, zamiast tego będą mogły „żyć”, co umożliwi także dostęp do nich przy następnym uruchomieniu aplikacji. Innymi słowy, trwałość oznacza, że ​​istnieje czas życia obiektu, niezależny od czasu życia uruchomionej aplikacji. Jednym ze sposobów wdrożenia trwałości jest przechowywanie obiektów gdzieś w zewnętrznym pliku lub bazie danych, a następnie przywracanie ich w późniejszym czasie, używając tych plików lub bazy danych jako źródeł. Tutaj w grę wchodzi serializacja. Każdy nietrwały obiekt istnieje tak długo, jak działa maszyna JVM. Obiekty serializowane to po prostu obiekty konwertowane na strumienie, które następnie są zapisywane w pliku zewnętrznym lub przesyłane przez sieć w celu przechowywania i odzyskiwania.

Implementacja interfejsu Serializable

Każda klasa musi implementować interfejs java.io.Serializabledo serializacji obiektów tej klasy. Interfejs Serializablenie ma metod i oznacza jedynie klasę, dzięki czemu można ją zidentyfikować jako nadającą się do serializacji. Można zapisać tylko pola serializowanego obiektu klasy. Metody lub konstruktory nie są przechowywane jako część serializowanego strumienia. Jeśli jakikolwiek obiekt działa jako odniesienie do innego obiektu, wówczas pola tego obiektu są również serializowane, jeśli klasa tego obiektu implementuje interfejs Serializable. Innymi słowy, otrzymany w ten sposób wykres tego obiektu jest całkowicie serializowalny. Wykres obiektowy zawiera drzewo lub strukturę pól obiektu i jego podobiektów. Dwie główne klasy pomagające zaimplementować interfejs Seriliazable:
  • ObjectInputStream
  • ObjectOutputStream
Listing 1. Przykład prostej klasy pokazującej serializację
import java.io.*;
public class RandomClass implements Serializable {
 // Генерация рандомного значения
 private static int r() {
        return (int)(Math.random() * 10);
 }
    private int data[];
    // Конструктор
public RandomClass() {
        datafile = new int[r()];
        for (int i=0; i<datafile.length; i++)
        datafile[i]=r();
 }
    public void printout() {
 System.out.println("This RandomClass has "+datafile.length+" random integers");
 for (int i=0; i<datafile.length; i++) {
        System.out.print(datafile[i]+":");
        System.out.println();
    }
}
W powyższym kodzie utworzona jest klasa, którą można serializować, ponieważ „oznaczone” przez interfejs serializacji. Klasa tworzy tablicę losowych liczb całkowitych, gdy tworzona jest jej instancja. Poniższy kod pokazuje możliwość zapisywania obiektów w strumieniu przy użyciu metody ObjectOutputStream. Program ma tablicę liczb całkowitych, ale w przypadku serializacji nie musimy iterować po jego obiektach wewnętrznych. Interfejs Seriliazablezajmie się tym automatycznie. Listing 2. Prosty przykład serializacji obiektów w celu wyprowadzenia ich do pliku
import java.io.*;
import java.util.*;
public class OutSerialize {
    public static void main (String args[]) throws IOException {
        RandomClass rc1 = new RandomClass();
        RandomClass rc2 = new RandomClass();
//создание цепи потоков с потоком вывода obiektа в конце
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("objects.dat"));
        Date now = new Date(System.currentTimeMillis());
//java.util.* был импортирован для использования класса Date
        out.writeObject(now);
        out.writeObject(rc1);
        out.writeObject(rc2);
out.close();
        System.out.println("I have written:");
System.out.println("A Date object: "+now);
        System.out.println("Two Group of randoms");
rc1.printout();
rc2.printout();
 }
}
Poniższy kod demonstruje możliwości klasy ObjectInputStream, która wczytuje do programu serializowane dane z pliku zewnętrznego. Należy pamiętać, że obiekty są odczytywane w tej samej kolejności, w jakiej zostały zapisane do pliku. Listing 3. Odczyt serializowanych obiektów lub deserializacja
import java.io.*;
import java.util.*;
public class InSerialize {
 public static void main (String args[]) throws  IOException, ClassNotFoundException {
    ObjectInputStream in =  new ObjectInputStream (new FileInputStream("objects.dat"));
 Date d1 = (Date)in.readObject();
 RandomClass rc1 = (RandomClass)in.readObject();
    RandomClass rc2 = (RandomClass)in.readObject();
    System.out.println("I have read:");
    System.out.println("A Date object: "+d1);
    System.out.println("Two Group of randoms");
    rc1.printout();
rc2.printout();
 }
}
Prawie wszystkie klasy Java, łącznie z klasami AWT, mogą być serializowane. Ramka będąca oknem zawiera zestaw elementów graficznych. Jeśli ramka jest serializowana, silnik serializacji zajmuje się tym i serializuje wszystkie jej komponenty i dane (położenie, treść itp.). Niektórych obiektów klas Java nie można serializować, ponieważ zawierają dane odwołujące się do efemerycznych zasobów systemu operacyjnego. Na przykład klasy java.io.FileInputStreami java.lang.Thread. Jeśli obiekt zawiera odniesienia do elementów, których nie można serializować, cała operacja serializacji zakończy się niepowodzeniem i zostanie zgłoszony wyjątek NotSerializableException. Jeśli jakikolwiek obiekt odwołuje się do odniesienia do obiektu niezserializowanego, można go serializować za pomocą słowa kluczowego transient . Listing 4. Tworzenie obiektów serializowalnych przy użyciu słowa kluczowego transient
public class Sclass implements Serializable{
public transient Thread newThread;
//помните, что поток(поток параллельного исполнения) по умолчанию не сериализуемый класс
    private String studentID;
    private int sum;
}

Bezpieczeństwo w serializacji

Serializacja klasy w Javie polega na przekazaniu wszystkich jej danych do zewnętrznego pliku lub bazy danych za pośrednictwem strumienia. Możemy ograniczyć dane, które będą serializowane, kiedy tylko chcemy. Można to zrobić na dwa sposoby:
  • Każdy parametr klasy zadeklarowany jako przejściowy nie jest serializowany (domyślnie serializowane są wszystkie parametry klasy)
  • Lub każdy parametr klasy, który chcemy serializować, jest oznaczony znacznikiem Externalizable(domyślnie żadne parametry nie są serializowane).
Pole danych nie zostanie serializowane za pomocą ObjectOutputStream, gdy zostanie wywołane na obiekcie, jeśli pole danych tego obiektu jest oznaczone jako przejściowe . Na przykład: private transient String password. Z drugiej strony, aby jawnie zadeklarować dane obiektu jako nadające się do serializacji, musimy oznaczyć klasę jako ExternalizablewriteExternaljawnie readExteranlpiszącą i czytającą dane tego obiektu.

Wniosek

Cecha serializacji obiektów jest wykorzystywana w wielu systemach rozproszonych jako sposób przesyłania danych. Serializacja ujawnia jednak ukryte szczegóły, niszcząc w ten sposób autentyczność abstrakcyjnych typów danych, co z kolei niszczy enkapsulację. Jednocześnie miło jest wiedzieć, że dane serializowanego obiektu to te same dane, które znajdowały się w oryginalnym, oryginalnym obiekcie. Jest to również świetna okazja do zaimplementowania interfejsu ObjectInputValidationi zastąpienia metody validateObject(), nawet jeśli używanych jest wiele linii kodu. Jeśli obiekt nie zostanie znaleziony, możemy odpowiednio zgłosić wyjątek InvalidObjectException. Artykuł oryginalny: Jak działa serializacja w Javie
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION