ホームページ >Java >&#&チュートリアル >Java の基本 - シリアル化
一、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. Serializable インターフェースと Externalizable インターフェース (以下は基本的な知識の記録です)
1.Serializable
ObjectOutputStream は、Serializable インターフェイスを持つクラスのオブジェクトのみをシリアル化できます。
デフォルトでは、ObjectOutputStream はデフォルトの方法でシリアル化されます。このシリアル化メソッドは、オブジェクトの非一時的 (一時的、非永続的) インスタンス変数のみをシリアル化しますが、オブジェクトの一時的なインスタンス変数もシリアル化しません。シリーズ化されていない。
ObjectOutputStream がデフォルトの方法で逆シリアル化される場合、次の特性があります:
1) メモリ内でオブジェクトが属するクラスがロードされていない場合、このクラスが最初にロードされて初期化されます。対応するクラスファイルがクラスパスに存在しない場合、ClassNotFoundException がスローされます。
2) 逆シリアル化中にクラスのコンストラクター メソッドは呼び出されません。
ユーザーがクラスのシリアル化方法を制御したい場合は、次の形式の writeObject() および readObject() メソッドをシリアル化可能なクラスで提供できます。
private void writeObject(java.io.ObjectOutputStream out) は IOException をスローします
private void readObject(java.io.ObjectInputStream in) は IOException、ClassNotFoundException をスローします;
ObjectOutputStream が Person オブジェクトをシリアル化するとき、オブジェクトに writeObject() メソッドがある場合はこのメソッドが実行され、そうでない場合はデフォルトでシリアル化されます。オブジェクトの writeObjectt() メソッドで、最初に ObjectOutputStream のdefaultWriteObject() メソッドを呼び出すことができます。これにより、オブジェクト出力ストリームが最初にデフォルトのシリアル化操作を実行します。逆シリアル化についても同じことが言えますが、今回は、defaultReadObject() メソッドが呼び出されます。
一部のオブジェクトには、一般公開すべきではない機密情報が含まれています。デフォルトの方法でシリアル化されている場合、シリアル化されたデータはネットワーク経由で送信されるときに犯罪者によって盗まれる可能性があります。このタイプの情報については、暗号化してからシリアル化することができ、逆シリアル化中に復号化して元の情報に復元する必要があります。
デフォルトのシリアル化メソッドはオブジェクト グラフ全体をシリアル化するため、オブジェクト グラフを再帰的に走査する必要があります。オブジェクト グラフが複雑な場合、再帰的な走査操作は多くのスペースと時間を消費し、その内部データ構造は双方向リストになります。
アプリケーション中に、一部のメンバー変数を一時型 (private transient int age) に変更すると、スペースと時間が節約され、シリアル化のパフォーマンスが向上します。
2.外部化可能
Serializable インターフェイスから継承。クラスが Externalizable インターフェイスを実装している場合、このクラスは独自のシリアル化動作を完全に制御します。 Externalizable インターフェースは 2 つのメソッドを宣言します:
public void writeExternal(ObjectOutput out) は IOException をスローします
public void readExternal(ObjectInput in) は IOException、ClassNotFoundException をスローします
前者はシリアル化操作を担当し、後者は逆シリアル化操作を担当します。
Externalizable インターフェイスを実装するクラスのオブジェクトを逆シリアル化する場合、 /* は最初にパラメーターなしでクラスのコンストラクターを呼び出します。これは、デフォルトの逆シリアル化メソッド */
とは異なります。クラスのパラメータを指定せずにコンストラクターを削除した場合、またはコンストラクターのアクセス権限をプライベート、デフォルト、または保護レベルに設定した場合、
java.io.InvalidException: 有効なコンストラクター例外がスローされます。
3.serialVersionUID
シリアル化可能クラスのさまざまなバージョンのシリアル化互換性。Serializable インターフェイスを実装するクラスには、シリアル化バージョン識別子を表す静的変数があります。 プライベート静的最終ロングserialVersionUID;
上記のserialVersionUID値は、クラスの内部詳細に基づいてJavaランタイム環境によって自動的に生成されます。クラスのソースコードを変更して再コンパイルすると、新しく生成されたクラスファイルのserialVersionUIDの値も変わる可能性があります。
クラスのserialVersionUIDのデフォルト値は、Javaコンパイラの実装に完全に依存し、異なるJavaコンパイラでコンパイルされた同じクラスの場合、異なるserialVersionUIDになる場合もあれば、同じになる場合もあります。 SerialVersionUID の独立性と確実性を向上させるために、シリアル化可能なクラスで SerialVersionUID を明示的に定義し、それに明示的な値を与えることを強くお勧めします。 SerialVersionUID を明示的に定義すると、次の 2 つの用途があります:
1) 場合によっては、クラスの異なるバージョンがシリアル化と互換性があることが望まれるため、クラスの異なるバージョンが同じ SerialVersionUID を持つようにする必要があります。
2) 場合によっては、クラスの異なるバージョンにシリアル化互換性を持たせたくない場合があるため、クラスの異なるバージョンが異なる SerialVersionUID を持つようにする必要があります以上がJava の基本 - シリアル化の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。