2012-05-04 10 views
16

Javaのデフォルトのシリアル化メカニズムは、a)リフレクションによって書き込み/読み取りを行うフィールドを検出します。通常は遅いです。b)余分なデータをストリームに書き込むためです。Java:writeObject vs writeExternalの効率

これをより効率的にする方法の1つは、ExternalizableメソッドとそのwriteExternal/readExternalメソッドを実装することです。

ここに質問があります:代わりに 'writeObject/readObject'メソッドを提供し、それらのメソッドでdeafiltWriteObject/defaultReadObjectを呼び出さないと、このメカニズムはリフレクションを使用して書き込み/読み取りするフィールドを特定します余分なデータをストリームに書き込むことはできません(またはそれはわかりません)。ですから、効率性の観点から、上記のwriteObject/readObjectを実装しているのは、Externalizableですか?あるいは、後者のオプションは、前者ではない実際的なメリットをいくつか与えていますか?

EDIT:readObject/writeObjectを実装しているSerializableクラスがサブクラス化されている場合、サブクラスに独自のreadObject/writeObjectがある場合、superのreadObject/writeObjectを呼び出す必要はありません。スーパー/サブクラスが代わりにExternalizableを実装する場合はそうではありません。この場合、superのwriteExternal/readExternalを明示的に呼び出す必要があります。 しかし、この違いは効率の観点からは関係ありません。

答えて

7

次に呼び出すクラス/ writeObject/readObjectを選択する際にはまだ頭がおかしくなります。それは大幅に削減されます。

これは、あなたがやっていることと、それがあなたに与える余分なオプションを使用するかどうかによって、Externalizableと同じことができます。例えばreadObjectは、毎回新しいオブジェクトを作成すると想定しています.ExternalizableにはreadResolveがあります。つまり、オブジェクトを再利用できます。多くの場合

http://docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/input.html

、リサイクルオブジェクトが直列化復元をスピードアップで「次」のステップです。実験と直列化メカニズムのコードを通過しながら、物事のカップルを発見

http://vanillajava.blogspot.co.uk/2011/10/recycling-objects-to-improve.html

+0

お願いします。これについてもう少し説明してください。「次に呼び出すクラス/ writeObject/readObjectを選択するには、まだ頭がおかしくなっています。また、 'readResolve'は 'Externalizable'契約の一部ではありません。だから少し混乱している。 – shrini1000

+0

あなた自身もそうしない限り、readObjectまたはreadExternalを呼び出すクラスを決定する必要があります。 readResolveは、Serailizableでも使用できるオプションのメソッドです。詳細については、最初のリンクを参照してください。 –

+1

Thx。私はreadResolveを使用しましたが、あなたがExternalizableに関連してそれを述べたので、混乱しました。 Btw、私はあなたの記事を読んでいます。良いもの。私はそこに質問をしました。もしあなたがplできるなら、それは素晴らしいことでしょう。応答。 – shrini1000

1

を(それはあなたのためのオプションだと仮定):オブジェクトが外部化であることが判明した場合)

1を、それが外部化にキャストです対応するメソッドが呼び出されます。一方、Serializableオブジェクトの場合、readObject/writeObjectがあるかどうかは反射的にチェックされます。これは、わずかに遅くなるかもしれません。

2)Externalizableのために書かれたデータの量は、readObject/writeObjectを使ってSerializableより少し小さいです(私はBのオブジェクトを書いたときに次のコードのために1バイトの違いが見つかりました) 。外部化のために

:直列化のために

static class A implements Externalizable 
{ 
    @Override 
    public void writeExternal(ObjectOutput out) throws IOException 
    { 
     System.out.println("A write called"); 
    } 

    @Override 
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException 
    { 
     System.out.println("A read called"); 
    }  
} 

static class B extends A implements Externalizable 
{  
    @Override 
    public void writeExternal(ObjectOutput out) throws IOException 
    { 
     super.writeExternal(out); 
     System.out.println("B write called"); 
    } 

    @Override 
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException 
    { 
     super.readExternal(in); 
     System.out.println("B read called"); 
    }  
} 

static class A implements Serializable 
{ 
    private void writeObject(ObjectOutputStream out) throws IOException 
    { 
     System.out.println("A write called"); 
    } 

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException 
    { 
     System.out.println("A read called"); 
    }  
} 

static class B extends A implements Serializable 
{  
    private void writeObject(ObjectOutputStream out) throws IOException 
    {   
     System.out.println("B write called"); 
    } 

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException 
    {   
     System.out.println("B read called"); 
    }  
} 
2

クラス設計の面で大きな違い、Externalizableのみ変更可能なクラスに働くのに対し、Serializableは、任意のクラスで動作するということですパブリックデフォルト(引数なし)のコンストラクタを使用します。

+0

本当に変更可能である必要がありますか?私はこれのようなことをすることはできないのですか? http://www.byteslounge.com/tutorials/java-externalizable-example – shrini1000

+0

@ shrini1000、それを行うことはできますが、 'User'クラスはスレッドセーフではありません。しかし、すべてのフィールドを「揮発性」にすることはそれを修正するはずですので、結局は正しいと思います。クラスは厳密に言えば変更可能でなければなりません。 – nilskp