2010-08-07 6 views
87

Was genau bedeutet es für eine Klasse in Java Serializable zu sein? Oder allgemeinWas bedeutet Serializable?

+10

@skaffman Hier ist, was es für die Klasse 'Serializable' sagt: ' Serialisierbarkeit einer Klasse wird von der Klasse ermöglicht die java.io.Serializable Schnittstelle implementieren. Für Klassen, die diese Schnittstelle nicht implementieren, wird der Status nicht serialisiert oder deserialisiert. Alle Subtypen einer serialisierbaren Klasse sind selbst serialisierbar. Die Serialisierungsschnittstelle hat keine Methoden oder Felder und dient nur dazu, die Semantik der Serialisierung zu identifizieren. –

+26

Eine großartige Erklärung, wenn Sie bereits wissen, was serialisiert und deserialisiert ist. (Kein Kompliment.) Solche Definitionen helfen Ihnen, das Problem technisch einmal besser zu verstehen, und nur einmal, Sie haben bereits ein gewisses Wissen darüber. – Xonatron

Antwort

92

Serialization speichert ein Objekt aus dem Speicher in einer Bitfolge, z. B. 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, wenn sie in einer Klasse implementiert wird, automatisch von verschiedenen Serialisierern serialisiert und deserialisiert werden kann.

+1

Beachten Sie auch, dass alle Felder, die nicht explizit anders gekennzeichnet sind, ebenfalls serialisiert werden. Dies bedeutet, dass Sie eine komplexe Datenstruktur einfach durch Serialisierung des Stammobjekts speichern können. –

29

Es bedeutet, dass Instanzen der Klasse in einen Byte-Stream umgewandelt werden können (um zum Beispiel in einer Datei gespeichert zu werden) und dann wieder in Klassen konvertiert werden. Dieses erneute Laden kann in einer anderen Instanz des Programms oder sogar auf einem anderen Computer geschehen. Die Serialisierung (in jeder Sprache) beinhaltet jedoch alle möglichen Probleme, besonders wenn Sie Verweise auf andere Objekte im serialisierbaren Objekt haben.

5

Serializable wird wie eine Schnittstelle aufgerufen, aber es ist eher eine Markierung für den Compiler. Es besagt, dass dieses Objekt gespeichert werden kann. Alle Objektinstanzvariablen mit Ausnahme von nicht serialisierbaren Objekten und Einsen, die flüchtig sind, werden gespeichert.

Stellen Sie sich vor, Ihre Anwendung kann die Farbe als Option ändern, ohne diese Einstellung extern zu halten, müssten Sie die Farbe jedes Mal ändern, wenn Sie sie ausführen.

+4

Es ist kein 'Flag für den Compiler'. Dies ist ein Flag für das Serialization-Subsystem zur Laufzeit. – EJP

+0

@EJP - Danke, wusste nicht, dass – AphexMunky

+0

Mit Respekt, warum schreiben Sie es, wenn Sie es nicht wissen, um wahr zu sein? Sie haben auch "vorübergehend" ausgelassen. Alles in allem eine schlechte Antwort, Entschuldigung. – EJP

8

Bei der Serialisierung wird der aktuelle Status eines Objekts in einem Stream gespeichert und ein entsprechendes Objekt aus diesem Stream wird wiederhergestellt. Der Stream fungiert als Container für das Objekt

0

Nur um die anderen Antworten hinzuzufügen und in Bezug auf die Allgemeinheit. Serialisierung wird manchmal als Archivierung bezeichnet, zum Beispiel in Objective-C.

4

Serialisierung ist eine Technik zum Speichern oder Schreiben der Objekte und Daten in Dateien. Unter Verwendung der Klassen ObjectOutputStream und . Diese Klassen haben ihre spezifischen Methoden, um die Objekte zu erhalten. wie writeObject();

für klare Erklärung mit Zahlen. See Here for more info

1

Um aus einer anderen Perspektive zu präsentieren. Serialisierung ist eine Art Schnittstelle, die "Markierungsschnittstelle" genannt wird. Eine Markierungsschnittstelle ist eine Schnittstelle, die keine Methodendeklarationen enthält, aber bezeichnet lediglich eine Klasse (oder "markiert"), die die Schnittstelle als bestimmte Eigenschaft implementiert. Wenn Sie Polymorphismus verstehen, wird das sehr viel Sinn machen. Im Fall der serialisierbaren Markierungsschnittstelle schlägt die ObjectOutputStream.write (Object) -Methode fehl, wenn ihr Argument die Schnittstelle nicht implementiert. Dies ist ein möglicher Fehler in Java, es hätte sein können ObjectOutputStream.write (Serializable)

Sehr zu empfehlen: Lesen Artikel 37 von Effektive Java von Joshua Bloch um mehr zu erfahren.

