Co to jest serializacja obiektów?


Odpowiedzi:


400

Serializacja to konwersja obiektu na szereg bajtów, dzięki czemu obiekt można łatwo zapisać w pamięci trwałej lub przesłać strumieniowo przez łącze komunikacyjne. Strumień bajtów można następnie przekształcić z postaci szeregowej - przekonwertować na replikę oryginalnego obiektu.


16
czy to jest obowiązkowe? czy muszę serializować dane przed wysłaniem? do jakiego formatu jest konwertowany?
Francisco Corrales Morales

15
@FranciscoCorralesMorales - za kulisami wszystkie dane zostaną serializowane przed przesłaniem ich strumieniowo. To, co musisz zrobić i jaki będzie format, zależy zarówno od używanej platformy, jak i bibliotek.
TarkaDaal

3
@FranciscoCorralesMorales Jak to mówisz? mam na myśli, że mówisz, że format zależy od platformy i bibliotek. Naprawdę chcę znać format.
JAVA,

1
Czy dotyczy tylko obiektów? Czy możemy serializować zmienne (zadeklarowane bez użycia obiektów)?
Rumado

@ Tylko
obiektyumado

395

Serializację można traktować jako proces przekształcania instancji obiektu w sekwencję bajtów (która może być binarna lub nie w zależności od implementacji).

Jest to bardzo przydatne, gdy chcesz przesłać dane jednego obiektu przez sieć, na przykład z jednej maszyny JVM do drugiej.

W Javie mechanizm serializacji jest wbudowany w platformę, ale musisz zaimplementować interfejs Serializable , aby obiekt mógł zostać serializowany.

Można również zapobiec szeregowaniu niektórych danych w obiekcie, zaznaczając atrybut jako przejściowy .

Wreszcie możesz zastąpić domyślny mechanizm i podać własny; może to być odpowiednie w niektórych szczególnych przypadkach. Aby to zrobić, użyj jednej z ukrytych funkcji w Javie .

Należy zauważyć, że serializowane są „wartości” obiektu lub zawartości, a nie definicja klasy. Zatem metody nie są serializowane.

Oto bardzo podstawowa próbka z komentarzami ułatwiającymi jej czytanie:

import java.io.*;
import java.util.*;

// This class implements "Serializable" to let the system know
// it's ok to do it. You as programmer are aware of that.
public class SerializationSample implements Serializable {

    // These attributes conform the "value" of the object.

    // These two will be serialized;
    private String aString = "The value of that string";
    private int    someInteger = 0;

    // But this won't since it is marked as transient.
    private transient List<File> unInterestingLongLongList;

    // Main method to test.
    public static void main( String [] args ) throws IOException  { 

        // Create a sample object, that contains the default values.
        SerializationSample instance = new SerializationSample();

        // The "ObjectOutputStream" class has the default 
        // definition to serialize an object.
        ObjectOutputStream oos = new ObjectOutputStream( 
                               // By using "FileOutputStream" we will 
                               // Write it to a File in the file system
                               // It could have been a Socket to another 
                               // machine, a database, an in memory array, etc.
                               new FileOutputStream(new File("o.ser")));

        // do the magic  
        oos.writeObject( instance );
        // close the writing.
        oos.close();
    }
}

Po uruchomieniu tego programu tworzony jest plik „o.ser” i możemy zobaczyć, co się stało.

Jeśli zmienimy wartość: someInteger na, na przykład Integer.MAX_VALUE , możemy porównać dane wyjściowe, aby zobaczyć, jaka jest różnica.

Oto zrzut ekranu pokazujący dokładnie tę różnicę:

alternatywny tekst

Czy dostrzegasz różnice? ;)

W serializacji Java jest dodatkowe istotne pole: serialversionUID, ale myślę, że jest to już za długo, aby je objąć.


1
@ raam86 przykład obiektem jest w odcinkach. W głównej metodzie możesz myśleć jako o osobnym programie, który tworzy obiekt typuSerializationSample
OscarRyz

2
@ raam86 to pierwsza instrukcja w metodzie głównej: SerializationSample instance = new SerializationSample();następnie tworzony jest wynik, a obiekt zapisywany na tym wyjściu.
OscarRyz

1
O. Nie dość blisko. Świetny!!
raam86

1
@jacktrades Dlaczego nie spróbujesz? Wystarczy skopiować / wkleić przykład i zobaczyć zgłoszenie „NotSerializableException” :)
OscarRyz

1
@jacktrades, ponieważ komputerowi nie powiedziano, że obiekt może być serializowany :) co rozumie się przez oos?
Chris Bennett,

101

Odważę się odpowiedzieć na 6-letnie pytanie, dodając tylko bardzo wysokiego poziomu zrozumienia dla osób, które nie znały Javy

Co to jest serializacja?

Konwertowanie obiektu na bajty

Co to jest deserializacja?

Konwertowanie bajtów z powrotem na obiekt (deserializacja).

