Che cos'è la serializzazione degli oggetti?


Risposte:


400

La serializzazione è la conversione di un oggetto in una serie di byte, in modo che l'oggetto possa essere facilmente salvato nella memoria permanente o trasmesso in streaming attraverso un collegamento di comunicazione. Il flusso di byte può quindi essere deserializzato, convertito in una replica dell'oggetto originale.


16
è obbligatorio? devo serializzare i dati prima di inviarli? in quale formato viene convertito?
Francisco Corrales Morales,

15
@FranciscoCorralesMorales: dietro le quinte, tutti i dati verranno serializzati prima di essere inviati su un flusso. Quanto devi fare e in quale formato sarà, dipende sia dalla piattaforma che dalle librerie che stai utilizzando.
TarkaDaal,

3
@FranciscoCorralesMorales Come lo stai dicendo? voglio dire che stai dicendo che il formato dipende dalla piattaforma e dalle librerie. Voglio davvero conoscere il formato.
JAVA,

1
È applicabile solo agli oggetti? Possiamo serializzare le variabili (dichiarate senza usare oggetti)?
Rumado,

@Rumado Objects only
anKotliner

395

Puoi pensare alla serializzazione come al processo di conversione di un'istanza di oggetto in una sequenza di byte (che può essere binaria o non dipendente dall'implementazione).

È molto utile quando si desidera trasmettere i dati di un oggetto attraverso la rete, ad esempio da una JVM a un'altra.

In Java, il meccanismo di serializzazione è integrato nella piattaforma, ma è necessario implementare l' interfaccia Serializable per rendere serializzabile un oggetto.

È inoltre possibile impedire la serializzazione di alcuni dati nell'oggetto contrassegnando l'attributo come transitorio .

Finalmente puoi sovrascrivere il meccanismo predefinito e fornire il tuo; questo può essere adatto in alcuni casi speciali. Per fare questo, usi uno dei funzioni nascoste in Java .

È importante notare che ciò che viene serializzato è il "valore" dell'oggetto o dei contenuti e non la definizione della classe. Pertanto i metodi non sono serializzati.

Ecco un esempio molto semplice con commenti per facilitare la sua lettura:

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();
    }
}

Quando eseguiamo questo programma, viene creato il file "o.ser" e possiamo vedere cosa è successo dietro.

Se cambiamo il valore di: someInteger in, ad esempio Integer.MAX_VALUE , potremmo confrontare l'output per vedere qual è la differenza.

Ecco uno screenshot che mostra esattamente quella differenza:

testo alternativo

Riesci a individuare le differenze? ;)

C'è un ulteriore campo rilevante nella serializzazione Java: il serialversionUID ma immagino che questo sia già troppo lungo per coprirlo.


1
@ istanza raam86 è l'oggetto da serializzare. Puoi pensare nel metodo principale come un programma separato che crea un oggetto di tipoSerializationSample
OscarRyz,

2
@ raam86 è la prima affermazione del metodo principale: SerializationSample instance = new SerializationSample(); quindi l'output viene creato e l'oggetto scritto su quell'output.
Oscar Ryz,

1
Oh. Non è abbastanza vicino. Grande!!
raam86,

1
@jacktrades Perché non provarlo. Basta copiare / incollare l'esempio e vedere "NotSerializableException" lanciato :)
OscarRyz

1
@jacktrades perché al computer non è stato detto che è possibile serializzare l'oggetto :) cosa si intende per oos?
Chris Bennett,

101

Osare rispondere alla domanda di 6 anni, aggiungendo una comprensione di altissimo livello per le persone che non conoscono Java

Che cos'è la serializzazione?

Conversione di un oggetto in byte

Che cos'è la deserializzazione?

Conversione di byte in un oggetto (deserializzazione).

Quando viene utilizzata la serializzazione?

Quando vogliamo persistere nell'oggetto. Quando vogliamo che l'oggetto esista oltre la durata della JVM.

Esempio del mondo reale:

