このプロセスは、ネットワークを介して実装することもできます。ネットワークは、まずWindowsマシンにオブジェクトを作成し、シリアル化してからネットワーク上のUNIXマシンに送信してから、正確に再組み立てできます。 RMI、Socket、JMS、およびEJBのそれぞれがJavaオブジェクトを渡すことができるのはなぜですか?
Javaオブジェクトのシリアル化メカニズムには、一般に2つの用途があります。
Java Javabeans:Beanステータス情報は、設計時に構成されています。オブジェクトの状態を読んで、オブジェクトを再構築し、プログラム状態を復元します。
RMIは、ネットワークのようにリモートマシンのオブジェクトを動作させることができます。
クラスにjava.io.serializableインターフェイスを実装することにより、クラスをシリアル化できます。このインターフェイスは、メーカーインターフェイスです。つまり、クラスがそれを実装するためには、インターフェイスはどのメソッドを実装する必要もありません。主に、オブジェクトをシリアル化する必要があることをJava仮想マシン(JVM)に通知するために使用されます。
これを明確にする必要があるいくつかのポイントがあります。
すべてのクラスをシリアル化することはできません。
Javaには、文字列、ベクトルなどのシリアル化可能なインターフェイスを実装した多くの基本クラスがあります。しかし、たとえば、ハッシュテーブルはシリアル化可能なインターフェイスを実装しません。
ストリームにオブジェクトを読み書きするための2つの主要なクラスがあります。ObjectOutputStreamとObjectInputStream.ObjectOutputStreamは、出力ストリームにオブジェクトを書き込むために使用されるWriteObjectメソッドを提供し、ObjectInputStreamは、入力ストリームからオブジェクトを読み取るためのReadObjectメソッドを提供します。これらのメソッドを使用したオブジェクトは、シリアル化されている必要があります。つまり、シリアル化可能なインターフェイスが実装されている必要があります。ハッシュテーブルオブジェクトをオブジェクトに書きたい場合は、例外が表示されます。
シリアル化のプロセスは、バイトストリームからオブジェクトを書き込み、オブジェクトを読み取ることです。オブジェクトの状態をバイトストリームに変換した後、java.ioパッケージのさまざまなバイトストリームクラスを使用してファイルに保存したり、別のスレッドにパイプしたり、ネットワーク接続を介して別のホストにオブジェクトデータを送信したりできます。オブジェクトのシリアル化関数は非常にシンプルで強力であり、RMI、Socket、JMS、およびEJBで使用されています。オブジェクトのシリアル化の問題は、ネットワークプログラミングで最もエキサイティングなトピックではありませんが、非常に重要であり、多くの実際的な重要性を持っています。
オブジェクトシリアル化は、分散オブジェクトを実装できます。次のような主なアプリケーション:RMIは、オブジェクトのシリアル化を使用して、ローカルマシンでオブジェクトを実行するときと同じように、リモートホストでサービスを実行します。
Javaオブジェクトのシリアル化は、1つのオブジェクトのデータを保持するだけでなく、オブジェクトによって参照される各オブジェクトのデータを再帰的に保存します。オブジェクト全体の階層は、バイトストリームに書き込まれたり、ファイルに保存されたり、ネットワーク接続に渡されたりできます。オブジェクトのシリアル化を使用して、オブジェクトの「ディープコピー」、つまりオブジェクト自体と参照されるオブジェクト自体をコピーすることができます。オブジェクトをシリアル化すると、オブジェクトのシーケンス全体が生じる可能性があります。
Javaのシリアル化は比較的単純であり、通常、オブジェクト状態を保存および復元するためにカスタマイズされたコードを作成する必要はありません。 java.io.serializableインターフェイスを実装するクラスオブジェクトは、クラスにコードを追加せずにバイトストリームから変換または回復することができます。まれにのみ、オブジェクト状態を保存または復元するために必要なカスタムコードが必要です。ここに注意してください:すべてのクラスをシリアル化することはできません。たとえば、いくつかのクラスをシリアル化することはできません。
シリアル化メカニズム:
シリアル化は、シリアル化と脱派化の2つの部分に分かれています。シリアル化はこのプロセスの最初の部分であり、データをファイル内のストレージまたはネットワーク上の送信のためにバイトのストリームに分割します。脱皮化とは、バイトストリームを開き、オブジェクトを再構築することです。オブジェクトのシリアル化には、基本的なデータ型をバイト表現に変換するだけでなく、データを回復することもあります。データの回復には、データを復元するオブジェクトのインスタンスが必要です。 ObjectOutputStreamのシリアル化プロセスは、オブジェクトの種類やバージョン情報を含むバイトストリームに接続されています。脱isizationの間、JVMはヘッダー情報を含むオブジェクトインスタンスを生成し、オブジェクトバイトストリームからデータをオブジェクトデータメンバーにコピーします。 2つの部分で説明しましょう。
オブジェクトの流れの処理:(シリアル化プロセスと脱介入プロセス)
Java.ioパッケージには、オブジェクトをシリアル化する2つのクラスがあります。 ObjectOutputStreamは、オブジェクトをバイトストリームに書き込む責任があり、ObjectInputStreamはバイトストリームからオブジェクトを再構築します。
まず、ObjectOutputStreamクラスを理解しましょう。 ObjectOutputStreamクラスは、DataUtputインターフェイスを拡張します。
writeObject()メソッドは、オブジェクトシリアル化の最も重要な方法です。オブジェクトに他のオブジェクトへの参照が含まれている場合、writeObject()メソッドはこれらのオブジェクトを再帰的にシリアル化します。各ObjectOutputStreamは、同じオブジェクトの複数のコピーが送信されるのを防ぐために、シリアル化されたオブジェクト参照テーブルを維持します。 (これは重要です)writeObject()は、相互参照オブジェクトのセット全体をシリアル化できるため、同じオブジェクトを誤って同じオブジェクトをシリアル化するように誤って要求される場合があります。現時点では、オブジェクトバイトストリームに再び書き込む代わりに、アンチサイレンファレンスのシリアル化が実行されます。
次に、例からObjectOutputStreamクラスを理解しましょう。
コードコピーは次のとおりです。
//今日の日付をファイルにシリアル化します。
fileoutputStream f = new fileoutputStream( "TMP");
objectOutputStream s = new objectOutputStream(f);
S.WriteObject( "Today");
s.writeObject(new date());
s.flush();
それでは、ObjectInputStreamクラスを理解しましょう。 ObjectOutputStreamに似ています。 DateAnputインターフェイスを拡張します。 ObjectInputStreamの方法は、DatainputStreamのJava Basicデータ型を読み取るパブリック方法を反映しています。 readObject()メソッドは、バイトストリームからオブジェクトを脱上化します。 readObject()メソッドが呼び出されるたびに、ストリーム内の次のオブジェクトが返されます。オブジェクトバイトストリームは、クラスのバイトコードを送信しませんが、クラス名とその署名が含まれます。 readObject()がオブジェクトを受信すると、JVMは指定されたクラスをヘッダーにロードします。このクラスが見つからない場合、readobject()はclassNotFoundExceptionをスローします。 ObjectInputStreamメソッドの残りの部分は、脱力化プロセスをカスタマイズするために使用されます。
例は次のとおりです。
コードコピーは次のとおりです。
//ファイルから文字列オブジェクトと日付オブジェクトをDeserializeします
fileInputStream in = new FileInputStream( "TMP");
ObjectInputStream s = new ObjectInputStream(in);
string today =(string)S.ReadObject();
日付date =(date)s.readObject();
カスタマイズされたシリアル化プロセス:
通常、シリアル化は自動的に実行できますが、プロセスが制御される場合があります。 Javaは、クラスをシリアル化可能であると宣言することができますが、静的または一時的なものとして宣言されたデータメンバーを手動で制御できます。
例:非常にシンプルなシリアル化クラス。
コードコピーは次のとおりです。
パブリッククラスSimpleSeRializableClassはシリアル化可能な実装{
string stoday = "today:";
一時的な日付dttoday = new Date();
}
シリアル化の場合、クラスのすべてのデータメンバーは、一時的または静的と宣言されたデータを除き、シリアル化可能です。変数を一時的に宣言すると、JVMに、引数のシリアル化に責任があることを伝えます。データメンバーを一時的であると宣言した後、シリアル化プロセスはオブジェクトバイトストリームに追加できず、一時的なデータメンバーから送信されるデータはありません。その後、データを脱必要にする場合、データメンバーを再構築する必要があります(クラス定義の一部であるため)が、このデータメンバーがストリームにデータを記述しないため、データは含まれていません。オブジェクトストリームは静的または一時的なシリアル化ではないことを忘れないでください。クラスは、これらのデータメンバーを処理するために、writeObject()およびreadObject()メソッドを使用する必要があります。 writeObject()およびreadObject()メソッドを使用する場合、これらのデータメンバーが書かれた順序で読み取ることにも注意を払う必要があります。
カスタムシリアル化の使用方法に関するいくつかのコードは次のとおりです
コードコピーは次のとおりです。
// writeObject()メソッドを書き換えて、過渡メンバーを処理します。
public void writeObject(objectOutputStream outputStream)IOException {
outputStream.DefaultWriteObject(); //カスタマイズされたwriteObject()メソッドを作成します
//自動シリアル化で組み込みロジックを使用します。
outputStream.writeObject(osocket.getinetAddress());
outputStream.writeint(osocket.getport());
}
// readObject()メソッドを書き換えて、一時的なメンバーを受信します。
private void readObject(ObjectInputStream inputstream)はioExceptionをスローします。
classNotFoundException {
inputstream.defaultreadobject(); // defaultreadobject()サプリメント自動シリアル化
inetAddress oaddress =(inetAddress)inputstream.readObject();
int iport = inputstream.readint();
osocket = new Socket(oaddress、iport);
iid = getId();
dttoday = new date();
}
シリアル化プロセスを完全にカスタマイズします。
クラスが独自のシリアル化に完全に責任を負う場合、シリアル化可能なインターフェイスの代わりに外部化可能なインターフェイスを実装します。外部化可能なインターフェイス定義には、2つのメソッドWriteExternal()とreadExternal()が含まれます。これらのメソッドは、オブジェクトのデータメンバーがバイトストリームにどのように書き込まれるかを制御することができます、自動シリアル化はまったくありません。ここで注意してください。宣言クラスは、重大なセキュリティリスクを持つ外部化可能なインターフェイスを実装します。 writeexternal()およびreadexternal()メソッドは公開されており、悪意のあるクラスはこれらのメソッドを使用してオブジェクトデータを読み書きすることができます。オブジェクトに機密情報が含まれている場合は、特に注意してください。これには、安全なソケットを使用するか、バイトストリーム全体を暗号化することが含まれます。この時点で、シリアル化の基本的な知識を学びました。