Kiedy stosuje się serializację?

Kiedy chcemy przetrwać w obiekcie. Gdy chcemy, aby obiekt istniał poza okresem istnienia JVM.

Przykład świata rzeczywistego:

Bankomat: gdy właściciel konta próbuje wypłacić pieniądze z serwera za pośrednictwem bankomatu, informacje o posiadaczu rachunku, takie jak dane dotyczące wypłaty, zostaną przekształcone do postaci szeregowej i wysłane do serwera, na którym dane te są deserializowane i wykorzystywane do wykonywania operacji.

Jak odbywa się serializacja w Javie.

  1. Implementuj java.io.Serializableinterfejs (interfejs znacznika, więc nie ma metody implementacji).

  2. Utrwal obiekt: użyj java.io.ObjectOutputStreamklasy, strumienia filtru, który jest opakowaniem wokół strumienia bajtów niższego poziomu (aby zapisać obiekt do systemów plików lub przenieść spłaszczony obiekt przez przewód sieciowy i odbudowany po drugiej stronie).

    • writeObject(<<instance>>) - napisać obiekt
    • readObject() - odczytać zserializowany obiekt

Zapamiętaj:

Podczas szeregowania obiektu zapisywany jest tylko stan obiektu, a nie plik klasy obiektu lub metody.

Podczas serializacji obiektu 2-bajtowego widzisz 51-bajtowy plik serializowany.

Kroki, w jaki sposób obiekt jest serializowany i usuwany z serializacji.

Odpowiedź na: Jak przekonwertowano go na plik 51 bajtów?

  • Najpierw zapisuje magiczne dane strumienia serializacji (STREAM_MAGIC = „AC ED” i STREAM_VERSION = wersja JVM).
  • Następnie zapisuje metadane klasy powiązane z instancją (długość klasy, nazwa klasy, serialVersionUID).
  • Następnie rekurencyjnie zapisuje metadane nadklasy, dopóki nie znajdzie java.lang.Object.
  • Następnie rozpoczyna się od rzeczywistych danych powiązanych z instancją.
  • Na koniec zapisuje dane obiektów powiązanych z instancją, zaczynając od metadanych do rzeczywistej treści.

Jeśli interesują Cię bardziej szczegółowe informacje na temat serializacji Java, sprawdź ten link .

Edycja : jeszcze jeden dobry link do przeczytania.

Pozwoli to odpowiedzieć na kilka często zadawanych pytań:

  1. Jak nie serializować żadnego pola w klasie.
    Odp .: użyj przejściowego słowa kluczowego

  2. Kiedy serializowana jest klasa podrzędna, czy klasa nadrzędna jest serializowana?
    Odp .: Nie, jeśli rodzic nie rozszerza pola nadającego się do interfejsu szeregowego, rodzice nie podlegają serializacji.

  3. Kiedy serializowany jest rodzic, czy klasa potomna jest serializowana?
    Odp .: Tak, domyślnie serializowana jest również klasa podrzędna.

  4. Jak uniknąć serializacji klasy dziecięcej?
    Odp .: a. Przesłoń metodę writeObject i readObject i wyrzuć NotSerializableException.

    b. możesz także oznaczyć wszystkie pola jako przejściowe w klasie potomnej.

  5. Niektórych klas na poziomie systemu, takich jak Thread, OutputStream i jego podklasy oraz Socket, nie można serializować.

3
bardzo dziękuję za tę zwięzłą odpowiedź, była bardzo pomocna!
Nobi

21

Serializacja polega na pobraniu „aktywnego” obiektu z pamięci i przekształceniu go do formatu, który może być gdzieś zapisany (np. W pamięci, na dysku), a później „zdezrializowany” z powrotem na obiekt aktywny.


14

Podobał mi się sposób, w jaki prezentuje @OscarRyz. Chociaż tutaj kontynuuję historię serializacji, która została pierwotnie napisana przez @amitgupta.

Mimo że wiedza na temat struktury klas robotów i szeregowanie danych naukowcy Ziemi nie byli w stanie dokonać deserializacji danych, które mogą sprawić, że roboty będą działać.

Exception in thread "main" java.io.InvalidClassException:
SerializeMe; local class incompatible: stream classdesc
:

Naukowcy Marsa czekali na pełną płatność. Po dokonaniu płatności naukowcy Marsa udostępnili serialversionUID naukowcom z Ziemi. Naukowiec Ziemi ustawił go na klasę robotów i wszystko stało się dobrze.


9

Serializacja oznacza utrwalanie obiektów w Javie. Jeśli chcesz zapisać stan obiektu i chcesz go później odbudować (może być w innym JVM), możesz zastosować serializację.

Pamiętaj, że właściwości obiektu zostaną zapisane. Jeśli chcesz ponownie wskrzesić obiekt, powinieneś mieć plik klasy, ponieważ tylko zmienne składowe zostaną zapisane, a nie funkcje składowe.