27

Obwohl die meisten der Benutzer bereits die Antwort gegeben haben, aber ich möchte ein Beispiel für diejenigen hinzuzufügen, die sie benötigen, um die Idee zu erklären:

Angenommen, Sie haben eine Klasse Person wie folgt aus:

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 Sie dann ein Objekt wie folgt erstellen:

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

Sie können das Objekt zu viele Ströme serialise. Ich werde das auf zwei Ströme tun:

Serialisierung auf die 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:

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

Serialisierung: Schreiben State of Object/Netzwerk Datei oder überall. (Mittleres Java-Objekt unterstützt Formular zu Datei unterstützt Formular oder Netzwerk unterstützt Formular)

Deserialisierung: Lesen von Objektstatus aus Datei/Netzwerk oder irgendwo. (Mean Datei/Netzwerk Unterstützte Formular Java Object Unterstützte Form)

4

Here is a detailed explanation of the Serialization: (mein eigenes Blog)

Serialisierung:

Serialisierung ist der Prozess den Zustand eines Objekts von Serialisierung dargestellt und in Form einer Bytefolge gespeichert. Dies kann in einer Datei gespeichert werden. Der Prozess zum Lesen des Zustands des Objekts aus der Datei und zum Wiederherstellen wird als Deserialisierung bezeichnet.

Was ist die Notwendigkeit der Serialisierung?

In der modernen Architektur muss der Objektstatus immer gespeichert und dann abgerufen werden. Um zum Beispiel in Hibernate ein Objekt zu speichern, sollten wir die Klasse Serializable machen. Sobald der Objektzustand in Form von Bytes gespeichert ist, kann er zu einem anderen System übertragen werden, das dann aus dem Zustand lesen und die Klasse abrufen kann. Der Objektzustand 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 Erläuterung:

Zuerst schaut sie sich das Item Class einen Blick:

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

In dem obigen Code kann man sehen, dass Artikel Klasse implementiert Serializable.

Dies ist die Schnittstelle, über die eine Klasse serialisiert werden kann.

Jetzt können wir sehen, eine Variable namens serialVersionUID wird initialisiert, um Long Variable. Diese Zahl wird vom Compiler basierend auf dem Status der Klasse und den Klassenattributen berechnet. Dies ist die Nummer, mit deren Hilfe der jvm den Status eines Objekts identifizieren kann, wenn er den Status des Objekts aus der Datei liest.

Dafür können wir einen Blick auf die offizielle Oracle-Dokumentation haben:

Die Serialisierung Runtime ordnet jedem serializable Klasse eine Versionsnummer, ein serialVersionUID genannt, die während Deserialisierung verwendet wird, um sicherzustellen, dass die Absender und Empfänger eines serialisierten Objekts haben Klassen für dieses Objekt geladen, die mit bezüglich der Serialisierung kompatibel sind. Wenn der Empfänger eine Klasse für das Objekt geladen hat, das eine andere serialVersionUID als die der entsprechenden Klasse des 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 statisch final long serialVersionUID = 42L; Wenn eine serializable Klasse nicht explizit eine serialVersionUID erklären, dann wird die Serialisierung Laufzeit einen Standard serialVersionUID Wert für diese Klasse auf der Grundlage verschiedenen Aspekte der Klasse berechnen, wie in der Java (TM) Objektserialisierung Spezifikation beschrieben. Es wird jedoch dringend empfohlen, dass alle serializable Klassen explizit serialVersionUID Werte erklären, da der Standard serialVersionUID Berechnung Klasse Details sehr empfindlich ist, die auf Compiler-Implementierungen variieren abhängig und kann somit in unerwarteten InvalidClassExceptions während Deserialisierung führen. Um einen konsistenten Wert für serialVersionUID über verschiedene Java-Compiler-Implementierungen zu garantieren, muss daher eine serialisierbare Klasse einen expliziten serialVersionUID-Wert deklarieren. Es ist auch stark empfohlen, dass explizite serialVersionUID-Deklarationen den privaten Modifizierer, wo möglich, verwenden, da solche Deklarationen gelten nur für die sofort deklarierende Klasse - serialVersionUID Felder sind nicht nützlich als geerbte Mitglieder.

Wenn Sie bemerkt haben, gibt es ein weiteres Schlüsselwort wir verwendet haben, die vorübergehende ist.

Wenn ein Feld nicht serialisierbar ist, muss es als transient markiert werden.Hier markierten wir den itemCostPrice als vorübergehend und nicht wollen, dass es in einer

Nun Datei geschrieben wird Werfen sie einen Blick darauf, wie der Zustand eines Objekts in der Datei zu schreiben und es dann von dort gelesen werden.

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. Zum Serialisieren 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:

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 von deserialisiert Objekt ist null, da es nicht geschrieben wurde.