Heim > Java > JavaErste Schritte > Hauptteil

So serialisieren Sie in Java

爱喝马黛茶的安东尼
Freigeben: 2019-11-12 17:44:30
Original
2445 Leute haben es durchsucht

So serialisieren Sie in Java

1. Serialisierung und Deserialisierung

Serialisierung: Bezieht sich auf die Java-Objektdaten im Heap-Speicher auf irgendeine Weise in einer Festplattendatei koppeln oder an andere Netzwerkknoten weitergeben (Netzwerkübertragung). Dieser Vorgang wird Serialisierung genannt und bezieht sich normalerweise auf den Vorgang der Konvertierung einer Datenstruktur oder eines Objekts in eine Binärdatei.

即将对象转化为二进制,用于保存,或者网络传输。
Nach dem Login kopieren

Deserialisierung: Der Prozess der Wiederherstellung der Objektdaten in der Festplattendatei oder der Objektdaten auf dem Netzwerkknoten im Java-Objektmodell. Das heißt, der Prozess der Konvertierung der während des Serialisierungsprozesses generierten Binärzeichenfolge in eine Datenstruktur oder ein Objekt

与序列化相反,将二进制转化成对象。
Nach dem Login kopieren

2 Die Rolle der Serialisierung

① Möchten Sie speichern? Speicher Wenn die Objekte in einer Datei oder Datenbank gespeichert werden;

② Wenn Sie Sockets zum Übertragen von Objekten über das Netzwerk verwenden möchten

③ Wenn Sie Objekte über RMI übertragen möchten; >

一些应用场景,涉及到将对象转化成二进制,序列化保证了能够成功读取到保存的对象。
Nach dem Login kopieren

3. Java-Serialisierungsimplementierung

Um die Serialisierung von Objekten zu realisieren, besteht die direkteste Operation darin, die serialisierbare Schnittstelle zu implementieren

Verwenden Sie Objekte im IO Stream Streams können Serialisierungsvorgänge implementieren, Objekte in Dateien speichern und sie dann auslesen.

Erstellen Sie zunächst ein Objekt und implementieren Sie die serialisierbare Schnittstelle:

import java.io.Serializable;
public class User implements Serializable{
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }
}
Nach dem Login kopieren

Verwenden Sie den Objektstrom, um eine Toolklasse zum Speichern und Lesen von Objekten zu schreiben:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializeUtil {
    // 保存对象,序列化
    public static void saveObject(Object object) throws Exception {
        ObjectOutputStream out = null;
        FileOutputStream fout = null;
        try {
            fout = new FileOutputStream("D:/1.txt");
            out = new ObjectOutputStream(fout);
            out.writeObject(object);
        } finally {
            fout.close();
            out.close();
        }
    }
    // 读取对象,反序列化
    public static Object readObject() throws Exception {
        ObjectInputStream in = null;
        FileInputStream fin = null;
        try {
            fin = new FileInputStream("D:/1.txt");
            in = new ObjectInputStream(fin);
            Object object = in.readObject();
            return object;
        } finally {
            fin.close();
            in.close();
        }
    }
}
Nach dem Login kopieren

Test:

public class Main {
    public static void main(String[] args) {
        User user = new User();
        user.setName("旭旭宝宝");
        user.setAge(33);
        // 保存
        try {
            SerializeUtil.saveObject(user);
        } catch (Exception e) {
            System.out.println("保存时异常:" + e.getMessage());
        }
        // 读取
        User userObject;
        try {
            userObject = (User) SerializeUtil.readObject();
            System.out.println(userObject);
        } catch (Exception e) {
            System.out.println("读取时异常:" + e.getMessage());
        }
    }
}
Nach dem Login kopieren

Testergebnisse:

So serialisieren Sie in Java

Hier haben wir das Objekt erfolgreich in einer Datei gespeichert und dann ausgelesen. Wenn wir die Serialisierungsschnittstelle zu diesem Zeitpunkt nicht implementieren, tritt eine Ausnahme auf. Wir brechen den implementierten Serialiable-Schnittstellencode ab:

