Heim > Java > JavaErste Schritte > Hauptteil

Serialisierung und Deserialisierung von Java-Objekten

青灯夜游
Freigeben: 2019-11-27 17:59:22
nach vorne
2536 Leute haben es durchsucht

Serialisierung und Deserialisierung von Java-Objekten

Serialisierung und Deserialisierung von Objekten

1) Die Objektserialisierung dient andernfalls dazu, das Objektobjekt in eine Bytesequenz umzuwandeln Dies wird als Deserialisierung des Objekts bezeichnet.

2) Serialisierungsstrom (ObjectOutputStream), der ein gefilterter Bytestrom ist – writeObject()-Methode

Deserialisierungsstrom (ObjectInputStream) – readObject()-Methode

3) Serialisierbare Schnittstelle (Serialisierbar)

Das Objekt muss die Serialisierungsschnittstelle implementieren, um serialisiert zu werden, andernfalls tritt eine Ausnahme auf.

Hinweis: Diese Schnittstelle hat keine Methoden, es ist nur ein [Standard]

1 Grundlegendste Sequenz Der Prozess der Serialisierung und Deserialisierung

Serialisierung und Deserialisierung werden alle an Objektobjekten durchgeführt. Hier ist ein einfacher Fall, um den Prozess der Objektserialisierung und -deserialisierung zu demonstrieren.

1. Erstellen Sie eine neue Student-Klasse (Testklasse)

Hinweis: Zur Durchführung von Serialisierungsvorgängen ist eine Klasse erforderlich, die die Serialisierungsschnittstelle implementiert! !

@SuppressWarnings("serial")
public class Student implements Serializable{
    private String stuno;//id
    private String stuna;//姓名
    private int stuage;//年龄
    public String getStuno() {
        return stuno;
    }
    public void setStuno(String stuno) {
        this.stuno = stuno;
    }
    public String getStuna() {
        return stuna;
    }
    public void setStuna(String stuna) {
        this.stuna = stuna;
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Student(String stuno, String stuna, int stuage) {
        super();
        this.stuno = stuno;
        this.stuna = stuna;
        this.stuage = stuage;
    }
    @Override
    public String toString() {
        return "Student [stuno=" + stuno + ", stuna=" + stuna + ", stuage=" + stuage + "]";
    }
    public int getStuage() {
        return stuage;
    }
    public void setStuage(int stuage) {
        this.stuage = stuage;
    }
}
Nach dem Login kopieren

2. Instanzen der Student-Klasse in Dateien serialisieren

Die grundlegenden Schritte sind wie folgt:

1) Geben Sie die Serialisierung an und Datei speichern

2), die ObjectOutputStream-Klasse erstellen

3), eine Student-Klasse erstellen

4), die writeObject-Methode zum Serialisieren verwenden

5 ), Verwenden Sie die Methode close(), um den Stream zu schließen

String file="demo/obj.dat";
        //对象的序列化
        ObjectOutputStream oos=new ObjectOutputStream(
                new FileOutputStream(file));
        //把Student对象保存起来,就是对象的序列化
        Student stu=new Student("01","mike",18);
        //使用writeObject方法序列化
        oos.writeObject(stu);
        oos.close();
Nach dem Login kopieren

Ergebnisse ausführen: Sie können sehen, dass die serialisierte Datei von obj.dat im Demoverzeichnis

3. Deserialisieren Sie die Datei und lesen Sie das Student-Klassenobjekt aus

Die grundlegenden Schritte sind wie folgt:

1), geben Sie die Datei an, die deserialisiert werden soll

2), Konstruieren Sie die ObjectInputStream-Klasse

3), verwenden Sie die readObject-Methode zum Deserialisieren

1), verwenden Sie die close-Methode, um den Stream zu schließen

String file="demo/obj.dat";
        ObjectInputStream ois =new ObjectInputStream(
                new FileInputStream(file));
        //使用readObject()方法序列化
        Student stu=(Student)ois.readObject();//强制类型转换
        System.out.println(stu);
        ois.close();
Nach dem Login kopieren
Betriebsergebnisse:

Hinweis: Beim Deserialisieren einer Datei sind die von der readObject-Methode herausgenommenen Objekte standardmäßig vom Typ Object und müssen in umgewandelt werden entsprechenden Typ.

2. Transienten- und ArrayList-Quellcode-Analyse

Im täglichen Programmierprozess wollen wir manchmal nicht alle Elemente Was soll ich zu diesem Zeitpunkt tun, wenn eine Klasse vom Compiler serialisiert werden soll?

Java stellt ein Schlüsselwort

transient bereit, um Elemente zu ändern, die nicht automatisch vom JVM serialisiert werden sollen. Lassen Sie uns dieses Schlüsselwort kurz erklären.

Transient-Schlüsselwort: Durch Transient geändertes Element. Dieses Element wird standardmäßig nicht von JVM serialisiert, Sie können die Serialisierung dieses Elements jedoch selbst abschließen.

