Heim  >  Artikel  >  Java  >  Java-Grundlagen – Serialisierung

Java-Grundlagen – Serialisierung

PHP中文网
PHP中文网Original
2017-07-09 18:13:101459Durchsuche

一、java中的序列化

当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。把Java对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为Java对象的过程称为对象的反序列化。

对象的序列化主要有两种用途:

1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

2) 在网络上传送对象的字节序列。

JDK类库中的序列化API

ObjectOutputStream //代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。

ObjectInputStream  //代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

只有实现了Serializable和Externalizable接口的类的对象才能被序列化。

Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式
对象序列化包括如下步骤:

1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;

2) 通过对象输出流的writeObject()方法写对象。

对象反序列化的步骤如下:

1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;

2) 通过对象输入流的readObject()方法读取对象。

<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span><span style="color: #000000"> Test3 {
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> main(String[] args) <span style="color: #0000ff">throws</span><span style="color: #000000">  IOException, ClassNotFoundException {
                </span><span style="color: #008000">/*</span><span style="color: #008000">ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("c:\\1.obj"));
                
                //序列化对象
                Person p=new Person(777,"我们要好好学习");
                
                out.writeObject("我是String类型的数据");  //写入String类型
                out.writeObject(new Date()); //写入日期类型
                out.writeObject(p); //写入自定义类型
                out.writeInt(123); //定入基本数据类型
                
                out.close();</span><span style="color: #008000">*/</span>
                
                <span style="color: #008000">//</span><span style="color: #008000">反序列化对象</span>
                ObjectInputStream in=<span style="color: #0000ff">new</span> ObjectInputStream(<span style="color: #0000ff">new</span> FileInputStream("c:\\1.obj"<span style="color: #000000">));
                
                System.out.println(</span>"obj1="+<span style="color: #000000">in.readObject());  
                System.out.println(</span>"obj2="+<span style="color: #000000">in.readObject());  
                System.out.println(</span>"obj3="+<span style="color: #000000">in.readObject());  
                System.out.println(</span>"obj4="+<span style="color: #000000">in.readInt());     
                
                in.close();
            }
        }</span>
<span style="color: #008000">//</span><span style="color: #008000">Serializable 是个空接口</span>
        <span style="color: #0000ff">class</span> Person <span style="color: #0000ff">implements</span><span style="color: #000000"> Serializable{
            </span><span style="color: #0000ff">int</span><span style="color: #000000"> age;
            String name;
            
            Person(</span><span style="color: #0000ff">int</span><span style="color: #000000"> age,String name){
                </span><span style="color: #0000ff">this</span>.age=<span style="color: #000000">age;
                </span><span style="color: #0000ff">this</span>.name=<span style="color: #000000">name;
            }
            
            </span><span style="color: #0000ff">public</span><span style="color: #000000"> String toString(){
                </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">this</span>.name+":"+<span style="color: #0000ff">this</span><span style="color: #000000">.age;
            }
        }</span>

2. Serialisierbare Schnittstelle und Externalisierbare Schnittstelle (das Folgende ist der grundlegende Wissensdatensatz)
1.Serialisierbar

ObjectOutputStream kann nur Objekte von Klassen mit der Serializable-Schnittstelle serialisieren.

ObjectOutputStream wird standardmäßig auf die Standardmethode serialisiert. Diese Serialisierungsmethode serialisiert nur die nicht-transienten (transienten, nicht-persistenten) Instanzvariablen des Objekts, nicht jedoch die transienten Instanzvariablen (statisch). Variablen werden nicht serialisiert.

Wenn ObjectOutputStream standardmäßig deserialisiert wird, weist es die folgenden Eigenschaften auf:

1) Wenn die Klasse, zu der das Objekt im Speicher gehört, nicht geladen wurde, wird diese Klasse zuerst geladen und initialisiert. Wenn die entsprechende Klassendatei nicht im Klassenpfad vorhanden ist, wird ClassNotFoundException

ausgelöst

2) Während der Deserialisierung wird keine Konstruktormethode der Klasse aufgerufen.

Wenn der Benutzer steuern möchte, wie die Klasse serialisiert wird, kann die folgende Form der Methoden writeObject() und readObject() in der serialisierbaren Klasse bereitgestellt werden.

private void writeObject(java.io.ObjectOutputStream out) löst eine IOException aus

private void readObject(java.io.ObjectInputStream in) löst IOException, ClassNotFoundException;

aus