Bancomat: quando il titolare del conto tenta di prelevare denaro dal server tramite bancomat, le informazioni sul titolare del conto, come i dettagli di prelievo, vengono serializzate e inviate al server in cui i dettagli vengono deserializzati e utilizzati per eseguire le operazioni.

Come viene eseguita la serializzazione in Java.

  1. Implementare l' java.io.Serializableinterfaccia (interfaccia marker quindi nessun metodo da implementare).

  2. Persistere l'oggetto: Usa java.io.ObjectOutputStream classe, un flusso di filtro che è un wrapper attorno a un flusso di byte di livello inferiore (per scrivere l'oggetto su file system o trasferire un oggetto appiattito attraverso un filo di rete e ricostruito sull'altro lato).

    • writeObject(<<instance>>) - per scrivere un oggetto
    • readObject() - leggere un oggetto serializzato

Ricorda:

Quando si serializza un oggetto, verrà salvato solo lo stato dell'oggetto, non il file o i metodi della classe dell'oggetto.

Quando si serializza un oggetto a 2 byte, viene visualizzato un file serializzato di 51 byte.

Passa come l'oggetto viene serializzato e deserializzato.

Risposta per: Come è stato convertito in un file di 51 byte?

  • Scrive innanzitutto i dati magici del flusso di serializzazione (STREAM_MAGIC = "AC ED" e STREAM_VERSION = versione della JVM).
  • Quindi scrive i metadati della classe associata a un'istanza (lunghezza della classe, nome della classe, serialVersionUID).
  • Quindi scrive in modo ricorsivo i metadati della superclasse fino a quando non trova java.lang.Object .
  • Quindi inizia con i dati effettivi associati all'istanza.
  • Scrive infine i dati degli oggetti associati all'istanza a partire dai metadati nel contenuto effettivo.

Se sei interessato a informazioni più approfondite sulla serializzazione Java, controlla questo link .

Modifica : un altro link valido da leggere.

Questo risponderà ad alcune domande frequenti:

  1. Come non serializzare alcun campo in classe.
    Risposta: usa una parola chiave temporanea

  2. Quando la classe figlio viene serializzata, la classe genitore viene serializzata?
    Risp: No, se un genitore non estende il campo Genitori dell'interfaccia serializzabile non viene serializzato.

  3. Quando un genitore è serializzato, la classe figlio viene serializzata?
    Risp: Sì, per impostazione predefinita anche la classe figlio viene serializzata.

  4. Come evitare che le classi secondarie vengano serializzate?
    Ans: a. Sostituisci il metodo writeObject e readObject e lancia NotSerializableException.

    b. inoltre puoi contrassegnare tutti i campi transitori nella classe figlio.

  5. Alcune classi a livello di sistema come Thread, OutputStream e le sue sottoclassi e Socket non sono serializzabili.

3
grazie mille per questa risposta concisa, è stato molto utile!
Nobi,

21

La serializzazione sta prendendo in memoria un oggetto "live" e lo sta convertendo in un formato che può essere archiviato da qualche parte (ad es. In memoria, su disco) e successivamente "deserializzato" in un oggetto live.


14

Mi è piaciuto il modo in cui @OscarRyz si presenta. Anche se qui sto continuando la storia della serializzazione che è stata originariamente scritta da @amitgupta.

Sebbene conoscendo la struttura della classe dei robot e avendo dati serializzati, lo scienziato della Terra non è stato in grado di deserializzare i dati che possono far funzionare i robot.

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

Gli scienziati di Mars stavano aspettando il pagamento completo. Una volta effettuato il pagamento, gli scienziati di Mars hanno condiviso il serialversionUID con gli scienziati della Terra. Lo scienziato della Terra lo ha impostato sulla classe dei robot e tutto è andato bene.


9

La serializzazione significa oggetti persistenti in Java. Se si desidera salvare lo stato dell'oggetto e ricostruire lo stato in un secondo momento (potrebbe essere in un'altra JVM), è possibile utilizzare la serializzazione.

