1

抽象クラスがあるとします

public abstract class Base implements Serializable {
    static final long serialVersionUID = 1;
    public Base(int x) { ... }
    public abstract void baseMethod();
}

そして、クラスを動的に作成します

public class Temp {
    public Base getBase() {
        return new Base(2) {

            static final long serialVersionUID = 1;

            @Override
            public void baseMethod() { .... } 
        };
    }
}

String からクラス Temp を動的に生成し、新しいインスタンスを呼び出し、ベース オブジェクトを抽出して、Base を拡張する他のインスタンスと同様に使用することができます。問題は、シリアル化するときに発生します。動的な Temp クラスから抽出した Base ベース オブジェクトをシリアル化できますが、後で別のセッションで逆シリアル化することはできません。これは、Temp がクラス パスに存在しなくなったためです。

皆さんはこれを回避する方法を考えられますか? 問題の Base オブジェクトを Temp クラスから分離して取得する方法が必要です (そこから Base クラスを抽出した後は気にしません)。Base オブジェクトは、Temp クラスの何にも依存しません。

4

2 に答える 2

1

を書き込むようにオブジェクトに実装し、それをラップするを作成するようにオブジェクトに実装writeReplaceしてみてください。Serializable コントラクトを参照してください。TempBasereadResolveBaseTemp

コードは次のようになります。これを実際にテストしたわけではありませんが、かなり近いはずです。

public class Base implements Serializable {
    // Existing members here

    private Object readResolve() throws ObjectStreamException {
        return new Temp(this);
    }
}

public class Temp implements Serializable {
    Base base;

    public Temp(Base base) {
        this.base = base;
    }

    // Other existing methods here

    private Object writeReplace() throws ObjectStreamException {
        return base;
    }
}

これにより、これら2つのクラス間に厄介な循環依存関係が導入されることはわかっていますが、他の人が提案した外部リーダー/ライターメソッドを除いて、これを行う別の優れた方法は見当たりません。Tempこのアプローチの利点は、より大きなオブジェクト グラフの一部として を書き出すことがサポートされていることです。

于 2013-02-23T18:24:38.243 に答える
0

まず第一に、リチャード、これは私がこの独特のケースを見たのは本当に初めてです。これがお役に立てば幸いです。:

import java.io.*;
abstract class Base implements Serializable
{
    protected int x ;
    private static final long serialVersionUID = 1L;
    public Base(int x) { this.x = x; }
    public abstract void baseMethod();
}
class Temp implements Serializable
{
    private static final long serialVersionUID = 2L;//Make Temp serializable also.
    public Base getBase(int i) 
    {
        Base base = new Base(i)
        {
            static final long serialVersionUID = 1L;
            @Override
            public void baseMethod() { System.out.println(x); } 
        };
        return base;
    }
}
public class ReadWriteBaseObject 
{
    public static Base createBaseObject(int i)
    {
        Temp temp = new Temp();//You might be creating your Temp object here Dynamically..
        Base base = temp.getBase(i);
        return base;
    }
    public static Base read()
    {
        ObjectInputStream oin = null;
        try
        {
            FileInputStream fin = new FileInputStream("BASE.ser");
            oin = new ObjectInputStream(fin);
            Base base = (Base)oin.readObject();
            return base;
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            return null;
        }
        finally
        {
            if (oin!=null)
            {
                try
                {
                    oin.close();
                }
                catch (Exception ex){}
            }
        }
    }
    public static void write(Base base)
    {
        if (base == null)
        {
            System.out.println("Can't write null");
            return;
        }
        ObjectOutputStream os = null;
        try
        {
            FileOutputStream fos = new FileOutputStream("BASE.ser");
            os = new ObjectOutputStream(fos);
            os.writeObject(base);
            System.out.println("Wrote to file");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            if (os!=null)
            {
                try
                {
                    os.close();
                }
                catch (Exception ex){}
            }
        }
    }
    public static void main(String st[])
    {
        Base base = createBaseObject(45);
        write(base);
        Base obj = read();
        obj.baseMethod();
    }
}

EDIT
匿名クラスのインスタンスは正常にシリアライズできますが、いくつかの複雑さのためにJavaでは強く推奨されていません。Javaの公式サイトには次のように記載されています

注 -ローカル クラスと匿名クラスを含む内部クラス (つまり、静的メンバー クラスではない入れ子になったクラス) のシリアル化は、いくつかの理由から強くお勧めできません。非静的コンテキストで宣言された内部クラスには、囲んでいるクラス インスタンスへの暗黙的で非一時的な参照が含まれているため、そのような内部クラス インスタンスをシリアル化すると、関連する外部クラス インスタンスもシリアル化されます。内部クラスを実装するために javac (または他の JavaTM コンパイラ) によって生成される合成フィールドは、実装に依存し、コンパイラ間で異なる場合があります。そのようなフィールドの違いは、互換性を損なうだけでなく、
デフォルトの serialVersionUID 値が競合しています。ローカルおよび匿名の内部クラスに割り当てられる名前も実装に依存し、コンパイラ間で異なる場合があります。内部クラスはコンパイル時の定数フィールド以外の静的メンバーを宣言できないため、serialPersistentFields メカニズムを使用してシリアライズ可能なフィールドを指定することはできません。最後に、外部インスタンスに関連付けられた内部クラスには引数のないコンストラクターがないため (このような内部クラスのコンストラクターは、囲んでいるインスタンスを先頭に追加されたパラメーターとして暗黙的に受け入れます)、Externalizable を実装できません。ただし、上記の問題はいずれも静的メンバー クラスには当てはまりません。

Java でのシリアライゼーションの詳細については、こちらをご覧ください。

于 2013-02-23T19:02:30.837 に答える