na przykład:

ObjectInputStream oos = new ObjectInputStream(                                 
                                 new FileInputStream(  new File("o.ser")) ) ;
SerializationSample SS = (SearializationSample) oos.readObject();

Searializable to interfejs znaczników, który oznacza, że ​​twoja klasa jest serializowalna. Interfejs znaczników oznacza, że ​​jest to po prostu pusty interfejs i użycie tego interfejsu powiadomi JVM, że ta klasa może zostać przekształcona do postaci szeregowej.


9

Moje dwa centy z mojego bloga:

Oto szczegółowe wyjaśnienie serializacji : (mój własny blog)

Serializacja:

Serializacja to proces utrwalania stanu obiektu. Jest reprezentowany i przechowywany w postaci sekwencji bajtów. Można to zapisać w pliku. Proces odczytu stanu obiektu z pliku i przywracania go nazywa się deserializacją.

Jaka jest potrzeba serializacji?

We współczesnej architekturze zawsze istnieje potrzeba przechowywania stanu obiektu, a następnie jego odzyskiwania. Na przykład w Hibernacji, aby przechowywać obiekt, należy uczynić klasę Serializowalną. Po zapisaniu stanu obiektu w postaci bajtów można go przenieść do innego systemu, który może następnie odczytać stan i pobrać klasę. Stan obiektu może pochodzić z bazy danych lub innego środowiska JVM lub z oddzielnego komponentu. Za pomocą serializacji możemy odzyskać stan obiektu.

Przykład kodu i objaśnienie:

Najpierw spójrzmy na klasę przedmiotów:

public class Item implements Serializable{

    /**
    *  This is the Serializable class
    */
    private static final long serialVersionUID = 475918891428093041L;
    private Long itemId;
    private String itemName;
    private transient Double itemCostPrice;
    public Item(Long itemId, String itemName, Double itemCostPrice) {
        super();
        this.itemId = itemId;
        this.itemName = itemName;
        this.itemCostPrice = itemCostPrice;
      }

      public Long getItemId() {
          return itemId;
      }

     @Override
      public String toString() {
          return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
       }


       public void setItemId(Long itemId) {
           this.itemId = itemId;
       }

       public String getItemName() {
           return itemName;
       }
       public void setItemName(String itemName) {
            this.itemName = itemName;
        }

       public Double getItemCostPrice() {
            return itemCostPrice;
        }

        public void setItemCostPrice(Double itemCostPrice) {
             this.itemCostPrice = itemCostPrice;
        }
}

W powyższym kodzie widać, że klasa Item implementuje Serializable .

Jest to interfejs, który umożliwia serializację klasy.

Teraz widzimy, że zmienna o nazwie serialVersionUID jest inicjowana na zmienną Long. Liczba ta jest obliczana przez kompilator na podstawie stanu klasy i atrybutów klasy. Jest to liczba, która pomoże jvm zidentyfikować stan obiektu podczas odczytu stanu obiektu z pliku.

W tym celu możemy zapoznać się z oficjalną dokumentacją Oracle:

Środowisko wykonawcze serializacji wiąże z każdą klasą możliwą do serializacji numer wersji, zwany serialVersionUID, który jest używany podczas deserializacji w celu sprawdzenia, czy nadawca i odbiorca obiektu serializowanego załadowali klasy dla tego obiektu, które są kompatybilne w odniesieniu do serializacji. Jeśli odbiorca załadował klasę dla obiektu, który ma inny identyfikator serialVersionUID niż klasy odpowiedniego nadawcy, deserializacja spowoduje wyjątek InvalidClassException. Klasa możliwa do serializacji może jawnie zadeklarować własny serialVersionUID, deklarując pole o nazwie „serialVersionUID”, które musi być statyczne, końcowe i typu długiego: ANY-ACCESS-MODIFIER statyczny końcowy długi serialVersionUID = 42L; Jeśli klasa możliwa do serializacji nie deklaruje jawnie identyfikatora serialVersionUID, środowisko wykonawcze serializacji obliczy domyślną wartość serialVersionUID dla tej klasy na podstawie różnych aspektów tej klasy, zgodnie z opisem w specyfikacji Java Serialization Object Specification. Jednak zdecydowanie zaleca się, aby wszystkie klasy szeregowalne jawnie deklarowały wartości serialVersionUID, ponieważ domyślne obliczenie serialVersionUID jest bardzo wrażliwe na szczegóły klas, które mogą się różnić w zależności od implementacji kompilatora, a zatem może spowodować nieoczekiwane wyjątki InvalidClassException podczas deserializacji. Dlatego, aby zagwarantować spójną wartość serialVersionUID w różnych implementacjach kompilatora Java, klasa możliwa do serializacji musi zadeklarować jawną wartość serialVersionUID. Zdecydowanie zaleca się również, aby jawne deklaracje serialVersionUID korzystały w miarę możliwości z prywatnego modyfikatora,