Hinweis:

1) Wenn bei der zukünftigen Netzwerkprogrammierung bestimmte Elemente nicht übertragen werden müssen, können Sie vorübergehende Änderungen verwenden, um Datenverkehr zu sparen Effiziente Elementserialisierung zur Verbesserung der Leistung.

2) Sie können writeObject verwenden, um die Serialisierung dieses Elements selbst abzuschließen.

ArrayList wird mit dieser Methode optimiert. Object[] elementData, der Kerncontainer von ArrayList, verwendet vorübergehende Änderungen, die Serialisierung des elementData-Arrays ist jedoch in writeObject selbst implementiert. Nur gültige Elemente im Array werden serialisiert. readObject ist ähnlich.

--------------Der Weg, sich selbst zu serialisieren- -

Fügen Sie der zu serialisierenden Klasse zwei Methoden hinzu (

Diese beiden Methoden stammen aus dem ArrayList-Quellcode Zwei spezielle Methoden, die aus extrahiert wurden):

private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{
        s.defaultWriteObject();//把jvm能默认序列化的元素进行序列化操作
        s.writeInt(stuage);//自己完成被transient修饰的元素的序列化
    }
    private void readObject(java.io.ObjectInputStream s) throws java.io.IOException,ClassNotFoundException{
        s.defaultReadObject();//把jvm能默认反序列化的元素进行反序列化操作
        this.stuage=s.readInt();//自己完成stuage的反序列化操作
    }
Nach dem Login kopieren
Nach dem Hinzufügen dieser beiden Methoden können sogar durch Transient geänderte Elemente serialisiert und deserialisiert werden, da JVM diese beiden Methoden jetzt automatisch verwendet, um diese Aktion abzuschließen .

Hier gibt es eine weitere Frage: Warum müssen wir die Serialisierung und Deserialisierung immer noch manuell durchführen?

Dieses Problem muss anhand des Quellcodes von ArrayList analysiert werden:

Sie können das sehen ArrayList-Quellcode Der Zweck der Selbstserialisierung: Die unterste Ebene von ArrayList ist ein Array. Die Selbstserialisierung kann ungültige Elemente im Array filtern und nur gültige Elemente im Array serialisieren,

wodurch die Leistung verbessert wird .

Daher können wir während des eigentlichen Programmiervorgangs die Serialisierung nach Bedarf selbst abschließen, um die Leistung zu verbessern.

三、序列化中子父类构造函数问题

在类的序列化和反序列化中,如果存在子类和父类的关系时,序列化和反序列化的过程又是怎么样的呢?

这里我写一个测试类来测试子类和父类实现序列化和反序列化时构造函数的实现变化。

public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        String file="demo/foo.dat";
        ObjectOutputStream oos=new ObjectOutputStream(
                new FileOutputStream(file));
        Foo2 foo2 =new Foo2();
        oos.writeObject(foo2);
        oos.flush();
        oos.close();
    }

}
class Foo implements Serializable{
    public Foo(){
        System.out.println("foo");
    }
}
class Foo1 extends Foo{
    public Foo1(){
        System.out.println("foo1");
    }
    
}
class Foo2 extends Foo1{
    public Foo2(){
        System.out.println("foo2");
    }
}
Nach dem Login kopieren

运行结果:这是序列化时递归调用了父类的构造函数

接来下看看反序列化时,是否递归调用父类的构造函数。

ObjectInputStream ois=new ObjectInputStream(
new FileInputStream(file));
Foo2 foo2=(Foo2)ois.readObject();
ois.close();
Nach dem Login kopieren

运行结果:控制台没有任何输出。

那么这个结果是否证明反序列化过程中父类的构造函数就是始终不调用的呢?

然而不能证明!!

因为再看下面这个不同的测试例子:

class Bar {
    public Bar(){
        System.out.println("bar");
    }
}
class Bar1 extends Bar implements Serializable{
    public Bar1(){
        System.out.println("bar1");
    }
}
class Bar2 extends Bar1{
    public Bar2(){
        System.out.println("bar2");
    }
}
Nach dem Login kopieren

我们用这个例子来测试序列化和反序列化。

序列化结果:

反序列化结果:没实现序列化接口的父类被显示调用构造函数

【反序列化时】,向上递归调用构造函数会从【可序列化的一级父类结束】。即谁实现了可序列化(包括继承实现的),谁的构造函数就不会调用。

总结:

1)父类实现了serializable接口,子类继承就可序列化。

子类在反序列化时,父类实现了序列化接口,则不会递归调用其构造函数。

2)父类未实现serializable接口,子类自行实现可序列化

子类在反序列化时,父类没有实现序列化接口,则会递归调用其构造函数。

本文来自 java入门 栏目,欢迎学习!

Das obige ist der detaillierte Inhalt vonSerialisierung und Deserialisierung von Java-Objekten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:cnblogs.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage