2011-02-08 11 views
2

自分でシリアル化を実装するにはどうしたらいいですか?意味私はクラスが直列化を実装することを望んでいません。しかし、私は自分でシリアル化を実装したい。シリアル化を実装せずに、ネットワーク経由でオブジェクトを転送したり、ファイルに書き込んだり後で同じ状態でオブジェクトを取得したりすることができます。私は物事を学び、探求したいので、私はそれをしたい。自分のシリアル化をJavaで実装する

+1

何を試してみましたか?私たちが助けることができる特定の問題はありますか?これは実装するのが非常に難しく、それを行う方法について議論するのは非常に複雑で、Java言語仕様を読んで、どのように完了したかを見ているほうがはるかに優れています。いい答えのために – templatetypedef

答えて

6

シリアライゼーションは、オブジェクトの構造をネットワーク経由で簡単に転送できる別の形式に変換するプロセスです。ファイルに格納することもできます。 Javaは、オブジェクトをバイナリ形式にシリアル化します。これは、帯域幅/ディスクスペースに問題がない場合は必要ありません。あなたは、単にXMLとしてあなたのオブジェクトをエンコードすることができます

// Code is for illustration purpose only, I haven't compiled it!!! 

public class Person { 
    private String name; 
    private int age; 
    // ... 

    public String serializeToXml() { 
     StringBuilder xml = new StringBuilder(); 
     xml.append("<person>"); 
     xml.append("<attribute name=\"age\" type=\"int\">").append(age); 
     xml.append("</attribute>"); 
     xml.append("<attribute name=\"name\" type=\"string\">").append(name); 
     xml.append("</attribute>"); 
     xml.append("</person>"); 
     return xml.toString(); 
} 

今、あなたは、オブジェクトのXML表現を取得し、ファイルやネットワーク接続にそれを「シリアライズ」することができます。 XMLを解析できる任意の言語で書かれたプログラムは、このオブジェクトをそれ自身のデータ構造に「逆直列化」することができます。

あなたはよりコンパクトな表現が必要な場合は、バイナリエンコーディングを考えることができます:

// A naive binary serializer. 
    public byte[] serializeToBytes() { 
     ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 

     // Object name and number of attributes. 
     // Write the 4 byte length of the string and the string itself to 
     // the ByteArrayOutputStream. 
     writeString("Person", bytes); 
     bytes.write(2); // number of attributes; 

     // Serialize age 
     writeString("age", bytes); 
     bytes.write(1); // type = 1 (i.e, int) 
     writeString(Integer.toString(age), bytes); 

     // serialize name 
     writeString("name", bytes); 
     bytes.write(2); // type = 2 (i.e, string) 
     writeString(name, bytes); 

     return bytes.toByteArray(); 
    } 

    private static void writeString(String s, ByteArrayOutputStream bytes) { 
     bytes.write(s.length()); 
     bytes.write(s.toBytes()); 
    } 

Google Protocol BuffersのJava実装を参照して、よりコンパクトなバイナリシリアル化方式の詳細については。

+0

ありがとう。 – akshay

+0

@akshayあなたが良い答えだと思うなら、アップしてください:-) –

1

Externalizableを使用して、独自のシリアル化メカニズムを実装できます。シリアライゼーションの難しい側面の1つはバージョン管理であり、これは実装が難しい課題です。バイナリシリアル化形式としてprotobufAvroを見ることもできます。

1

あなたはリフレクションで始まります。オブジェクトのクラスとそのクラスの宣言されたフィールドとすべてのスーパークラスを取得します。次に、各フィールドの値を取得し、それをダンプに書き出します。

デシリアライズするときは、シリアル化されたフォームからクラス名を取得し、オブジェクトをインスタンス化し、そのフィールドをダンプに応じて設定します。

これは、学習したいだけの単純なアプローチです。あなたが「本当に」のためにそれをしたいと思うなら、多くの問題が出てくるでしょう:

  • バージョン管理。アプリケーションの一方の端が新しいバージョンを実行していて、もう一方の端にいくつかのフィールドがないか名前が変更された古いクラス定義がある場合はどうなりますか?
  • デフォルト動作を上書きします。オブジェクトが複雑でフィールド単位で簡単に再作成できない場合はどうなりますか?
  • オブジェクト間の依存関係の再作成(周期的なものを含む)。
  • ...おそらくもっと多くの。
0

Javaソースコードを取得し、シリアル化の実装方法を理解してください。私は数ヶ月前にこれを行いました。そして、シリアライズされたデータを書いたクラスが変更されていないと仮定して、スペースの16%と「通常の」シリアライゼーションの20%を使用するシリアライズを行いました。私はこの仮定を使用することができるクライアント - サーバーのシリアル化にこれを使用します。

0

@Konrad Garusの答えの補足として。 Javaのシリアライゼーションを完全に再実装するための目が離せない問題が1つあります。

オブジェクトを逆シリアル化するときは、オブジェクトのクラスのコンストラクタの1つを使用してインスタンスを再作成する必要があります。しかし、どのコンストラクタを使うべきですか?引数のないコンストラクタがある場合は、おそらくそれを使うことができます。しかし、引数なしのコンストラクタ(または実際には任意のコンストラクタ)は、オブジェクトを作成するだけでなく、オブジェクトで何かを行う可能性があります。たとえば、新しいインスタンスが作成されたという通知を他のものに送信して、まだ完全に逆シリアル化されていないインスタンスを渡すことがあります。

実際には、標準的なJavaデシリアライゼーションコードが行うことを複製することは実際には困難です。それは次のとおりです。

  1. 作成するクラスを決定します。
  2. クラスのインスタンスを、そのコンストラクタのいずれも呼び出さずに作成します。
  3. これは、プライベートフィールドを含むインスタンスのフィールドを埋め込むためにリフレクションを使用して、シリアル化から再構築されたオブジェクトと値を使用します。

問題は、ステップ2には、通常のJavaクラスでは許可されていない「ブラックマジック」が含まれていることです。あなたは

(あなたが血みどろの詳細を理解したい場合は、シリアル化の仕様を読んで、OpenJDKのコードベースでの実装を見てみましょう。)

関連する問題