Jeśli zauważyłeś, że użyliśmy innego słowa kluczowego, które jest przejściowe .

Jeśli pola nie można przekształcić do postaci szeregowej, należy je oznaczyć jako przejściowe. Tutaj zaznaczyliśmy itemCostPrice jako przejściowy i nie chcemy, aby był zapisany w pliku

Teraz przyjrzyjmy się, jak zapisać stan obiektu w pliku, a następnie odczytać go stamtąd.

public class SerializationExample {

    public static void main(String[] args){
        serialize();
       deserialize();
    } 

    public static void serialize(){

         Item item = new Item(1L,"Pen", 12.55);
         System.out.println("Before Serialization" + item);

         FileOutputStream fileOut;
         try {
             fileOut = new FileOutputStream("/tmp/item.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut);
             out.writeObject(item);
             out.close();
             fileOut.close();
             System.out.println("Serialized data is saved in /tmp/item.ser");
           } catch (FileNotFoundException e) {

                  e.printStackTrace();
           } catch (IOException e) {

                  e.printStackTrace();
           }
      }

    public static void deserialize(){
        Item item;

        try {
                FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
                ObjectInputStream in = new ObjectInputStream(fileIn);
                item = (Item) in.readObject();
                System.out.println("Serialized data is read from /tmp/item.ser");
                System.out.println("After Deserialization" + item);
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        } catch (IOException e) {
               e.printStackTrace();
        } catch (ClassNotFoundException e) {
               e.printStackTrace();
        }
     }
}

Powyżej widzimy przykład serializacji i deserializacji obiektu.

Do tego wykorzystaliśmy dwie klasy. Do serializacji obiektu użyliśmy ObjectOutputStream. Użyliśmy metody writeObject, aby zapisać obiekt w pliku.

Do deserializacji użyliśmy ObjectInputStream, który czyta obiekt z pliku. Używa readObject do odczytu danych obiektu z pliku.

Wyjście powyższego kodu wyglądałoby następująco:

Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
Serialized data is saved in /tmp/item.ser
After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]

Zauważ, że itemCostPrice z zdezrializowanego obiektu ma wartość NULL ponieważ nie został zapisany.

Omówiliśmy już podstawy serializacji Java w części I tego artykułu.

Teraz omówmy to głęboko i jak to działa.

Najpierw zacznijmy od serialversionuid.

SerialVersionUID służy jako kontrola wersji w postaci szeregowej klasie.

Jeśli jawnie nie zadeklarujesz serialVersionUID, JVM zrobi to za ciebie automatycznie, w oparciu o różne właściwości klasy Serializable.

