[予約]のJavaシリアライゼーションおよびデシリアライゼーション

[予約]のJavaシリアライゼーションおよびデシリアライゼーション

出典:https://www.cnblogs.com/anitinaj/p/9253921.html

より基本的な知識として、Javaのシリアライズとデシリアライズは、その後、あなたはシリアル化および基礎となるのデシリアライズは、それを達成することであるかについて話すことができますか?

まず、基本的な概念

1.シリアライズとデシリアライズとは何ですか

(は1)は、Java直列化は、Javaは、バイトの配列を処理するオブジェクトを変換して、JavaバイトシーケンスをデシリアライズするためにJavaオブジェクトの回収プロセスを指す指します。

(2)連載:オブジェクトのシリアライズ主な用途は、配達時にオブジェクトを保存すると、オブジェクトの整合性と配信を確保することです。シリアル化は、伝送のために順序付けられたバイトストリームにオブジェクトであるか、またはネットワーク上のローカルファイルに保存されています。直列化されたバイトストリームはJavaオブジェクトと関連する記述情報の状態を保存します。直列化機構の中心的な役割は、オブジェクトの状態の保存と再構築です。

(3)デシリアライズ:ターゲットクライアントシリアライズバイトストリームまたはネットワークからファイル、再構成されたオブジェクトによってデシリアライズオブジェクトおよび説明の状態に応じて格納されたバイト・ストリームを取得します。

(4)本質的には、物理​​的オブジェクトの配列は、特定のフォーマットに従って秩序状態バイトストリームに書き込まれ、デシリアライズは、オブジェクトの状態を復元するように命じたバイトストリームから再構成されたオブジェクトです。

2.なぜシリアライズとデシリアライズが必要なのか

我々は2つのプロセスがリモートで通信するとき、あなたはテキスト、画像、オーディオ、ビデオなどを含むデータの相互様々なタイプを、送信することができ、これらのデータは、ネットワークを介して送信バイナリシーケンスの形態であることを知っています。

だから、2つのJavaは、プロセス間のオブジェクト転送を達成する能力を通信するために処理するとき?答えはイエスです!どのようにそれを行うには?これは、Javaのシリアライゼーションとのデシリアライズが必要です!

換言すれば、一方では、Javaオブジェクトを変換するセンダ必要はバイトのシーケンスであり、そして、ネットワーク上に送信、他の手は、受け手は、バイトシーケンスからJavaオブジェクトを回復する必要があります。

我々は、Javaのシリアライズとデシリアライズする理由を明確にする必要があるとき、私たちは自然のJava直列化のメリットをお勧めします。まず、その利点は、データを永続達成するために、データが永続的にディスク(通常はファイルに格納されている)へのシリアライゼーションを保存することができ、そして第二に、遠隔通信の配列、すなわちを使用することは、ネットワークバイト上のオブジェクトを転送しますシーケンス。

次のように一般的には、要約することができます。

ローカルファイルまたはデータベース内のバイトの永続オブジェクト記憶標的配列保存(1)、
(2)オブジェクトのバイトストリームにおけるネットワーク内の送信及び受信のためにシリアライズすることにより、
(3)の配列オブジェクトを渡すプロセス間。

3、直列化アルゴリズムは、一般的に次のことを行うための手順に従います:

(1)関連データ出力クラス・オブジェクト・インスタンス・メタデータ。
再帰ないスーパークラスまで出力の(2)の説明スーパー。
クラスメタデータが終了した後、(3)は、実際のデータ値のスーパークラスから最上位オブジェクト・インスタンスの出力を開始し始めます。
再帰的なインスタンストップダウンからデータ(4)出力

二つは、Javaは、シリアライズとデシリアライズを実装する方法

1、JDKのクラスライブラリのシリアライズとデシリアライズAPI

(1)java.io.ObjectOutputStreamの:出力ストリームを表すオブジェクト。

それのwriteObject(オブジェクトobj)メソッドは、オブジェクトOBJパラメーターが指定されたターゲット出力ストリームに書き込まれたバイトの結果の配列をシリアライズすることができます。

