| 目次 | 前の項目 | 次の項目 | Java オブジェクト直列化仕様 |
クラスObjectOutputStreamは、オブジェクト直列化を実装するためのものです。このクラスは、すでに直列化されたオブジェクトセ ットなどのストリームの状態を維持します。そのメソッドは、直列化するオブジェクトのトラバーサルを 制御して、指定されたオブジェクトと参照するオブジェクトを保管します。package java.io; public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants { public ObjectOutputStream(OutputStream out) throws IOException; public final void writeObject(Object obj) throws IOException; public void defaultWriteObject(); throws IOException, NotActiveException; public PutField putFields() throws IOException; public writeFields() throws IOException; public void reset() throws IOException; protected void annotateClass(Class cl) throws IOException; protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException; protected Object replaceObject(Object obj) throws IOException; protected boolean enableReplaceObject(boolean enable) throws SecurityException; protected void writeStreamHeader() throws IOException; public void write(int data) throws IOException; public void write(byte b[]) throws IOException; public void write(byte b[], int off, int len) throws IOException; public void flush() throws IOException; protected void drain() throws IOException; public void close() throws IOException; public void writeBoolean(boolean data) throws IOException; public void writeByte(int data) throws IOException; public void writeShort(int data) throws IOException; public void writeChar(int data) throws IOException; public void writeInt(int data) throws IOException; public void writeLong(long data) throws IOException; public void writeFloat(float data) throws IOException; public void writeDouble(double data) throws IOException; public void writeBytes(String data) throws IOException; public void writeChars(String data) throws IOException; public void writeUTF(String data) throws IOException; // Inner class to provide access to serializable fields. abstract static public class PutField { public void put(String name, boolean value) throws IOException, IllegalArgumentException; public void put(String name, char data) throws IOException, IllegalArgumentException; public void put(String name, byte data) throws IOException, IllegalArgumentException; public void put(String name, short data) throws IOException, IllegalArgumentException; public void put(String name, int data) throws IOException, IllegalArgumentException; public void put(String name, long data) throws IOException, IllegalArgumentException; public void put(String name, float data) throws IOException, IllegalArgumentException; public void put(String name, double data) throws IOException, IllegalArgumentException; public void put(String name, Object data) throws IOException, IllegalArgumentException; } public void useProtocolVersion(int version) throws IOException; protected ObjectOutputStream() throws IOException; protected writeObjectOverride() throws NotActiveException, IOException; }ObjectOutputStreamコンストラクタには、OutputStreamが必要です。このコンストラクタは、writeStreamHeaderを呼び出して、マジック番号とバージョンをストリームに書き込みます。 そして、このストリームは、ObjectInputStreamコンストラクタの対応するreadStreamHeaderによって読み込まれ、検査されます。
writeObjectメソッドは、オブジェクトをストリームに直列化するために使用します。オブジェクトは、次のように直 列化されます。
writeObjectOverride
メソッドを呼び出してから、復帰します。実装のオーバーライドは、この節の最後で説明します。
writeObject から戻ります。
writeObject から戻ります。
Class であれば、対応する
ObjectStreamClass
がストリームに書き込まれ、そのクラスのハンドルが割り当てられ、writeObject
から戻ります。
ObjectStreamClass
であれば、そのクラスの記述子がストリームに書き込まれます。
これには、その名前、serialVersionUID、名前と型別のフィールドリストが含まれます。
この記述子のハンドルが割り当てられます。writeObject
から戻る前に、annotateClass サブクラスメソッドが呼び出されます。
ObjectInputStream
のサブクラスによる潜在的な置換を処理します。
上記の一方または両方の手順で元のオブジェクトを置き換えた場合、元のオブジェクトから置換オブジェ クトへのマッピングが (手順 4 で利用するために) 記録されます。その後、新規オブジェクトに対し、手順 3 〜 7 が繰り返されます。置換オブジェクトが、手順 3 〜 7 を適用できないタイプの場合、手順 10 で置換オブジェクトを使った処理が再開されます。
java.lang.String の場合、文字列は
UTF (Universal Transfer Format) 形式、また長い文字列は UTF の異形式 (詳細は 「6.2 ストリーム要素」を参照)
で書き込まれます。ハンドルが文字列に割り当てられ、writeObject が返されます。
writeObject
が再帰的に呼び出されて、配列の ObjectStreamClass
が書き込まれます。配列用のハンドルが割り当てられます。その直後に、配列の長さの分だけ続きます。
その後、配列の各要素がストリームに書き込まれて、writeObject が返されます。
writeObject
を再帰的に呼び出すことにより、オブジェクトのクラスの ObjectStreamClass
が書き込まれます。この、ストリームへの書き込みは、オブジェクトの最初の参照時だけです。このオブ
ジェクト用のハンドルが割り当てられます。JavaTM 2 SDK,
Standard Edition, v1.3 から、writeObject は writeClassDescriptor
を呼び出して ObjectStreamClass オブジェクトを出力するようになりました。
writeObject メソッドを保持しない場合、defaultWriteObject
メソッドが呼び出されて、直列化可能フィールドのストリームへの書き込みが行われます。クラスが
writeObject
メソッドを保持する場合、このメソッドが呼び出されます。defaultWriteObject か
putFields のどちらか、および writeFields
を呼び出してオブジェクトの状態を保存し、その後、他の情報をストリームに書き込むことができます。
writeExternal メソッドが呼び出されます。
NotSerializableException
がスローされます。
例外は、トラバーサル中に発生する場合も、基礎ストリーム内で発生する場合もあります。IOExce ptionのすべてのサブクラスで、例外プロトコルを使って例外がストリームに書き込まれ、ストリーム状態が破 棄されます。最初の例外をストリームに書き込んでいる間に 2 番目のIOExceptionがスローされると、ストリームの状態は不明のままで、writeObjectからStreamCorruptedExceptionがスローされます。その他の例外の場合、ストリームは中止され、不明で使用不能な状態のままになりま す。
defaultWriteObjectメソッドは、現在のクラスに対するデフォルトの直列化機構を実装します。このメソッドの呼び出しは、 クラスのwriteObjectメソッドからのみ可能です。このメソッドは、現在のクラスの直列化可能フィールドすべてをストリーム に書き込みます。writeObjectメソッドの外部からこのメソッドが呼び出されると、NotActiveExceptionがスローされます。
putFieldsメソッドは、ストリーム内の直列化可能フィールドの値を設定する際に呼び出し側が使用するPutFieldオブジェクトを返します。フィールドは、任意の順序で設定できます。すべてのフィールドの設定が完了 したら、writeFieldsを呼び出してフィールド値を規定の順序でストリームに書き込む必要があります。フィールドが設定され ない場合、そのフィールドタイプに適したデフォルト値がストリームに書き込まれます。このメソッドは 、直列化可能クラスのwriteObjectメソッド内からしか呼び出すことができません。また、このメソッドは、1 回しか呼び出すことができず、defaultWriteObjectがすでに呼び出されている場合は呼び出せません。writeFieldsを呼び出した後でないと、他のデータをストリームに書き込むことはできません。
resetメソッドは、ストリーム状態を再設定して、構成時の状態に戻します。Resetにより、それまでストリームに書き込まれたすべてのオブジェクト状態は破棄されます。ストリーム内の 現在位置に再設定のマークが付けられるため、対応するObjectInputStreamも同じ位置で再設定されます。以前にストリームに書き込まれたオブジェクトが、ストリームに書き込み 済みのオブジェクトとして記憶されることはありません。これらのオブジェクトは、ストリームに再度書 き込まれます。これは、オブジェクトの内容やオブジェクトを再送信しなければならない場合に有用です 。オブジェクトの直列化時にResetが呼び出されない場合もあります。不正な仕方で呼び出されると、IOExceptionがスローされます。JavaTM 2 SDK, Standard Edition, v1.3 から、
ObjectStreamClassの直列化が必要になると、writeClassDescriptorが呼び出されるようになりました。writeClassDescriptorは、ObjectStreamClass表現の直列化ストリームへの書き込みを担当します。サブクラスでこのメソッドをオーバーライドするこ とにより、クラス記述子の直列化ストリームへの書き込み方法をカスタマイズできます。このメソッドを オーバーライドする場合は、ObjectInputStream内の対応するreadClassDescriptorメソッドもオーバーライドして、カスタムストリーム表現からクラス記述子を再構成する必要があります 。デフォルトでは、writeClassDescriptorは、「6.4 ストリーム形式の文法」で指定された形式に従ってクラス記述子を書き込みます。このメソッドは、ObjectOutputStreamが以前の直列化ストリーム形式を使用していない場合にのみ、呼び出し可能である点に留意してください (「6.3 ストリームプロトコルのバージョン」を参照)。直列化ストリームに以前の形式 (ObjectStreamConstants.PROTOCOL_VERSION_1) が使用されている場合、クラス記述子はオーバーライドまたはカスタマイズ不可能な方法で内部に書き込 まれます。
Classの直列化中、かつクラス記述子のストリームへの書き込み後に、annotateClassメソッドが呼び出されます。サブクラスがこのメソッドを継承して、クラスに関する他の情報をストリー ムに書き込むことも可能です。この情報の読み取りは、対応するObjectInputStreamサブクラスのresolveClassメソッドを使って実行する必要があります。
ObjectOutputStreamサブクラスは、replaceObjectメソッドを実装することにより、直列化の過程でのオブジェクトの監視および置換を実行できます。オブ ジェクトを置換する場合、最初の置換対象オブジェクトに対しwriteObjectを呼び出す前に、enableReplaceObjectを呼び出して置換を明示的に有効にする必要があります。オブジェクトの置換が有効にされた後、オブジ ェクトを初めて直列化する直前に、各オブジェクトに対してreplaceObjectが呼び出されます。replaceObjectメソッドは、特別に処理されるクラスであるClass、ObjectStreamClassのオブジェクトに対しては呼び出されません。サブクラスの実装が、元のオブジェクトではなく直列化さ れる代替オブジェクトを返す場合があります。代替オブジェクトは、直列化可能でなければなりません。 ストリームにおける元のオブジェクトへのすべての参照は、置換オブジェクトによって置き換えられます 。オブジェクトの置換中に、サブクラスは、代替オブジェクトと参照の格納される全フィールドとの互換性 が保たれていること、または直列化復元時に相補置換が行われることを保証する必要があります。オブジ ェクトのタイプがフィールドまたは配列要素のタイプのサブクラスではない場合、そのオブジェクトは、
ClassCastExceptionをスローすることにより直列化復元を中止します。参照は格納されません。
enableReplaceObjectメソッドは、信頼できるObjectOutputStreamのサブクラスが、直列化の際に、あるオブジェクトで別のオブジェクトを代用することを可能にするため に、呼び出します。オブジェクトの置換は、enableReplaceObjectがtrue値で呼び出されるまでは、使用不可になっています。また、使用可能にしたあとで、falseに設定して、使用不可にされる場合があります。前の設定が返されます。enableReplaceObject は、置換を要求するストリームを信頼できるかどうかを調べます。オブジェクトの private 状態が意図せずに公開されないことを保証するために、信頼できるストリームサブクラスだけがreplaceObjectを使用することを許可されます。信頼されるクラスは、Serializable 置換を有効にする権限を保持する、セキュリティ保護ドメインに属するクラスです。
ObjectOutputStreamのサブクラスがシステムドメインの一部とはみなされない場合、SerializablePermission "enableSubstitution"をセキュリティポリシーファイルに追加する必要があります。ObjectInputStreamのサブクラスの保護ドメインに、enableReplaceObjectの呼び出しによる"enableSubstitution"の権限がない場合は、AccessControlExceptionがスローされます。セキュリティモデルの詳細は、JavaTM セキュリティアーキテクチャ (JDK1.2) のドキュメントを参照してください。
writeStreamHeaderメソッドは、マジック番号とバージョンをストリームに書き込みます。この情報は、ObjectInputS treamのreadStreamHeaderメソッドを使って読み取る必要があります。ストリームの一意な形式を識別するために、サブクラスがこ のメソッドを実装することが必要な場合があります。
flushメソッドを使用して、ストリームが保持するバッファを空にして、基礎ストリームにフラッシュを転送し ます。基礎ストリームのフラッシュを強制せずにObjectOutputStreamのバッファだけを空にする場合、サブクラスからdrainメソッドを使用できます。プリミティブ型の書き込みメソッドはすべて、
DataOutputStreamを使って値を符号化して、標準ストリーム形式にします。バイトがブロックデータレコードにバッファリ ングされることにより、オブジェクトのエンコーディングとの区別が可能になります。このバッファリン グにより、クラスのバージョン管理が必要な場合、プリミティブデータのスキップも可能になります。ま た、クラス固有のメソッドを呼び出すことなく、ストリームの構文解析を行うことも可能になります。直列化の実装をオーバーライドするために、
ObjectOutputStreamのサブクラスは、保護された引数なしのObjectOutputStreamコンストラクタを呼び出す必要があります。SerializablePermission "enableSubclassImplementation"の引数なしのコンストラクタ内にはセキュリティチェックがあり、信頼できるクラスだけにデフォルトの 実装のオーバーライドを許可します。このコンストラクタは、ObjectOutputStreamに private なデータを割り当てず、ファイナルのwriteObjectメソッドはwriteObjectOverrideメソッドを呼び出してから復帰することを示すフラグを設定します。ほかのすべてのObjectOutputStreamメソッドは、ファイナルではないので、サブクラスによって直接オーバーライドされます。