Algorytm Java obliczania serialversionuid (Przeczytaj więcej szczegółów tutaj)

  1. Nazwa klasy.
    1. Modyfikatory klas zapisane jako 32-bitowa liczba całkowita.
    2. Nazwa każdego interfejsu posortowana według nazwy.
    3. Dla każdego pola klasy posortowanego według nazwy pola (z wyjątkiem prywatnych pól statycznych i prywatnych zmiennych przejściowych: Nazwa pola. Modyfikatory pola zapisane jako 32-bitowa liczba całkowita. Deskryptor pola.
    4. Jeśli istnieje inicjalizator klasy, napisz następujące: Nazwa metody,.
    5. Modyfikator metody java.lang.reflect.Modifier.STATIC, zapisany jako 32-bitowa liczba całkowita.
    6. Deskryptor metody () V.
    7. Dla każdego nieprywatnego konstruktora posortowanego według nazwy i podpisu metody: Nazwa metody,. Modyfikatory metody zapisane jako 32-bitowa liczba całkowita. Deskryptor metody.
    8. Dla każdej nieprywatnej metody posortowanej według nazwy i podpisu metody: Nazwa metody. Modyfikatory metody zapisane jako 32-bitowa liczba całkowita. Deskryptor metody.
    9. Algorytm SHA-1 jest wykonywany na strumieniu bajtów generowanym przez DataOutputStream i wytwarza pięć wartości 32-bitowych sha [0..4]. Wartość skrótu jest zestawiana z pierwszej i drugiej 32-bitowej wartości skrótu komunikatu SHA-1. Jeśli wynik podsumowania komunikatu, pięć 32-bitowych słów H0 H1 H2 H3 H4 znajduje się w tablicy pięciu wartości int o nazwie sha, wartość skrótu zostanie obliczona w następujący sposób:
    long hash = ((sha[0] >>> 24) & 0xFF) |
>            ((sha[0] >>> 16) & 0xFF) << 8 |
>            ((sha[0] >>> 8) & 0xFF) << 16 |
>            ((sha[0] >>> 0) & 0xFF) << 24 |
>            ((sha[1] >>> 24) & 0xFF) << 32 |
>            ((sha[1] >>> 16) & 0xFF) << 40 |
>            ((sha[1] >>> 8) & 0xFF) << 48 |
>        ((sha[1] >>> 0) & 0xFF) << 56;

Algorytm serializacji Java

Algorytm serializacji obiektu opisano poniżej:
1. Zapisuje metadane klasy powiązanej z instancją.
2. Rekurencyjnie zapisuje opis nadklasy, dopóki nie znajdzie java.lang.object .
3. Po zakończeniu zapisywania informacji o metadanych rozpocznie się od rzeczywistych danych powiązanych z instancją. Ale tym razem zaczyna się od najwyższej nadklasy.
4. Rekurencyjnie zapisuje dane powiązane z instancją, zaczynając od najmniejszej nadklasy do klasy najbardziej pochodnej.

O czym należy pamiętać:

  1. Pola statyczne w klasie nie mogą być serializowane.

    public class A implements Serializable{
         String s;
         static String staticString = "I won't be serializable";
    }
  2. Jeśli serialversionuid jest inny w klasie read, wygeneruje InvalidClassExceptionwyjątek.

  3. Jeśli klasa implementuje szeregowalny, wszystkie jego podklasy również będą szeregowalne.

    public class A implements Serializable {....};
    
    public class B extends A{...} //also Serializable
  4. Jeśli klasa ma odwołanie do innej klasy, wszystkie odniesienia muszą być możliwe do serializacji, w przeciwnym razie proces serializacji nie zostanie wykonany. W takim przypadku NotSerializableException jest generowany w czasie wykonywania.

Na przykład:

public class B{
     String s,
     A a; // class A needs to be serializable i.e. it must implement Serializable
}

1
„Serializacja to proces serializacji stanu obiektu jest reprezentowany i przechowywany w postaci sekwencji bajtów” jest bez znaczenia. Jeśli serialVersionUIDjest inaczej, rzuci an InvalidClassException, a nie a ClassCastException. Nie trzeba marnować całego miejsca na serialVersionUIDobliczenia. Dokumentacja jest cytowana w nadmiernej długości, ale nie jest powiązana ani właściwie cytowana. Tutaj jest za dużo puchu i za dużo błędów.
Markiz Lorne

„Serializacja to proces serializacji” pozostaje bez znaczenia.
Markiz Lorne

6

Serializacja to proces przekształcania stanu obiektu na bity, aby można go było zapisać na dysku twardym. Kiedy deserializujesz ten sam obiekt, zachowa on swój stan później. Umożliwia odtwarzanie obiektów bez konieczności ręcznego zapisywania właściwości obiektów.

http://en.wikipedia.org/wiki/Serialization


„... aby można go było zapisać na dysku twardym”. Lub przesyłane za pomocą protokołu binarnego.
Jim Anderson

4

Serializacja obiektów Java

wprowadź opis zdjęcia tutaj

Serializationjest mechanizmem przekształcającym wykres obiektów Java w tablicę bajtów do przechowywania ( to disk file) lub transmisji ( across a network), a następnie za pomocą deserializacji możemy przywrócić wykres obiektów. Wykresy obiektów są przywracane poprawnie za pomocą mechanizmu udostępniania referencji. Ale przed zapisaniem sprawdź, czy serialVersionUID z pliku wejściowego / sieci i pliku .class serialVersionUID są takie same. Jeśli nie, rzuć java.io.InvalidClassException.

Każda wersjonowana klasa musi zidentyfikować oryginalną wersję klasy, dla której jest w stanie zapisywać strumienie i z której może czytać. Na przykład klasa z wersją musi zadeklarować:

serialVersionUID Składnia

// ANY-ACCESS-MODIFIER static final long serialVersionUID = (64-bit has)L;
private static final long serialVersionUID = 3487495895819393L;

serialVersionUID jest niezbędny w procesie serializacji. Ale programista może opcjonalnie dodać go do pliku źródłowego Java. Jeśli serialVersionUID nie zostanie uwzględniony, środowisko wykonawcze serializacji wygeneruje serialVersionUID i powiąże go z klasą. Zserializowany obiekt będzie zawierał ten serialVersionUID wraz z innymi danymi.

Uwaga - Zdecydowanie zaleca się, aby wszystkie klasy szeregowalne jawnie deklarowały serialVersionUID since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, a zatem mogą powodować nieoczekiwane konflikty serialVersionUID podczas deserializacji, powodując niepowodzenie deserializacji.

Sprawdzanie klas możliwych do serializacji

wprowadź opis zdjęcia tutaj


Obiekt Java jest możliwy do serializacji. jeśli klasa lub którakolwiek z jej nadklas implementuje interfejs java.io.Serializable lub jego podinterface java.io.Externalizable .

  • Klasa musi zaimplementować interfejs java.io.Serializable , aby pomyślnie serializować swój obiekt. Serializable jest interfejsem znaczników i służy do informowania kompilatora, że ​​klasa implementująca go musi zostać dodana do postaci szeregowej. W tym przypadku Java Virtual Machine (JVM) odpowiada za automatyczną serializację.

    przejściowe Słowo kluczowe: java.io.Serializable interface

    Podczas szeregowania obiektu, jeśli nie chcemy, aby pewne elementy danych obiektu były serializowane, możemy użyć przejściowego modyfikatora. Przejściowe słowo kluczowe zapobiegnie serializacji tego elementu danych.

    • Pola zadeklarowane jako przejściowe lub statyczne są ignorowane przez proces serializacji.

    PRZEJRZYSTY I LOTNY

    +--------------+--------+-------------------------------------+
    |  Flag Name   |  Value | Interpretation                      |
    +--------------+--------+-------------------------------------+
    | ACC_VOLATILE | 0x0040 | Declared volatile; cannot be cached.|
    +--------------+--------+-------------------------------------+
    |ACC_TRANSIENT | 0x0080 | Declared transient; not written or  |
    |              |        | read by a persistent object manager.|
    +--------------+--------+-------------------------------------+
    class Employee implements Serializable {
        private static final long serialVersionUID = 2L;
        static int id;
    
        int eno; 
        String name;
        transient String password; // Using transient keyword means its not going to be Serialized.
    }
  • Implementacja interfejsu zewnętrznego umożliwia obiektowi przejęcie pełnej kontroli nad zawartością i formatem postaci szeregowej obiektu. Metody interfejsu zewnętrznego, writeExternal i readExternal, są wywoływane w celu zapisania i przywrócenia stanu obiektów. Po zaimplementowaniu przez klasę mogą zapisywać i odczytywać swój własny stan przy użyciu wszystkich metod ObjectOutput i ObjectInput. Obiekt jest odpowiedzialny za obsługę wszelkich występujących wersji.

    class Emp implements Externalizable {
        int eno; 
        String name;
        transient String password; // No use of transient, we need to take care of write and read.
    
        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeInt(eno);
            out.writeUTF(name);
            //out.writeUTF(password);
        }
        @Override
        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            this.eno = in.readInt();
            this.name = in.readUTF();
            //this.password = in.readUTF(); // java.io.EOFException
        }
    }
  • Tylko obiekty obsługujące interfejs java.io.Serializable lub java.io.Externalizable mogą być written to/read from streamami. Klasa każdego obiektu możliwego do serializacji jest kodowana, w tym nazwa klasy i podpis klasy, wartości pól i tablic obiektu oraz zamknięcie wszelkich innych obiektów, do których odwołuje się obiekt początkowy.

