55

シリアル化する必要がある不変の値の型を定義するクラスがあります。不変性は、コンストラクターで設定された最終フィールドに由来します。シリアル化を試みましたが、うまくいきました (驚くべきことに?) - しかし、方法がわかりません。

クラスの例はこちら

public class MyValueType implements Serializable
{
    private final int value;

    private transient int derivedValue;

    public MyValueType(int value)
    {
        this.value = value;
        this.derivedValue = derivedValue(value);
    }

    // getters etc...
}

クラスに引数なしのコンストラクターがない場合、インスタンス化して最終的なフィールドを設定するにはどうすればよいでしょうか?

(余談ですが、IDEAはこのクラスに対して「no serialVersionUID」検査警告を生成していなかったにもかかわらず、シリアライズ可能にしたばかりの他のクラスに対して警告を正常に生成したため、特にこのクラスに気付きました。)

4

3 に答える 3

44

デシリアライゼーションは、基本的な言語構造より下のレベルで JVM によって実装されます。具体的には、コンストラクターを呼び出しません。

于 2010-05-25T12:35:26.173 に答える
24

クラスに引数なしのコンストラクターがない場合、インスタンス化して最終的なフィールドを設定するにはどうすればよいでしょうか?

厄介な黒魔術が発生します。JVM には、コンストラクターを呼び出さずにオブジェクトを作成できるバックドアがあります。新しいオブジェクトのフィールドは、最初にデフォルト値 (false、0、null など) に初期化され、次にオブジェクトの逆シリアル化コードがフィールドにオブジェクト ストリームからの値を入力します。

(Java がオープンソース化された今、これを行うコードを読むことができます...そして泣きます!)

于 2010-05-25T12:36:32.247 に答える
13

transientマイケルとスティーブンの両方があなたに素晴らしい答えを与えました、私はただフィールドについてあなたに警告したいです。

nullデシリアライズ後にデフォルト値(参照の場合は0、プリミティブの場合は0)が受け入れられない場合は、のバージョンを提供し、readObjectそこで初期化する必要があります。

    private void readObject (
            final ObjectInputStream s
        ) throws
            ClassNotFoundException,
            IOException
    {
        s.defaultReadObject( );

        // derivedValue is still 0
        this.derivedValue = derivedValue( value );
    }
于 2010-05-25T12:53:29.750 に答える