Cosa significa esattamente che una classe si trova Serializable
in Java? O in generale, del resto ...
Cosa significa esattamente che una classe si trova Serializable
in Java? O in generale, del resto ...
Risposte:
La serializzazione sta persistendo un oggetto dalla memoria a una sequenza di bit, ad esempio per il salvataggio sul disco. La deserializzazione è l'opposto: leggere i dati dal disco per idratare / creare un oggetto.
Nel contesto della tua domanda, è un'interfaccia che se implementata in una classe, questa classe può automaticamente essere serializzata e deserializzata da diversi serializzatori.
Sebbene la maggior parte degli utenti abbia già dato la risposta, ma vorrei aggiungere un esempio per coloro che ne hanno bisogno per spiegare l'idea:
Supponiamo che tu abbia una persona di classe 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 poi crei un oggetto come questo:
Person william = new Person();
william.firstName = "William";
william.lastName = "Kinaan";
william.age = 26;
william.address = "Lisbon, Portugal";
È possibile serializzare quell'oggetto su molti flussi. Lo farò su due flussi:
Serializzazione allo 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();
}
Significa che le istanze della classe possono essere trasformate in un flusso di byte (ad esempio, per essere salvate in un file) e quindi nuovamente convertite in classi. Questa ricarica potrebbe avvenire in una diversa istanza del programma, o anche su una macchina diversa. La serializzazione (in qualsiasi lingua) comporta ogni sorta di problemi, specialmente quando si hanno riferimenti ad altri oggetti all'interno di quello serializzabile.
Ecco una spiegazione dettagliata della serializzazione : (il mio blog)
serializzazione:
La serializzazione è il processo di serializzazione dello stato di un oggetto 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'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 Long. 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 consiglia 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 inattese InvalidClassExceptions 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 itemCostPrice 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 è nullo in quanto non è stato scritto.
La serializzazione comporta il salvataggio dello stato corrente di un oggetto in un flusso e il ripristino di un oggetto equivalente da quel flusso. Il flusso funziona come contenitore per l'oggetto
Serializable è chiamato come un'interfaccia ma è più simile a un flag al sottosistema Serialization, in fase di esecuzione. Dice che questo oggetto può essere salvato. Verranno salvate tutte le variabili di istanza di Oggetti ad eccezione di nessun oggetto serializzabile e di quelli contrassegnati come volatili.
Immagina che la tua applicazione possa cambiare colore come opzione, senza mantenere quell'impostazione esterna dovrai cambiare il colore ogni volta che la esegui.
La serializzazione è una tecnica per archiviare o scrivere oggetti e dati in file. Usando ObjectOutputStream
e FileOutputStream
classi. Queste classi hanno i loro metodi specifici per mantenere gli oggetti. piacewriteObject();
per una chiara esplosione con figure. Per maggiori informazioni vedere qui
Presentare 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 "segna") una classe che implementa l'interfaccia come avente alcune proprietà. Se capisci il polimorfismo, questo avrà molto senso. Nel caso dell'interfaccia dell'indicatore 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 (Serializable)
Altamente raccomandato: leggere l'articolo 37 da Java efficace di Joshua Bloch per saperne di più.
Serializzazione: scrittura dello stato dell'oggetto su file / rete o ovunque. (Significa il modulo supportato da oggetto Java in File modulo supportato o modulo supportato in rete)
Deserializzazione: lettura dello stato dell'oggetto da file / rete o ovunque. (Modulo medio di file / rete supportato in modulo supportato oggetto Java)
Solo per aggiungere alle altre risposte e per quanto riguarda la generalità. La serializzazione è talvolta nota come archiviazione, ad esempio in Objective-C.
Serializable
:Serializability of a class is enabled by the class implementing the java.io.Serializable interface. Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.