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.
即将对象转化为二进制,用于保存,或者网络传输。
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
与序列化相反,将二进制转化成对象。
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; >
一些应用场景,涉及到将对象转化成二进制,序列化保证了能够成功读取到保存的对象。
3. Java-Serialisierungsimplementierung
Um die Serialisierung von Objekten zu realisieren, besteht die direkteste Operation darin, die serialisierbare Schnittstelle zu implementierenVerwenden 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 + "]"; } }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(); } } }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()); } } }Testergebnisse: 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 + "]"; } }und testen dann die Main-Methode: Sie können sehen, dass zu diesem Zeitpunkt ein Fehler gemeldet wird, verwenden Sie e.printStackTrace( ); Sehen Sie sich die Details der Ausnahme an: 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 istprivate static final long serialVersionUID = 1L;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是为了保证成功进行反序列化
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。
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接口,则父类和子类都可以序列化。
7. Verwenden Sie ein effizienteres Serialisierungsframework – Protostuff
<dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-core</artifactId> <version>1.5.9</version> </dependency>
<dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-core</artifactId> <version>1.5.9</version> </dependency>Ä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); } }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 + "]"; } }Testergebnisse:
若要要整合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; } }
这样即使我们的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!