Si noti che le proprietà di un oggetto verranno salvate. Se si desidera resuscitare nuovamente l'oggetto, è necessario disporre del file di classe, poiché verranno memorizzate solo le variabili membro e non le funzioni membro.

per esempio:

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

Searializable è un'interfaccia marker che indica che la tua classe è serializzabile. L'interfaccia Marker significa che è solo un'interfaccia vuota e l'utilizzo di tale interfaccia avviserà la JVM che questa classe può essere resa serializzabile.


9

I miei due centesimi dal mio blog:

Ecco una spiegazione dettagliata della serializzazione : (il mio blog)

serializzazione:

La serializzazione è il processo di persistenza dello stato di un oggetto. È rappresentato e memorizzato sotto forma di una sequenza di byte. Questo può essere memorizzato in un file. Il processo per leggere lo stato dell'oggetto dal file e ripristinarlo si chiama deserializzazione.

Qual è la necessità della serializzazione?

Nell'architettura moderna, è sempre necessario memorizzare lo stato dell'oggetto e quindi recuperarlo. Ad esempio in Hibernate, per memorizzare un oggetto dovremmo rendere la classe serializzabile. Ciò che fa è che una volta salvato lo stato dell'oggetto sotto forma di byte, può essere trasferito su un altro sistema che può quindi leggere dallo stato e recuperare la classe. Lo stato dell'oggetto può provenire da un database o da un jvm diverso o da un componente separato. Con l'aiuto della serializzazione possiamo recuperare lo stato dell'Oggetto.

Esempio di codice e spiegazione:

Per prima cosa diamo un'occhiata alla classe di oggetti:

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;
        }
}

Nel codice sopra si può vedere che la classe Item implementa Serializable .

Questa è l'interfaccia che consente a una classe di essere serializzabile.

Ora possiamo vedere una variabile chiamata serialVersionUID inizializzata su Variabile lunga. Questo numero viene calcolato dal compilatore in base allo stato della classe e agli attributi della classe. Questo è il numero che aiuterà jvm a identificare lo stato di un oggetto quando legge lo stato dell'oggetto dal file.

Per questo possiamo dare un'occhiata alla documentazione Oracle ufficiale:

Il runtime di serializzazione associa a ciascuna classe serializzabile un numero di versione, chiamato serialVersionUID, che viene utilizzato durante la deserializzazione per verificare che il mittente e il destinatario di un oggetto serializzato abbiano caricato classi per quell'oggetto compatibili rispetto alla serializzazione. Se il destinatario ha caricato una classe per l'oggetto che ha un serialVersionUID diverso da quello della classe del mittente corrispondente, la deserializzazione si tradurrà in InvalidClassException. Una classe serializzabile può dichiarare esplicitamente la propria serialVersionUID dichiarando esplicitamente un campo denominato "serialVersionUID" che deve essere statico, finale e di tipo lungo: ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; Se una classe serializzabile non dichiara esplicitamente un serialVersionUID, quindi il runtime di serializzazione calcolerà un valore serialVersionUID predefinito per quella classe in base a vari aspetti della classe, come descritto nelle Specifiche di serializzazione degli oggetti Java (TM). Tuttavia, si raccomanda vivamente che tutte le classi serializzabili dichiarino esplicitamente i valori serialVersionUID, poiché il calcolo serialVersionUID predefinito è altamente sensibile ai dettagli della classe che possono variare a seconda delle implementazioni del compilatore e può quindi provocare eccezioni InvalidClassException impreviste durante la deserializzazione. Pertanto, per garantire un valore serialVersionUID coerente tra le diverse implementazioni del compilatore java, una classe serializzabile deve dichiarare un valore serialVersionUID esplicito. Si consiglia inoltre vivamente che dichiarazioni esplicite serialVersionUID utilizzino il modificatore privato ove possibile,

Se hai notato che abbiamo usato un'altra parola chiave che è temporanea .

