Cosa significa Serializable?

Cosa significa esattamente per una class essere Serializable in Java? O in generale, del resto …

    La serializzazione sta mantenendo un object dalla memoria a una sequenza di bit, ad esempio per il salvataggio sul disco. La deserializzazione è l’opposto – la lettura dei dati dal disco per idratare / creare un object.

    Nel contesto della tua domanda, è un’interfaccia che, se implementata in una class, questa class può essere serializzata e deserializzata automaticamente da diversi serializzatori.

    Significa che le istanze della class possono essere trasformate in un stream di byte (ad esempio, per essere salvate in un file) e quindi riconvertite nuovamente in classi. Questo ricaricamento potrebbe avvenire in una diversa istanza del programma o anche su una macchina diversa. La serializzazione (in qualsiasi lingua) comporta tutti i tipi di problemi, tuttavia, specialmente quando si hanno riferimenti ad altri oggetti all’interno di uno serializzabile.

    Anche se la maggior parte degli utenti ha già dato la risposta, ma vorrei aggiungere un esempio a chi ne ha bisogno per spiegare l’idea:

    Supponiamo che tu abbia una persona di class come la seguente:

     public class Person implements java.io.Serializable { /** * */ private static final long serialVersionUID = 1L; public String firstName; public String lastName; public int age; public String address; public void play() { System.out.println(String.format( "If I win, send me the trophy to this address: %s", address)); } @Override public String toString() { return String.format(".....Person......\nFirst Name = %s\nLast Name = %s", firstName, lastName); } } 

    e quindi si crea un object come questo:

     Person william = new Person(); william.firstName = "William"; william.lastName = "Kinaan"; william.age = 26; william.address = "Lisbon, Portugal"; 

    Puoi serializzare quell’object su molti stream. Lo farò a due flussi:

    Serializzazione su standard output:

     public static void serializeToStandardOutput(Person person) throws IOException { OutputStream outStream = System.out; ObjectOutputStream stdObjectOut = new ObjectOutputStream(outStream); stdObjectOut.writeObject(person); stdObjectOut.close(); outStream.close(); } 

    Serializzazione in un file:

     public static void serializeToFile(Person person) throws IOException { OutputStream outStream = new FileOutputStream("person.ser"); ObjectOutputStream fileObjectOut = new ObjectOutputStream(outStream); fileObjectOut.writeObject(person); fileObjectOut.close(); outStream.close(); } 

    Poi:

    Deserializza dal file:

     public static void deserializeFromFile() throws IOException, ClassNotFoundException { InputStream inStream = new FileInputStream("person.ser"); ObjectInputStream fileObjectIn = new ObjectInputStream(inStream); Person person = (Person) fileObjectIn.readObject(); System.out.println(person); fileObjectIn.close(); inStream.close(); } 

    La serializzazione comporta il salvataggio dello stato corrente di un object in un stream e il ripristino di un object equivalente da quel stream. Lo stream funziona come un contenitore per l’object

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

    serializzazione:

    La serializzazione è il processo di serializzazione dello stato di un object che viene rappresentato e memorizzato sotto forma di una sequenza di byte. Questo può essere memorizzato in un file. Il processo per leggere lo stato dell’object dal file e ripristinarlo viene chiamato deserializzazione.

    Qual è il bisogno di serializzazione?

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

    Codice Esempio e spiegazione:

    Per prima cosa diamo un’occhiata alla class Item:

     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 class Item implementa Serializable .

    Questa è l’interfaccia che consente a una class di essere serializzabile.

    Ora possiamo vedere una variabile chiamata serialVersionUID inizializzata su Long variable. Questo numero viene calcolato dal compilatore in base allo stato della class e agli attributi della class. Questo è il numero che aiuterà jvm a identificare lo stato di un object quando legge lo stato dell’object dal file.

    Per questo possiamo dare un’occhiata alla documentazione ufficiale di Oracle:

    Il runtime di serializzazione associa a ciascuna class serializzabile un numero di versione, chiamato serialVersionUID, utilizzato durante la deserializzazione per verificare che il mittente e il destinatario di un object serializzato abbiano caricato classi per quell’object che sono compatibili con la serializzazione. Se il destinatario ha caricato una class per l’object che ha un serialVersionUID diverso da quello della class del mittente corrispondente, la deserializzazione produrrà una InvalidClassException. Una class serializzabile può dichiarare esplicitamente il proprio serialVersionUID dichiarando un campo denominato “serialVersionUID” che deve essere statico, finale e di tipo long: ANY-ACCESS-MODIFIER statico final long serialVersionUID = 42L; Se una class serializzabile non dichiara esplicitamente un serialVersionUID, il runtime di serializzazione calcolerà un valore serialVersionUID predefinito per quella class in base a vari aspetti della class, come descritto nella specifica di serializzazione dell’object Java (TM). Tuttavia, si consiglia vivamente che tutte le classi serializzabili dichiarino esplicitamente i valori serialVersionUID, poiché il calcolo serialVersionUID predefinito è estremamente sensibile ai dettagli della class che possono variare a seconda delle implementazioni del compilatore e può pertanto comportare imprevisti InvalidClassException durante la deserializzazione. Pertanto, per garantire un valore serialVersionUID coerente tra diverse implementazioni del compilatore java, una class serializzabile deve dichiarare un valore serialVersionUID esplicito. È inoltre vivamente consigliato che le dichiarazioni esplicite serialVersionUID utilizzino il modificatore privato laddove ansible, poiché tali dichiarazioni si applicano solo alla class immediatamente dichiarante – i campi serialVersionUID non sono utili come membri ereditati.

    Se hai notato c’è un’altra parola chiave che abbiamo usato che è transitoria .

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

    Ora diamo un’occhiata a come scrivere lo stato di un object nel file e poi 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 object.

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

    Per la deserializzazione abbiamo usato ObjectInputStream che legge dall’object dal file. Usa readObject per leggere i dati dell’object dal file.

    L’output del codice sopra sarebbe come:

     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’object deserializzato è nullo poiché non è stato scritto.

    Serializable è chiamato come un’interfaccia ma è più simile a una bandiera per il compilatore. Dice che questo object può essere salvato. Saranno salvate tutte le variabili di istanza di Oggetti con l’eccezione di nessuno oggetti serializzabili e quelle di segno volatile.

    Immagina che la tua applicazione possa cambiare colore come opzione, senza mantenere quella impostazione esterna avresti bisogno di cambiare il colore ogni volta che lo hai eseguito.

    La serializzazione è una tecnica per archiviare o scrivere oggetti e dati in file. Utilizzando le classi ObjectOutputStream e FileOutputStream . Queste classi hanno i loro metodi specifici per mantenere gli oggetti. come writeObject();

    per esplosione chiara con figure. Guarda qui per ulteriori informazioni

    Presentarsi da un’altra prospettiva. La serializzazione è un tipo di interfaccia chiamata ‘interfaccia marker’. Un’interfaccia marker è un’interfaccia che non contiene dichiarazioni di metodi, ma designa semplicemente (o “contrassegna”) una class che implementa l’interfaccia come avente alcune proprietà. Se capisci il polimorfismo questo avrà molto senso. Nel caso dell’interfaccia marcatore Serializable, il metodo ObjectOutputStream.write (Object) fallirà se il suo argomento non implementa l’interfaccia. Questo è un potenziale errore in java, potrebbe essere stato ObjectOutputStream.write (serializzabile)

    Altamente raccomandato: leggere l’articolo 37 da Java efficace di Joshua Bloch per saperne di più.

    Serializzazione: scrittura dello stato dell’object su file / rete o ovunque. (Modulo medio supportato da Java Object per modulo supportato da file o modulo supportato dalla rete)

    Deserializzazione: lettura dello stato dell’object da file / rete o da qualsiasi luogo. (File medio / modulo supportato dalla rete a modulo supportato da oggetti Java)

    Giusto per aggiungere alle altre risposte e in merito alla generalità. La serializzazione è talvolta nota come archiviazione, ad esempio in Objective-C.