(2)java.io.ObjectInputStream:入力ストリームを表すオブジェクト。

それのreadObject()メソッドは、次に、それらがデシリアライズする対象となる入力ストリームのバイトのソースシーケンスを読み出し、リターン。

2、シリアル化の要件を実装

唯一のオブジェクトクラスインタフェース直列化または外部化を達成することによってシリアライズ、または例外をスローすることができます!

Javaオブジェクトのシリアル化および逆シリアル化プロセスを実現するための3、

シリアル化するためにあるUserクラスを、と仮定すると、あなたは、次の3つの方法を持つことができます。

Userクラスが実装する直列化インターフェースは、次のように直列化および非直列化することができる場合にのみ、(1)

デフォルトの直列化、非transientインスタンス変数ユーザオブジェクトのシリアル化を使用してObjectOutputStream。
ObjcetInputStreamデフォルトの直列化復元モードでは、ユーザオブジェクトへの非transientインスタンス変数は、デシリアライズします。

(2)場合のみ、Userクラスが実装するシリアライズインターフェース、また定義のreadObject(ObjectInputStreamの中)およびwriteObject(ObjectOutputSteamアウト)、次いで、以下のように直列化および非直列化。

ObjectOutputStreamのは、ユーザーオブジェクトのwriteObject(ObjectOutputStreamのうち)直列化のための方法を呼び出します。
ObjectInputStreamのは、ユーザーオブジェクトが逆シリアル化メソッドのreadObject(中のObjectInputStream)を呼び出します。

(3)クラスが実装ExternalnalizableユーザインタフェースとユーザクラスがのreadExternal(れるObjectInputで)とwriteExternalメソッド(するObjectOutputアウト)方式、方法以下のシリアライゼーションおよびデシリアライゼーションを実装する必要がある場合。

プロセスシーケンスのObjectOutputStreamの呼び出し元ユーザーオブジェクトのwriteExternal(のObjectOutput出))。
ObjectInputStreamのは、ユーザオブジェクトのreadExternal(れるObjectInputで)逆シリアル化メソッドを呼び出します。

4、ステップのJDKライブラリシーケンス

それは、このようなファイル出力ストリームとしてターゲット出力ストリームをパッケージングする他の種類の、することができ、オブジェクトを作成するために、出力ストリーム:ステップ:

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\object.out"));

ステップ2:経由のwriteObject()メソッドライト対象オブジェクト出力ストリーム

oos.writeObject(new User("xuliugen", "123456", "male"));

5、JDKのクラスライブラリ直列化復元ステップ

そのようなファイルの入力ストリームとして入力ストリームの他のタイプのパッケージとすることができる、オブジェクトを作成するために入力ストリーム:手順:

ObjectInputStream ois= new ObjectInputStream(new FileInputStream("object.out"));

ステップ2:オブジェクト出力ストリームのreadObject()メソッドは、オブジェクトを読み出します。

User user = (User) ois.readObject();

説明:逆シリアル化が完了し、正しくデータを読み取るために、シーケンシャル書き込み、読み出し対象のシーケンスフロー入力と一致するオブジェクトから対象オブジェクトへの出力ストリームを保証しなければなりません。

図6に示すように、例示的なシリアライゼーションおよびデシリアライゼーション

より良い次のように簡単な例を挙げ、Javaおよび直列化復元の手順を理解するために:

コードをコピー