Se un campo non è serializzabile, deve essere contrassegnato come transitorio. Qui abbiamo contrassegnato l' articoloCostPrice come transitorio e non vogliamo che sia scritto in un file

Ora diamo un'occhiata a come scrivere lo stato di un oggetto nel file e quindi leggerlo da lì.

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();
        }
     }
}

In quanto sopra possiamo vedere un esempio di serializzazione e deserializzazione di un oggetto.

Per questo abbiamo usato due classi. Per serializzare l'oggetto abbiamo usato ObjectOutputStream. Abbiamo usato il metodo writeObject per scrivere l'oggetto nel file.

Per la deserializzazione abbiamo usato ObjectInputStream che legge dall'oggetto dal file. Utilizza readObject per leggere i dati dell'oggetto dal file.

L'output del codice sopra sarebbe simile a:

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]

Si noti che itemCostPrice dall'oggetto deserializzato è null quanto non è stato scritto.

Abbiamo già discusso le basi della serializzazione Java nella parte I di questo articolo.

Ora discutiamolo a fondo e come funziona.

Per prima cosa iniziamo con il serialversionuid.

il serialVersionUID viene utilizzato come controllo di versione in una classe Serializable.

Se non dichiari esplicitamente un serialVersionUID, JVM lo farà automaticamente per te, in base a varie proprietà della classe Serializable.

