19

Java のデフォルトのシリアル化メカニズムはあまり効率的ではないと言われています。これは、a) リフレクションを介して書き込み/読み取りを行うフィールドを検出するため、通常は低速である b) 余分なデータをストリームに書き込むためです。

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

ここに質問があります: 代わりに「writeObject/readObject」メソッドを提供し、deafiltWriteObject/defaultReadObject を呼び出さない場合、このメカニズムはリフレクションを使用して書き込み/読み取り対象のフィールドを特定しません。さらに、余分な書き込みも行いません。ストリーミングするデータ(またはそうなるかどうかはわかりません)。効率の観点から、上記の writeObject/readObject の実装は Externalizable の実装と同じですか? または、後者のオプションは、前者にないより実用的な利点を提供しますか?

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

4

3 に答える 3

9

次に呼び出すクラス/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

于 2012-05-04T06:45:23.003 に答える
2

シリアル化メカニズムのコードを実験して調べているときに、いくつかのことがわかりました。

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

2) Externalizable の書き込みデータ量は、Serializable with readObject/writeObject よりも少し少ない (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");
    }       
}
于 2012-05-04T08:36:48.683 に答える