1 public class SerialDemo {
2  
3  
4  
5 public static void main(String[] args) throws IOException, ClassNotFoundException {
6  
7 //序列化
8  
9 FileOutputStream fos = new FileOutputStream("object.out");
10  
11 ObjectOutputStream oos = new ObjectOutputStream(fos);
12  
13 User user1 = new User("xuliugen", "123456", "male");
14  
15 oos.writeObject(user1);
16  
17 oos.flush();
18  
19 oos.close();
20  
21 //反序列化
22  
23 FileInputStream fis = new FileInputStream("object.out");
24  
25 ObjectInputStream ois = new ObjectInputStream(fis);
26  
27 User user2 = (User) ois.readObject();
28  
29 System.out.println(user2.getUserName()+ " " +
30  
31 user2.getPassword() + " " + user2.getSex());
32  
33 //反序列化的输出结果为:xuliugen 123456 male
34  
35 }
36  
37 }
38  
39  
40  
41 public class User implements Serializable {
42  
43 private String userName;
44  
45 private String password;
46  
47 private String sex;
48  
49 //全参构造方法、get和set方法省略
50  
51 }

コードをコピー

(ウルトラエディットオープンを使用して)次の書類object.out:

書き込み絵は、ここで説明しました

注:0000000H-000000c0h行番号上図; 0-fは列を示し、テキストの行の後ろには、このラインを説明進表し、上記バイトコード表現注目コンテンツは、関連情報を制御することができます、ここでは議論しないで表される各文字の意味についての記事を読みます!

私たちは、Javaコードがコンパイルされた後、それぞれの文字が特定の意味を表すの.classファイルが好き。シリアライズとデシリアライズのプロセスが発生し、言った文字の解析のプロセスです!

シリアル化アイコン:

書き込み絵は、ここで説明しました

示すには、逆シリアル化:

書き込み絵は、ここで説明しました

第三に、関連の考慮事項

図1に示すように、オブジェクトの状態のみのシーケンスを保存する際に、関係なく、メソッドオブジェクトの。

図2に示すように、親クラスが実装シリアライズ、自動的にシリアライズサブクラス、明示的な道具シリアライズ。

図3に示すように、オブジェクト参照他のオブジェクト、参照されるオブジェクトをシリアル化するオブジェクトの配列のインスタンス変数。

:4、いないすべてのオブジェクトは、次のような多くの理由のために、なぜしないようにと、シリアライズすることができます

  • このような送信処理のシーケンスでは、など、ファイルへの書き込み、またはRMIの交通機関として転送されるオブジェクトのオブジェクトは、プライベート、パブリック、およびその他のフィールドを持っているなどのセキュリティ上の理由から、、、、このドメインの民間およびその他の目的のためにあります保護されていません。
  • 送信または保存され、そのようなあなたがシリアライズできるかどうソケット、スレッドクラス、などのリソースの割り当ては、それらへのリソースの再割り当てすることはできません理由は、しかし、達成する必要はありません。

静的データメンバと過渡型として宣言5は、シリアライズすることはできません。オブジェクトのクラス、過渡的な一時的なデータの代表の静的な状態の代表ので。

図6に示すように、バージョン番号がシーケンスに関連付けられた各クラスのserialVersionUIDと呼ばれることも、デシリアライゼーションシリアル化オブジェクトのシーケンス番号は、オブジェクトの送信者と受信者を確認し、ロードされた直列化ランタイムでありますシリアル化されたクラスとの互換性。それは明確な価値を与えるよう。明示的に定義されたserialVersionUIDのは2つの目的があります。

  • いくつかのケースでは、互換性の配列の所望のクラスの異なるバージョンが、クラスの異なるバージョンが同じserialVersionUIDのを持っていることを確認する必要があります。
  • いくつかのケースでは、クラスの異なるバージョンは、互換性のシリアライズしたいので、クラスの異なるバージョンが異なるserialVersionUIDのを持っていることを確認する必要はありません。

7、Javaの基礎クラスはすでに、このような文字列、ベクトルなどというように、Serializableインタフェースの多くを達成しています。しかし、Serializableインタフェースを実装していないいくつかあります。

オブジェクトのメンバ変数がオブジェクトである場合は8、そのオブジェクトのデータメンバが保存されます!これは、深いコピーを解決することができます直列化のための重要な理由です。

場合は、クラスのすべてのデータメンバの順序は、シリアライズ静的または宣言を除く過渡メンバーでなければなりません。一過性のtell JVM引数として宣言された変数は、私たちは、直列化のために責任を負うことになります。データメンバーが一時宣言した後、シリアル化プロセスが、バイトストリームオブジェクトに追加することはできません、データは一時データメンバから送信されていません。データバックをデシリアライズするとき(それは、クラス定義の一部であるため)、データメンバーを再構成するが、データメンバーは、ストリームにデータを書き込みませんので、すべてのデータが含まれていません。覚えておいて、オブジェクトは、ストリームの静的または一時的に連載されていません。私たちのクラスは、これらのデータメンバを処理するためのwriteObject()とreadObject()メソッドを使用します。writeObject()とreadObject()メソッドを使用して、だけでなく、順次メンバーに書き込まれたデータを読み取るために注意を払うとき

これらの問題それ、どのように我々はそれをシリアライズし、デシリアライズしますか?

私たちはどのように、個別に対処する必要があり、多分変数の型を持っているという単純な、?それはあなたのクラスでこのような変数の出現をする方法の両方を高めることです

コードをコピー

1 private void writeObject(java.io.ObjectOutputStream out) throws IOException
2  
3 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
4 而对应于我们的类中添加的方法就是
5 
6  
7 public class SerialTest extends parent implements Serializable {
8  
9 //省略
10  
11 private void writeObject(ObjectOutputStream out) throws IOException {
12  
13 out.defaultWriteObject();
14  
15 out.writeInt(this.testStatic);
16  
17 out.writeInt(this.testTransient);
18  
19 }
20  
21 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
22  
23 in.defaultReadObject();
24  
25 this.testStatic = in.readInt();
26  
27 this.testTransient = in.readInt();
28  
29 }
30  
31  
32  
33 }

コードをコピー

ときにObjectOutputStream A SerialTestオブジェクトをシリアル化するオブジェクトはのwriteObject()メソッドを持っている場合、それはそうでない場合は、デフォルトのシリアル化によって、このメソッドを実装します。writeObjecttにオブジェクト()メソッドは、最初ObjectOutputStreamのdefaultWriteObject()メソッド、オブジェクトはデフォルトのシリアル化操作を実行するように出力ストリームを呼び出すことができます。同様にデシリアライズがケースから引き出すことができるが、これはは、defaultReadObject()メソッドです。

ObjectOutputStream.defaultWriteObject() 非定常(静的)の現在のクラスとこのストリームの非トランジェントフィールド(過渡的)。

ObjectInputStream.defaultReadObject() ストリームは、現在のクラスの非staticおよび非transientフィールドから読み取ります。

外部化役割

直列化可能クラスを達成するため、時間の順序で、非静的(スタティック)と非transientフィールド(過渡)のすべてが自動的にシリアライズされるために、いくつかの特別な要件がある場合は、我々はフィールドがあることをしている、完全に手動制御することができますシリアライズしませんシリアライズ、。私たちの手の中に自分の人生と死の電源休み。方法は?今回は外部化クラスについて話すべきです。

限り外部化は、このクラスを達成するため、およびレプリケーションなど

readExternal(ObjectInput in) throws IOException,CalssNotFoundException

writeExternal(ObjectOutput out) throws IOException,CalssNotFoundException

readExternal(れるObjectInputで)であることができるのIOException、CalssNotFoundException処理をスローし、そして内のオブジェクトから読み取られたデータを決定することができます。

writeExternalメソッド(アウトされたObjectOutput)はIOExceptionが、CalssNotFoundExceptionプロセスは、データが出て行くことを書くために何を決定することができますがスローされます。

自動的にObjectInputStream.readObject();内のメソッド多分1意志ObjectOutputStream.writeObject(オブジェクト)。


参考記事:

1、https://zhidao.baidu.com/question/688891250408618484.html
2、https://blog.csdn.net/morethinkmoretry/article/details/5929345
3、https://www.jianshu.com/p/ edcf7bd2c085
4、https://blog.csdn.net/xiaocaidexuexibiji/article/details/22692097

おすすめ

転載: www.cnblogs.com/jiading/p/12013449.html