Was genau bedeutet es für eine Klasse, Serializable
in Java zu sein? Oder generell ...
Was genau bedeutet es für eine Klasse, Serializable
in Java zu sein? Oder generell ...
Antworten:
Bei der Serialisierung bleibt ein Objekt aus dem Speicher in einer Folge von Bits erhalten, beispielsweise zum Speichern auf der Festplatte. Deserialisierung ist das Gegenteil - Lesen von Daten von der Festplatte, um ein Objekt zu hydratisieren / zu erstellen.
Im Kontext Ihrer Frage handelt es sich um eine Schnittstelle, die bei Implementierung in einer Klasse von verschiedenen Serialisierern automatisch serialisiert und deserialisiert werden kann.
Obwohl die meisten Benutzer die Antwort bereits gegeben haben, möchte ich ein Beispiel für diejenigen hinzufügen, die sie benötigen, um die Idee zu erklären:
Angenommen, Sie haben eine Klassenperson wie die folgende:
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);
}
}
und dann erstellen Sie ein Objekt wie folgt:
Person william = new Person();
william.firstName = "William";
william.lastName = "Kinaan";
william.age = 26;
william.address = "Lisbon, Portugal";
Sie können dieses Objekt für viele Streams serialisieren. Ich werde das mit zwei Streams machen:
Serialisierung auf Standardausgabe:
public static void serializeToStandardOutput(Person person)
throws IOException {
OutputStream outStream = System.out;
ObjectOutputStream stdObjectOut = new ObjectOutputStream(outStream);
stdObjectOut.writeObject(person);
stdObjectOut.close();
outStream.close();
}
Serialisierung in eine Datei:
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();
}
Dann:
Deserialisieren aus Datei:
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();
}
Dies bedeutet, dass Instanzen der Klasse in einen Byte-Stream umgewandelt werden können (z. B. um in einer Datei gespeichert zu werden) und dann wieder in Klassen konvertiert werden können. Dieses Neuladen kann in einer anderen Instanz des Programms oder sogar auf einem anderen Computer erfolgen. Die Serialisierung (in jeder Sprache) ist jedoch mit allen möglichen Problemen verbunden, insbesondere wenn Sie Verweise auf andere Objekte innerhalb des serialisierbaren Objekts haben.
Hier ist eine detaillierte Erklärung der Serialisierung : (mein eigener Blog)
Serialisierung:
Bei der Serialisierung wird der Status eines Objekts serialisiert, das in Form einer Folge von Bytes dargestellt und gespeichert wird. Dies kann in einer Datei gespeichert werden. Der Vorgang zum Lesen und Wiederherstellen des Status des Objekts aus der Datei wird als Deserialisierung bezeichnet.
Was ist die Notwendigkeit der Serialisierung?
In der modernen Architektur besteht immer die Notwendigkeit, den Objektstatus zu speichern und dann abzurufen. Zum Beispiel sollten wir im Ruhezustand zum Speichern eines Objekts die Klasse Serializable machen. Sobald der Objektstatus in Form von Bytes gespeichert ist, kann er auf ein anderes System übertragen werden, das dann aus dem Status lesen und die Klasse abrufen kann. Der Objektstatus kann aus einer Datenbank oder einem anderen JVM oder aus einer separaten Komponente stammen. Mit Hilfe der Serialisierung können wir den Objektstatus abrufen.
Codebeispiel und Erklärung:
Schauen wir uns zuerst die Gegenstandsklasse an:
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;
}
}
Im obigen Code ist zu sehen, dass die Item- Klasse Serializable implementiert .
Dies ist die Schnittstelle, über die eine Klasse serialisierbar ist.
Jetzt können wir sehen, dass eine Variable namens serialVersionUID mit der Variablen Long initialisiert wird. Diese Zahl wird vom Compiler basierend auf dem Status der Klasse und den Klassenattributen berechnet. Dies ist die Nummer, mit der der JVM den Status eines Objekts identifizieren kann, wenn er den Status des Objekts aus der Datei liest.
Dafür können wir uns die offizielle Oracle-Dokumentation ansehen:
Die Serialisierungslaufzeit ordnet jeder serialisierbaren Klasse eine Versionsnummer zu, die als serialVersionUID bezeichnet wird und während der Deserialisierung verwendet wird, um zu überprüfen, ob der Absender und der Empfänger eines serialisierten Objekts Klassen für dieses Objekt geladen haben, die hinsichtlich der Serialisierung kompatibel sind. Wenn der Empfänger eine Klasse für das Objekt geladen hat, das eine andere serialVersionUID als die Klasse des entsprechenden Absenders hat, führt die Deserialisierung zu einer InvalidClassException. Eine serialisierbare Klasse kann ihre eigene serialVersionUID explizit deklarieren, indem sie ein Feld mit dem Namen "serialVersionUID" deklariert, das statisch, final und vom Typ long sein muss: ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; Wenn eine serialisierbare Klasse eine serialVersionUID nicht explizit deklariert, Anschließend berechnet die Serialisierungslaufzeit einen Standardwert für serialVersionUID für diese Klasse basierend auf verschiedenen Aspekten der Klasse, wie in der Java (TM) -Objektserialisierungsspezifikation beschrieben. Es wird jedoch dringend empfohlen, dass alle serialisierbaren Klassen explizit serialVersionUID-Werte deklarieren, da die Standardberechnung für serialVersionUID sehr empfindlich auf Klassendetails reagiert, die je nach Compiler-Implementierungen variieren können und daher während der Deserialisierung zu unerwarteten InvalidClassExceptions führen können. Um einen konsistenten serialVersionUID-Wert für verschiedene Java-Compiler-Implementierungen zu gewährleisten, muss eine serialisierbare Klasse daher einen expliziten serialVersionUID-Wert deklarieren. Es wird außerdem dringend empfohlen, dass explizite serialVersionUID-Deklarationen nach Möglichkeit den privaten Modifikator verwenden.
Wenn Sie bemerkt haben, dass wir ein anderes Schlüsselwort verwendet haben, das vorübergehend ist .
Wenn ein Feld nicht serialisierbar ist, muss es als vorübergehend markiert werden. Hier haben wir den itemCostPrice als vorübergehend markiert und möchten nicht, dass er in eine Datei geschrieben wird
Schauen wir uns nun an, wie Sie den Status eines Objekts in die Datei schreiben und von dort aus lesen.
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();
}
}
}
Oben sehen wir ein Beispiel für die Serialisierung und Deserialisierung eines Objekts.
Dafür haben wir zwei Klassen verwendet. Für die Serialisierung des Objekts haben wir ObjectOutputStream verwendet. Wir haben die Methode writeObject verwendet, um das Objekt in die Datei zu schreiben.
Für die Deserialisierung haben wir ObjectInputStream verwendet, der aus dem Objekt aus der Datei liest. Es verwendet readObject, um die Objektdaten aus der Datei zu lesen.
Die Ausgabe des obigen Codes wäre wie folgt:
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]
Beachten Sie, dass itemCostPrice vom deserialisierten Objekt null ist, da es nicht geschrieben wurde.
Bei der Serialisierung wird der aktuelle Status eines Objekts in einem Stream gespeichert und ein gleichwertiges Objekt aus diesem Stream wiederhergestellt. Der Stream fungiert als Container für das Objekt
Serializable wird wie eine Schnittstelle aufgerufen, ist jedoch eher ein Flag für den Compiler. Es heißt, dass dieses Objekt gespeichert werden kann. Alle Instanzvariablen von Objects mit Ausnahme von nicht serialisierbaren Objekten und solchen, die als flüchtig markiert sind, werden gespeichert.
Stellen Sie sich vor, Ihre Anwendung kann die Farbe optional ändern, ohne dass diese Einstellung extern bleibt. Sie müssten die Farbe jedes Mal ändern, wenn Sie sie ausführen.
Die Serialisierung ist eine Technik zum Speichern oder Schreiben der Objekte und Daten in Dateien. Mit ObjectOutputStream
und FileOutputStream
Klassen. Diese Klassen haben ihre spezifischen Methoden, um die Objekte beizubehalten. mögenwriteObject();
für eine klare Erklärung mit Zahlen. Weitere Informationen finden Sie hier
Aus einer anderen Perspektive präsentieren. Die Serialisierung ist eine Art Schnittstelle, die als "Marker-Schnittstelle" bezeichnet wird. Eine Markierungsschnittstelle ist eine Schnittstelle, die keine Methodendeklarationen enthält, sondern lediglich eine Klasse bezeichnet (oder „markiert“), die die Schnittstelle mit einer Eigenschaft implementiert. Wenn Sie Polymorphismus verstehen, ist dies sehr sinnvoll. Bei der Serializable-Marker-Schnittstelle schlägt die ObjectOutputStream.write (Object) -Methode fehl, wenn ihr Argument die Schnittstelle nicht implementiert. Dies ist ein möglicher Fehler in Java. Es könnte ObjectOutputStream.write (Serializable) gewesen sein.
Sehr zu empfehlen: Lesen Sie Punkt 37 aus Effective Java von Joshua Bloch , um mehr zu erfahren.
Serialisierung: Schreiben des Objektstatus in eine Datei / ein Netzwerk oder irgendwo anders. (Mittleres von Java Object unterstütztes Formular zu Dateiunterstütztes Formular oder Netzwerkunterstütztes Formular)
Deserialisierung: Lesen des Objektstatus aus Datei / Netzwerk oder irgendwo anders . (Mittleres von Dateien / Netzwerken unterstütztes Formular zum von Java Object unterstützten Formular)
Nur um die anderen Antworten und in Bezug auf die Allgemeinheit zu ergänzen. Serialisierung wird manchmal als Archivierung bezeichnet, beispielsweise 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.