Algorithm of Calculating serialversionuid di Java (Leggi maggiori dettagli qui)

  1. Il nome della classe
    1. I modificatori di classe scritti come un intero a 32 bit.
    2. Il nome di ciascuna interfaccia ordinata per nome.
    3. Per ogni campo della classe ordinato per nome campo (eccetto i campi transitori privati ​​statici e privati: il nome del campo. I modificatori del campo scritti come un numero intero a 32 bit. Il descrittore del campo.
    4. Se esiste un inizializzatore di classe, scrivere quanto segue: Il nome del metodo,.
    5. Il modificatore del metodo, java.lang.reflect.Modifier.STATIC, scritto come un numero intero a 32 bit.
    6. Il descrittore del metodo, () V.
    7. Per ogni costruttore non privato ordinato per nome e firma del metodo: Il nome del metodo,. I modificatori del metodo scritti come un numero intero a 32 bit. Il descrittore del metodo.
    8. Per ogni metodo non privato ordinato per nome e firma del metodo: il nome del metodo. I modificatori del metodo scritti come un numero intero a 32 bit. Il descrittore del metodo.
    9. L'algoritmo SHA-1 viene eseguito sul flusso di byte prodotto da DataOutputStream e produce cinque valori a 32 bit sha [0..4]. Il valore hash viene assemblato dal primo e dal secondo valore a 32 bit del digest del messaggio SHA-1. Se il risultato del digest del messaggio, le cinque parole a 32 bit H0 H1 H2 H3 H4, si trova in una matrice di cinque valori int chiamati sha, il valore di hash verrebbe calcolato come segue:
    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;

Algoritmo di serializzazione di Java

L'algoritmo per serializzare un oggetto è descritto di seguito:
1. Scrive i metadati della classe associata a un'istanza.
2. Scrive ricorsivamente la descrizione della superclasse fino a quando non trova java.lang.object .
3. Una volta terminata la scrittura delle informazioni sui metadati, inizia con i dati effettivi associati all'istanza. Ma questa volta, inizia dalla superclasse più in alto.
4. Scrive in modo ricorsivo i dati associati all'istanza, a partire dalla superclasse minima alla classe più derivata.

Cose da tenere a mente:

  1. I campi statici in una classe non possono essere serializzati.

    public class A implements Serializable{
         String s;
         static String staticString = "I won't be serializable";
    }
  2. Se il serialversionuid è diverso nella classe read genererà InvalidClassExceptionun'eccezione.

  3. Se una classe implementa serializzabile, anche tutte le sue sottoclassi saranno serializzabili.

    public class A implements Serializable {....};
    
    public class B extends A{...} //also Serializable
  4. Se una classe ha un riferimento di un'altra classe, tutti i riferimenti devono essere serializzabili altrimenti il ​​processo di serializzazione non verrà eseguito. In tal caso, NotSerializableException viene generato in fase di esecuzione.

Per esempio:

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

1
"La serializzazione è il processo di serializzazione dello stato di un oggetto rappresentato e memorizzato sotto forma di una sequenza di byte" non ha senso. Se serialVersionUIDè diverso, verrà lanciato un InvalidClassException, non un ClassCastException. Non è necessario sprecare tutto quello spazio rispettando il serialVersionUIDcalcolo. La documentazione viene citata, a una lunghezza eccessiva, ma non collegata o citata correttamente. Troppa lanugine qui e troppi errori.
Marchese di Lorne,

"La serializzazione è il processo di serializzazione" rimane insignificante.
Marchese di Lorne,

6

La serializzazione è il processo di conversione dello stato di un oggetto in bit in modo che possa essere memorizzato su un disco rigido. Quando si deserializza lo stesso oggetto, manterrà il suo stato in seguito. Ti consente di ricreare oggetti senza dover salvare le proprietà degli oggetti a mano.

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


"... in modo che possa essere memorizzato su un disco rigido." O trasferito tramite un protocollo binario.
Jim Anderson,

4

Serializzazione di oggetti Java

inserisci qui la descrizione dell'immagine

Serializationè un meccanismo per trasformare un grafico di oggetti Java in una matrice di byte per storage ( to disk file) o transmission ( across a network), quindi utilizzando la deserializzazione possiamo ripristinare il grafico degli oggetti. I grafici degli oggetti vengono ripristinati correttamente utilizzando un meccanismo di condivisione di riferimento. Ma prima di archiviare, controlla se serialVersionUID da input-file / network e .class serialVersionUID sono uguali. Altrimenti, lancia a java.io.InvalidClassException.

Ogni classe con versione deve identificare la versione della classe originale per la quale è in grado di scrivere flussi e dalla quale può leggere. Ad esempio, una classe con versione deve dichiarare:

serialVersionUID Sintassi

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

serialVersionUID è essenziale per il processo di serializzazione. Ma è facoltativo per lo sviluppatore aggiungerlo nel file sorgente Java. Se un serialVersionUID non è incluso, il runtime di serializzazione genererà un serialVersionUID e lo assocerà alla classe. L'oggetto serializzato conterrà questo serialVersionUID insieme ad altri dati.

Nota : si consiglia vivamente che tutte le classi serializzabili dichiarino esplicitamente un serialVersionUID since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementationse possano quindi causare conflitti imprevisti serialVersionUID durante la deserializzazione, causando il fallimento della deserializzazione.

Ispezione delle classi serializzabili

inserisci qui la descrizione dell'immagine


Un oggetto Java è solo serializzabile. se una classe o una delle sue superclasse implementa l' interfaccia java.io.Serializable o la sua interfaccia secondaria, java.io.Externalizable .

  • Una classe deve implementare l' interfaccia java.io.Serializable per serializzare correttamente il suo oggetto. Serializable è un'interfaccia marker e utilizzata per informare il compilatore che alla classe che lo implementa deve essere aggiunto un comportamento serializzabile. Qui Java Virtual Machine (JVM) è responsabile della sua serializzazione automatica.

    parola chiave transitoria: java.io.Serializable interface

    Durante la serializzazione di un oggetto, se non vogliamo che determinati membri dei dati dell'oggetto vengano serializzati, possiamo usare il modificatore transitorio. La parola chiave temporanea impedirà la serializzazione del membro in questione.

    • I campi dichiarati come transitori o statici vengono ignorati dal processo di serializzazione.

    TRANSIENTE E VOLATILE

    +--------------+--------+-------------------------------------+
    |  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.
    }
  • L'implementazione dell'interfaccia Externalizable consente all'oggetto di assumere il controllo completo sul contenuto e sul formato della forma serializzata dell'oggetto. I metodi dell'interfaccia Externalizable, writeExternal e readExternal, vengono chiamati per salvare e ripristinare lo stato degli oggetti. Se implementati da una classe, possono scrivere e leggere il proprio stato usando tutti i metodi di ObjectOutput e ObjectInput. È responsabilità degli oggetti gestire qualsiasi versione che si verifica.

    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
        }
    }
  • Solo gli oggetti che supportano l'interfaccia java.io.Serializable o java.io.Externalizable possono essere written to/read from stream. La classe di ogni oggetto serializzabile viene codificata includendo il nome e la firma della classe, i valori dei campi e delle matrici dell'oggetto e la chiusura di qualsiasi altro oggetto a cui fanno riferimento gli oggetti iniziali.