Serializowalny przykład plików

public class SerializationDemo {
    static String fileName = "D:/serializable_file.ser";

    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        Employee emp = new Employee( );
        Employee.id = 1; // Can not Serialize Class data.
        emp.eno = 77;
        emp.name = "Yash";
        emp.password = "confidential";
        objects_WriteRead(emp, fileName);

        Emp e = new Emp( );
        e.eno = 77;
        e.name = "Yash";
        e.password = "confidential";
        objects_WriteRead_External(e, fileName);

        /*String stubHost = "127.0.0.1";
        Integer anyFreePort = 7777;
        socketRead(anyFreePort); //Thread1
        socketWrite(emp, stubHost, anyFreePort); //Thread2*/

    }
    public static void objects_WriteRead( Employee obj, String serFilename ) throws IOException{
        FileOutputStream fos = new FileOutputStream( new File( serFilename ) );
        ObjectOutputStream objectOut = new ObjectOutputStream( fos );
        objectOut.writeObject( obj );
        objectOut.close();
        fos.close();

        System.out.println("Data Stored in to a file");

        try {
            FileInputStream fis = new FileInputStream( new File( serFilename ) );
            ObjectInputStream ois = new ObjectInputStream( fis );
            Object readObject;
            readObject = ois.readObject();
            String calssName = readObject.getClass().getName();
            System.out.println("Restoring Class Name : "+ calssName); // InvalidClassException

            Employee emp = (Employee) readObject;
            System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);

            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void objects_WriteRead_External( Emp obj, String serFilename ) throws IOException {
        FileOutputStream fos = new FileOutputStream(new File( serFilename ));
        ObjectOutputStream objectOut = new ObjectOutputStream( fos );

        obj.writeExternal( objectOut );
        objectOut.flush();

        fos.close();

        System.out.println("Data Stored in to a file");

        try {
            // create a new instance and read the assign the contents from stream.
            Emp emp = new Emp();

            FileInputStream fis = new FileInputStream(new File( serFilename ));
            ObjectInputStream ois = new ObjectInputStream( fis );

            emp.readExternal(ois);

            System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);

            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Przykład szeregowalny przez sieć

Rozkład stanu obiektu na różne przestrzenie adresowe, albo w różnych procesach na tym samym komputerze, albo nawet na wielu komputerach połączonych przez sieć, ale które współpracują ze sobą poprzez współdzielenie danych i wywoływanie metod.

/**
 * Creates a stream socket and connects it to the specified port number on the named host. 
 */
public static void socketWrite(Employee objectToSend, String stubHost, Integer anyFreePort) {
    try { // CLIENT - Stub[marshalling]
        Socket client = new Socket(stubHost, anyFreePort);
        ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
        out.writeObject(objectToSend);
        out.flush();
        client.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
// Creates a server socket, bound to the specified port. 
public static void socketRead(  Integer anyFreePort ) {
    try { // SERVER - Stub[unmarshalling ]
        ServerSocket serverSocket = new ServerSocket( anyFreePort );
        System.out.println("Server serves on port and waiting for a client to communicate");
            /*System.in.read();
            System.in.read();*/

        Socket socket = serverSocket.accept();
        System.out.println("Client request to communicate on port server accepts it.");

        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        Employee objectReceived = (Employee) in.readObject();
        System.out.println("Server Obj : "+ objectReceived.name );

        socket.close();
        serverSocket.close();
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
}

@widzieć


1
Kiedy dodajesz odpowiedź na sześcioletnie pytanie, które ma już kilka bardzo dobrych odpowiedzi, musisz zrobić znacznie więcej niż kakofonię błędów ortograficznych.
Markiz Lorne

@ejp Downvoting to narzędzie do wyrażania negatywnej opinii. Niedopuszczalne jest bycie obraźliwym i niegrzecznym.
Konstantinos Chertouras,

1
@KonstantinosChertouras Podanie powodów do głosowania jest pomocne dla plakatu, a są to moje powody, takie jak je lub nie, jak chcesz.
Markiz Lorne

Musisz także unikać błędów, takich jak twierdzenie, że serializacja ma cel bezpieczeństwa. Tak nie jest.
Markiz Lorne

@EJP Zaktualizowałem swój post, poprawiłem, że serializacja nie jest ze względów bezpieczeństwa, ale służy do transformacji stanu obiektu do dowolnej pamięci i do przywrócenia oryginalnego stanu obiektu za pomocą SUID poprzez dezrializację mechanisum. JVM to JVM
Yash

3

Serializacja to proces zapisywania obiektu na nośniku pamięci (takim jak plik lub bufor pamięci) lub przesyłania go przez połączenie sieciowe w formie binarnej. Serializowane obiekty są niezależne od JVM i mogą być ponownie serializowane przez dowolną JVM. W tym przypadku stan obiektów Java w pamięci jest konwertowany na strumień bajtów. Ten typ pliku nie może być zrozumiany przez użytkownika. Jest to specjalny typ obiektu, tj. Ponownie wykorzystywany przez JVM (Java Virtual Machine). Ten proces serializacji obiektu nazywa się również deflacją lub zestawieniem obiektu.

Obiekt, który ma być serializowany, musi implementować java.io.Serializableinterfejs. Domyślny mechanizm serializacji dla obiektu zapisuje klasę obiektu, sygnaturę klasy oraz wartości wszystkich pól nieprzemijających i niestatycznych.

class ObjectOutputStream extends java.io.OutputStream implements ObjectOutput,

ObjectOutputinterfejs rozszerza DataOutputinterfejs i dodaje metody serializacji obiektów i zapisywania bajtów do pliku. ObjectOutputStreamRozszerza java.io.OutputStreami narzędzia ObjectOutput interfejsu. Serializuje obiekty, tablice i inne wartości do strumienia. Tak więc konstruktor ObjectOutputStreamjest zapisany jako:

ObjectOutput ObjOut = new ObjectOutputStream(new FileOutputStream(f));

Powyższy kod został użyty do utworzenia instancji ObjectOutputklasy za pomocą ObjectOutputStream( )konstruktora, który przejmuje instancję klasyFileOuputStream jako parametr.

ObjectOutputInterfejs jest używany przez wdrożenie ObjectOutputStreamklasę. TheObjectOutputStreamJest wykonana serializacji obiektu.

Deserializowanie obiektu w java

Odwrotna operacja serializacji nazywa się deserializacją, tzn. Ekstrakcja danych z szeregu bajtów jest znana jako deserializacja, która jest również nazywana nadmuchiwaniem lub rozróżnianiem.

ObjectInputStreamrozszerza java.io.InputStreami implementuje ObjectInput interfejs. Deserializuje obiekty, tablice i inne wartości ze strumienia wejściowego. Tak więc konstruktor ObjectInputStreamjest zapisany jako:

ObjectInputStream obj = new ObjectInputStream(new FileInputStream(f));

Powyższy kod programu tworzy instancję ObjectInputStreamklasy w celu deserializacji tego pliku, który został zserializowany przez ObjectInputStreamklasę. Powyższy kod tworzy instancję za pomocą instancji FileInputStreamklasy, która przechowuje określony obiekt pliku, który należy zdekrirializować, ponieważ ObjectInputStream()konstruktor potrzebuje strumienia wejściowego.



2

Zwróć plik jako obiekt: http://www.tutorialspoint.com/java/java_serialization.htm

        import java.io.*;

        public class SerializeDemo
        {
           public static void main(String [] args)
           {
              Employee e = new Employee();
              e.name = "Reyan Ali";
              e.address = "Phokka Kuan, Ambehta Peer";
              e.SSN = 11122333;
              e.number = 101;

              try
              {
                 FileOutputStream fileOut =
                 new FileOutputStream("/tmp/employee.ser");
                 ObjectOutputStream out = new ObjectOutputStream(fileOut);
                 out.writeObject(e);
                 out.close();
                 fileOut.close();
                 System.out.printf("Serialized data is saved in /tmp/employee.ser");
              }catch(IOException i)
              {
                  i.printStackTrace();
              }
           }
        }

    import java.io.*;
    public class DeserializeDemo
    {
       public static void main(String [] args)
       {
          Employee e = null;
          try
          {
             FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn);
             e = (Employee) in.readObject();
             in.close();
             fileIn.close();
          }catch(IOException i)
          {
             i.printStackTrace();
             return;
          }catch(ClassNotFoundException c)
          {
             System.out.println("Employee class not found");
             c.printStackTrace();
             return;
          }
          System.out.println("Deserialized Employee...");
          System.out.println("Name: " + e.name);
          System.out.println("Address: " + e.address);
          System.out.println("SSN: " + e.SSN);
          System.out.println("Number: " + e.number);
        }
    }

Nie odpowiada to na pytanie „co to jest” lub „proszę wyjaśnić”.
Markiz Lorne

1

| * | Serializacja klasy: Konwersja obiektu na bajty i bajty z powrotem na obiekt (deserializacja).

class NamCls implements Serializable
{
    int NumVar;
    String NamVar;
}

| => Serializacja obiektu to proces przekształcania stanu obiektu w parę bajtów.

  • | -> Zaimplementuj, jeśli chcesz, aby obiekt istniał poza okresem istnienia JVM.
  • | -> Obiekt szeregowy może być przechowywany w bazie danych.
  • | -> Serializowalne obiekty nie mogą być odczytane i zrozumiane przez ludzi, dlatego możemy osiągnąć bezpieczeństwo.

| => Deserializacja obiektu to proces uzyskiwania stanu obiektu i przechowywania go w obiekcie (java.lang.Object).

  • | -> Przed zapisaniem stanu sprawdza, czy plik szeregowy_WersjiUżytkownika z pliku wejściowego / sieci i plik .klasowy_użytkownika są takie same.
    & nbsp & nbspJeśli nie wyrzucisz java.io.InvalidClassException.

| => Obiekt Java jest serializowalny tylko wtedy, gdy jego klasa lub którakolwiek z jego nadklas

  • implementuje interfejs java.io.Serializable lub
  • jego podinterface, java.io.Externalizable.

| => Pola statyczne w klasie nie mogą być serializowane.

class NamCls implements Serializable
{
    int NumVar;
    static String NamVar = "I won't be serializable";;
}

| => Jeśli nie chcesz serializować zmiennej klasy, użyj przejściowego słowa kluczowego

class NamCls implements Serializable
{
    int NumVar;
    transient String NamVar;
}

| => Jeśli klasa implementuje szeregowalny, to wszystkie jego podklasy również będą szeregowalne.

| => Jeśli klasa ma odwołanie do innej klasy, wszystkie odwołania muszą być możliwe do serializacji, w przeciwnym razie proces serializacji nie zostanie wykonany. W takim przypadku
NotSerializableException jest generowany w czasie wykonywania.


0

Przedstawię analogię, która może pomóc w utrwaleniu koncepcyjnego celu / praktyczności serializacji / deserializacji obiektu .

Wyobrażam sobie serializację / deserializację obiektu w kontekście próby przemieszczenia obiektu przez kanał burzowy. Obiekt jest zasadniczo „rozkładany” lub szeregowany w bardziej modułowe wersje siebie - w tym przypadku w szeregu bajtów - w celu skutecznego przejścia przez medium. W sensie obliczeniowym możemy postrzegać ścieżkę przebytą przez bajty przez kanał burzowy jako podobną do bajtów podróżujących przez sieć. Transmutujemy nasz obiekt, aby dostosować się do bardziej pożądanego środka transportu lub formatu. Zserializowany obiekt zwykle będzie przechowywany w pliku binarnym, z którego można później odczytać, zapisać lub jedno i drugie.

Być może, gdy nasz obiekt będzie w stanie prześlizgnąć się przez dren w postaci rozłożonej serii bajtów, możemy chcieć przechowywać tę reprezentację obiektu jako dane binarne w bazie danych lub na dysku twardym. Główną zaletą jest to, że w przypadku serializacji / deserializacji mamy możliwość pozostawienia naszego obiektu w postaci binarnej po serializacji lub „odzyskania” oryginalnej postaci obiektu przez przeprowadzenie deserializacji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.