1

クラス B の宣言で値 3 が割り当てられた静的変数 x を持つクラス B のインスタンスを作成するとします。main() メソッドでは、次のようにします。

B b = new B();
b.x = 7; //allowed to use an instance to set the static member value

この後、 b がシリアライズされてからデシリアライズされます。次に、次の行が発生します。

System.out.println ("static: " + b.x);

価値は?7か3?

静的変数がシリアル化されていないことはわかっていますが、クラス全体で静的メンバーのコピーが 1 つしかなく、値が 7 に設定されているため、インスタンスを逆シリアル化した後も保持する必要がありますか?

4

4 に答える 4

8

何が起こるかは次のとおりです。

  1. 静的初期化子は値を 3 に設定します。
  2. インスタンス コンストラクターは値を 7 に設定します。
  3. シリアル化は static 変数を認識せず、無視されます。
  4. 逆シリアル化は静的変数を認識せず、無視されます。
  5. プログラムがずっと実行されている場合、またはプログラムがシャットダウンされて再起動された場合、値はまだ 7 です (コンストラクターで発生した変更から)。

説明したロジックが必要な場合は、作成されたインスタンスの数をカウントする別の静的変数を追加し、カスタム ロジックでメソッドwriteObjectとメソッドをオーバーライドする必要があります。readObject

于 2009-12-18T16:15:22.710 に答える
7

JVM の同じインスタンスでデシリアライズすると、2 番目のスニペットは 7 を返します。これは、bx の値が 7 に設定されているためです。これは、B のインスタンスがシリアライズおよびデシリアライズされたため、変更されていません。

オブジェクトをシリアライズし、JVM をシャットダウンし、新しい JVM を起動してから、(静的初期化以外の場所で bx を設定せずに) オブジェクトをデシリアライズすると、bx の値は 3 になります。

于 2009-12-18T16:14:52.540 に答える
1

次のコードを使用して、メモリ内ストリームとの間でシリアライズおよびデシリアライズし、オブジェクトをやり取りします。

package com.example.serialization;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable; 
import junit.framework.TestCase;


public class SerializationTest extends TestCase {
    public void testStaticValueAfterSerialization() {
       B b = new B();
       b.x = 7; //allowed to use an instance to set the static member value

       B deserializedB = copyObject(b);
       assertEquals("b.x should be 7 after serialization", 7, deserializedB.x);
    }

    private <T extends Serializable> T copyObject(final T source) {
        if (source == null)
                throw new IllegalArgumentException("source is null");
        final T copy;
        try {
            copy = serializationClone(source);
            } catch (Exception e) {
                // (optional) die gloriously!
            throw new AssertionError("Error copying: " + source, e);
        }    
            return copy;
    }

    private <T extends Serializable> T serializationClone(final T source)
        throws IOException, ClassNotFoundException {
    ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
    ObjectOutputStream outputStream = new ObjectOutputStream(byteStream);

            // 1. serialize the object to the in-memory output stream
        outputStream.writeObject(source);

        ObjectInputStream inputStream = new ObjectInputStream(
                new ByteArrayInputStream(byteStream.toByteArray()));

        // 2. deserialize the object from the in-memory input stream
        @SuppressWarnings("unchecked")
            final T copy = (T) inputStream.readObject();

        return copy; // NOPMD : v. supra
    }
}

そのクラスを作成したら、JUnit ランナーで実行し、テストが成功するかどうかを確認してください! 必要に応じて、1 つのテスト ケースで結果をファイルに書き込むことができます。次に、別のテスト ケースで、ファイルから結果を読み取ります。

于 2009-12-18T17:05:07.367 に答える
0

静的イニシャライザは 1 回だけ実行されるため、値は7.

于 2009-12-18T16:16:11.413 に答える