Wenn ObjectOutputStream ein Person-Objekt serialisiert und das Objekt über eine writeObject()-Methode verfügt, wird diese Methode ausgeführt, andernfalls wird sie standardmäßig serialisiert. In der writeObjectt()-Methode des Objekts können Sie zunächst die defaultWriteObject()-Methode von ObjectOutputStream aufrufen, sodass der Objektausgabestream zunächst den Standardserialisierungsvorgang ausführt. Das Gleiche gilt für die Deserialisierung, dieses Mal wird jedoch die Methode defaultReadObject() aufgerufen.

Einige Objekte enthalten sensible Informationen, die nicht der Öffentlichkeit zugänglich gemacht werden sollten. Wenn sie standardmäßig serialisiert sind, können ihre serialisierten Daten bei der Übertragung über das Netzwerk von Kriminellen gestohlen werden. Für diese Art von Informationen können sie verschlüsselt und dann serialisiert werden. Bei der Deserialisierung müssen sie entschlüsselt und auf die ursprünglichen Informationen zurückgesetzt werden.

Die Standard-Serialisierungsmethode serialisiert das gesamte Objektdiagramm, was eine rekursive Durchquerung des Objektdiagramms erfordert. Wenn der Objektgraph komplex ist, nehmen rekursive Durchlaufoperationen viel Platz und Zeit in Anspruch, und seine interne Datenstruktur ist eine bidirektionale Liste.

Wenn während der Anwendung einige Mitgliedsvariablen in den transienten Typ (private transient int age) geändert werden, spart dies Platz und Zeit und verbessert die Leistung der Serialisierung.

2.Externalisierbar

Erbt von der Serializable-Schnittstelle. Wenn eine Klasse die Externalizable-Schnittstelle implementiert, steuert diese Klasse ihr eigenes Serialisierungsverhalten vollständig. Die Externalizable-Schnittstelle deklariert zwei Methoden:

public void writeExternal(ObjectOutput out) löst eine IOException aus

public void readExternal(ObjectInput in) löst IOException , ClassNotFoundException

aus

Ersterer ist für Serialisierungsvorgänge verantwortlich, letzterer für Deserialisierungsvorgänge.

Beim Deserialisieren eines Objekts einer Klasse, die die Externalizable-Schnittstelle implementiert, ruft /* zunächst den Konstruktor der Klasse ohne Parameter auf, was sich von der Standard-Deserialisierungsmethode */

unterscheidet

Wenn Sie den Konstruktor ohne Parameter der Klasse löschen oder die Zugriffsberechtigung des Konstruktors auf private, Standard- oder geschützte Ebene setzen,

Wird java.io.InvalidException auslösen: keine gültige Konstruktorausnahme.

3.serialVersionUID

EsSerialisierungskompatibilität verschiedener Versionen serialisierbarer Klassen. Jede Klasse, die die Serializable-Schnittstelle implementiert, verfügt über eine statische Variable, die die Serialisierungsversionskennung darstellt:

private static final long serialVersionUID;

Der obige serialVersionUID-Wert wird automatisch von der Java-Laufzeitumgebung basierend auf den internen Details der Klasse generiert. Wenn der Quellcode der Klasse geändert und anschließend neu kompiliert wird, kann sich auch der Wert von serialVersionUID der neu generierten Klassendatei ändern.

Der Standardwert der serialVersionUID einer Klasse hängt vollständig von der Implementierung des Java-Compilers ab. Wenn dieselbe Klasse mit verschiedenen Java-Compilern kompiliert wird, kann dies zu einer unterschiedlichen serialVersionUID führen oder gleich sein. Um die Unabhängigkeit und Sicherheit von serialVersionUID zu verbessern, wird dringend empfohlen, serialVersionUID explizit in einer serialisierbaren Klasse zu definieren und ihr einen expliziten Wert zu geben. Die explizite Definition von serialVersionUID hat zwei Verwendungszwecke:

1) In einigen Fällen hofft man, dass verschiedene Versionen einer Klasse mit der Serialisierung kompatibel sind. Daher muss sichergestellt werden, dass verschiedene Versionen einer Klasse dieselbe serialVersionUID haben

2) In manchen Fällen möchten Sie nicht, dass verschiedene Versionen einer Klasse mit der Serialisierung kompatibel sind. Daher müssen Sie sicherstellen, dass verschiedene Versionen der Klasse unterschiedliche serialVersionUIDs haben

Das obige ist der detaillierte Inhalt vonJava-Grundlagen – Serialisierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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