public class User {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

und testen dann die Main-Methode:

So serialisieren Sie in Java

Sie können sehen, dass zu diesem Zeitpunkt ein Fehler gemeldet wird, verwenden Sie e.printStackTrace( ); Sehen Sie sich die Details der Ausnahme an:

So serialisieren Sie in Java

Da sie nicht serialisiert ist, kann sie nicht gespeichert und gelesen werden.

4. Die Rolle der Serialisierungs-ID

Wie Sie sehen können, fügen wir beim Serialisieren ein serialVersionUID-Feld hinzu, das die Serialisierungs-ID ist

private static final long serialVersionUID = 1L;
Nach dem Login kopieren

Diese Serialisierungs-ID spielt eine Schlüsselrolle, sie bestimmt, ob die Deserialisierung erfolgreich sein kann! Der Serialisierungsmechanismus von Java überprüft die Versionskonsistenz, indem er die serialVersionUID der Laufzeitklasse beurteilt. Während der Deserialisierung vergleicht die JVM die serialVersionUID im eingehenden Bytestrom mit der serialVersionUID in der lokalen Entitätsklasse Andernfalls wird eine Ausnahme inkonsistenter serialisierter Versionen gemeldet.

即序列化ID是为了保证成功进行反序列化
Nach dem Login kopieren

5. Standard-Serialisierungs-ID

Wenn wir in einer unserer Entitätsklassen nicht explizit eine Variable mit dem Namen „serialVersionUID“ vom Typ long definieren, wird der Java-Serialisierungsmechanismus verwendet generiert automatisch eine serialVersionUID basierend auf der kompilierten Klasse als Serialisierungsversionsvergleich. In diesem Fall generieren nur die durch dieselbe Kompilierung generierten Klassen dieselbe serialVersionUID. Wenn wir beispielsweise eine Klasse schreiben, müssen wir im Laufe der Zeit aufgrund geänderter Anforderungen weitere Felder zur lokalen Klasse hinzufügen. Zu diesem Zeitpunkt ist die SerialVersionUID während der Deserialisierung inkonsistent, was dazu führt, dass die Deserialisierung fehlschlägt. Wie kann man es also lösen? Fügen Sie einfach eine Variable „serialVersionUID“ zur lokalen Klasse hinzu, der Wert bleibt unverändert und Serialisierung und Deserialisierung können durchgeführt werden.

如果没有显示指定serialVersionUID,会自动生成一个。
只有同一次编译生成的class才会生成相同的serialVersionUID。
但是如果出现需求变动,Bean类发生改变,则会导致反序列化失败。为了不出现这类的问题,所以我们最好还是显式的指定一个
serialVersionUID。
Nach dem Login kopieren

6. Andere Probleme mit der Serialisierung

1 Statische Variablen werden nicht serialisiert (statisch, vorübergehend)

Wenn ein Das übergeordnete Element Die Klasse implementiert die Serialisierung und die Unterklasse implementiert die Serialisierung automatisch. Es ist nicht erforderlich, die Serializable-Schnittstelle explizit zu implementieren.

3. Wenn die Instanzvariablen eines Objekts auf andere Objekte verweisen, wird bei der Serialisierung des Objekts auch das referenzierte Objekt serialisiert.

子类序列化时:
如果父类没有实现Serializable接口,没有提供默认构造函数,那么子类的序列化会出错;
如果父类没有实现Serializable接口,提供了默认的构造函数,那么子类可以序列化,父类的成员变量不会被序列化。如果父类
实现了Serializable接口,则父类和子类都可以序列化。
Nach dem Login kopieren

7. Verwenden Sie ein effizienteres Serialisierungsframework – Protostuff

Tatsächlich ist die native Serialisierungsmethode von Java (durch Implementierung der Serialiable-Schnittstelle) nicht so effizient als Nicht die höchste.

Auf Github gibt es ein Projekt zur Analyse der Serialisierungseffizienz: https://github.com/eihay/jvm-serializers/wiki

So serialisieren Sie in Java

Sehen Sie sich das an Eines mit der besten Leistung ist Colfer, das von Google entwickelt wurde. Da Colfer jedoch zu schwierig zu verwenden ist, verwenden immer mehr Menschen das Serialisierungs-Framework ProtoStuff. Um das Framework anzuwenden, müssen zwei Bibliotheken (Core und Runtime) eingeführt werden.

①Github-Adresse: https://github.com/protostuff/protostuff

③Wenn Sie Maven verwenden, fügen Sie Abhängigkeiten hinzu:

<dependency>
  <groupId>io.protostuff</groupId>
  <artifactId>protostuff-core</artifactId>
  <version>1.5.9</version>
</dependency>
Nach dem Login kopieren
Nach dem Login kopieren
<dependency>
  <groupId>io.protostuff</groupId>
  <artifactId>protostuff-core</artifactId>
  <version>1.5.9</version>
</dependency>
Nach dem Login kopieren
Nach dem Login kopieren

Ändern Sie den Hauptcode

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtobufIOUtil;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
public class Main {
    public static void main(String[] args) {
        User user = new User();
        user.setName("旭旭宝宝");
        user.setAge(33);
        Schema<User> schema = RuntimeSchema.getSchema(User.class);
        // 保存对象,序列化,转化二进制数据
        LinkedBuffer buffer = LinkedBuffer.allocate(512);
        final byte[] protostuff;
        try {
            protostuff = ProtobufIOUtil.toByteArray(user, schema, buffer);
        } finally {
            buffer.clear();
        }
        // 读取对象,反序列化
        User userObject = schema.newMessage();
        ProtostuffIOUtil.mergeFrom(protostuff, userObject, schema);
        System.out.println(userObject);
    }
}
Nach dem Login kopieren

Benutzerklasse implementiert die serialisierbare Schnittstelle nicht

public class User {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

Testergebnisse:


So serialisieren Sie in Java

若要要整合Redis使用,也可以写成一个工具类:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtobufIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
public class SerializeUtil {
    private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>();
    @SuppressWarnings("unchecked")
    public static <T> byte[] serializer(T obj) {
        Class<T> clazz = (Class<T>) obj.getClass();
        Schema<T> schema = getSchema(clazz);
        return ProtobufIOUtil.toByteArray(obj, schema, LinkedBuffer.allocate(256));
    }
    public static <T> T deSerializer(byte[] bytes, Class<T> clazz) {
        T message;
        try {
            message = clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        Schema<T> schema = getSchema(clazz);
        ProtobufIOUtil.mergeFrom(bytes, message, schema);
        return message;
    }
    @SuppressWarnings("unchecked")
    public static <T> Schema<T> getSchema(Class<T> clazz) {
        Schema<T> schema = (Schema<T>) cachedSchema.get(clazz);
        if (schema == null) {
            schema = RuntimeSchema.createFrom(clazz);
            if (schema != null) {
                cachedSchema.put(clazz, schema);
            }
        }
        return schema;
    }
}
Nach dem Login kopieren

这样即使我们的User类就不用再实现Serialiable接口了,同样可以进行序列化,效率也更高。

php中文网,大量的免费Java入门教程,欢迎在线学习!

Das obige ist der detaillierte Inhalt vonSo serialisieren Sie in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
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