Esempio serializzabile per file

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();
        }
    }
}

Esempio serializzabile su rete

Distribuire lo stato dell'oggetto su diversi spazi indirizzo, sia in processi diversi sullo stesso computer, sia in più computer collegati tramite una rete, ma che lavorano insieme condividendo dati e invocando metodi.

/**
 * 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();
    }
}

@vedere


1
Quando aggiungi una risposta a una domanda di sei anni che ha già molte risposte molto valide, devi fare molto meglio di una cacofonia di errori di ortografia.
Marchese di Lorne,

@ejp Il downvoting è lo strumento per esprimere la tua opinione negativa. Essere offensivi e maleducati è inaccettabile.
Konstantinos Chertouras,

1
@KonstantinosChertouras Fornire motivi per il downvote è utile per il poster, e quelli sono i miei motivi, come loro o meno come vuoi.
Marchese di Lorne,

È inoltre necessario evitare errori come l'asserire che la serializzazione ha uno scopo di sicurezza. Non
Marchese di Lorne,

@EJP Ho aggiornato il mio post, corretto che la serializzazione non è a scopo di sicurezza, ma viene utilizzata per trasformare lo stato di un oggetto in qualsiasi archivio e per ripristinare lo stato originale di un oggetto utilizzando SUID attraverso un meccanismo di deserializzazione. JVM to JVM
Yash,

3

La serializzazione è il processo di salvataggio di un oggetto in un supporto di memorizzazione (come un file o un buffer di memoria) o di trasmetterlo su una connessione di rete in forma binaria. Gli oggetti serializzati sono indipendenti dalla JVM e possono essere nuovamente serializzati da qualsiasi JVM. In questo caso lo stato degli oggetti java "in memoria" viene convertito in un flusso di byte. Questo tipo di file non può essere compreso dall'utente. Si tratta di un tipo speciale di oggetto, ovvero riutilizzato dalla JVM (Java Virtual Machine). Questo processo di serializzazione di un oggetto è anche chiamato sgonfiamento o marshalling di un oggetto.

L'oggetto da serializzare deve implementare l' java.io.Serializableinterfaccia. Il meccanismo di serializzazione predefinito per un oggetto scrive la classe dell'oggetto, la firma della classe e i valori di tutti i campi non transitori e non statici.

class ObjectOutputStream extends java.io.OutputStream implements ObjectOutput,

ObjectOutputinterfaccia estende l' DataOutputinterfaccia e aggiunge metodi per serializzare oggetti e scrivere byte nel file. L' ObjectOutputStreamestensione java.io.OutputStreame implementa l' ObjectOutput interfaccia. Serializza oggetti, matrici e altri valori su un flusso. Quindi il costruttore di ObjectOutputStreamè scritto come:

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

Il codice sopra è stato usato per creare l'istanza della ObjectOutputclasse con il ObjectOutputStream( )costruttore che accetta l'istanza di FileOuputStreamcome parametro.

L' ObjectOutputinterfaccia viene utilizzata implementando la ObjectOutputStreamclasse. Il ObjectOutputStreamè costruito per serializzare l'oggetto.

Deserializzare un oggetto in Java

L'operazione opposta della serializzazione si chiama deserializzazione, ovvero estrarre i dati da una serie di byte è conosciuta come deserializzazione, che è anche chiamata inflazione o smascheramento.

ObjectInputStreamestende java.io.InputStreame implementa l' ObjectInput interfaccia. Deserializza oggetti, matrici e altri valori da un flusso di input. Quindi il costruttore di ObjectInputStreamè scritto come:

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

Il codice sopra del programma crea l'istanza della ObjectInputStreamclasse per deserializzare quel file che era stato serializzato dalla ObjectInputStreamclasse. Il codice sopra crea l'istanza usando l'istanza della FileInputStreamclasse che contiene l'oggetto file specificato che deve essere deserializzato perché il ObjectInputStream()costruttore ha bisogno del flusso di input.



2

Restituisce il file come oggetto: 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);
        }
    }

Questo non risponde a "ciò che è" o "spiega" parti della domanda.
Marchese di Lorne,

1

| * | Serializzazione di una classe: conversione di un oggetto in byte e byte nuovamente in oggetto (Deserializzazione).

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

| => La serializzazione di oggetti è un processo di conversione dello stato di un oggetto in vapore di byte.

  • | -> Implementare quando si desidera che l'oggetto esista oltre la durata della JVM.
  • | -> L'oggetto serializzato può essere archiviato nel database.
  • | -> Gli oggetti serializzabili non possono essere letti e compresi dagli umani, quindi possiamo raggiungere la sicurezza.

| => La deserializzazione di oggetti è il processo per ottenere lo stato di un oggetto e memorizzarlo in un oggetto (java.lang.Object).

  • | -> Prima di memorizzarne lo stato controlla se serialVersionUID forma input-file / network e .class file serialVersionUID sono uguali.
    & nbsp & nbspSe non getti java.io.InvalidClassException.

| => Un oggetto Java è serializzabile solo se la sua classe o una delle sue superclasse

  • implementa l'interfaccia java.io.Serializable o
  • la sua interfaccia secondaria, java.io.Externalizable.

| => I campi statici in una classe non possono essere serializzati.

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

| => Se non si desidera serializzare una variabile di una classe, utilizzare una parola chiave temporanea

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

| => Se una classe implementa serializzabile, anche tutte le sue sottoclassi saranno serializzabili.

| => Se una classe ha un riferimento di un'altra classe, tutti i riferimenti devono essere serializzabili altrimenti il ​​processo di serializzazione non verrà eseguito. In tal caso,
NotSerializableException viene generato in fase di esecuzione.


0

Offrirò un'analogia per aiutare potenzialmente a consolidare lo scopo concettuale / la praticità della serializzazione / deserializzazione degli oggetti .

Immagino la serializzazione / deserializzazione degli oggetti nel contesto del tentativo di spostare un oggetto attraverso una tempesta. L'oggetto è essenzialmente "decomposto" o serializzato in versioni più modulari di se stesso - in questo caso, una serie di byte - per consentire effettivamente il passaggio attraverso un supporto. In senso computazionale, potremmo vedere il percorso percorso dai byte attraverso la tempesta come simile ai byte che viaggiano attraverso una rete. Trasmutiamo il nostro oggetto per conformarci a una modalità di trasporto o formato più desiderabile. L'oggetto serializzato viene in genere archiviato in un file binario che può essere successivamente letto, scritto o entrambi.

Forse una volta che il nostro oggetto è in grado di scivolare attraverso il drain come una serie decomposta di byte, potremmo voler archiviare quella rappresentazione dell'oggetto come dati binari all'interno di un database o di un disco rigido. Il principale takeaway però è che con la serializzazione / deserializzazione, abbiamo la possibilità di lasciare che il nostro oggetto rimanga nella sua forma binaria dopo essere stato serializzato, o "recuperare" la forma originale dell'oggetto eseguendo la deserializzazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.