2

クラス内の任意のメソッドからプライベート一時オブジェクトフィールドへのアクセスは、何らかのコードで制御する必要があります。ベストプラクティスは何ですか?

private transient MyClass object = null;

内部getメソッド:

private MyClass getObject() {
    if (object == null)
        object = new MyClass();
    return object;
}
// use...
getObject().someWhat();

または「確認する」方法:

private void checkObject() {
    if (object == null)
        object = new MyClass();
}
// use...
checkObject();
object.someWhat();

または何か賢い、より安全またはより強力ですか?

4

3 に答える 3

3

一時的なフィールドはシリアル化時に失われますが、逆シリアル化後にのみ必要になるため、readObject メソッドで必要なものに復元する必要があります...

于 2009-11-11T13:33:59.153 に答える
0

最も安全な(そして通常の)方法は、直接初期化することです。

private transient MyClass object = new MyClass();

またはコンストラクターを使用する

public ParentClass() {
    this.object = new MyClass();
}

ゲッターでの遅延読み込み(例で行ったように)は、のコンストラクターや初期化ブロックがMyClassかなり高価な処理を実行している場合にのみ役立ちますが、スレッドセーフではありません。

修飾子は何のtransient違いもありません。オブジェクトがシリアル化されようとしているときはいつでも、フィールドをスキップするだけです。

編集:もう関係ありません。他の誰かによって証明されているように、それらは実際に逆シリアル化で再初期化されません(興味深い考えですが、実際には宣言されている場合にのみ発生しますstatic)。遅延読み込みのアプローチを進めるか、逆シリアル化の直後にセッターを介してそれらをリセットします。

于 2009-11-11T13:28:02.540 に答える
0

コメントするには長すぎるため、transient に関する新しい回答を投稿する必要があります。次のコードプリント

Before: HELLO   FOO BAR
After:  HELLO   null    null


public class Test {

public static void main(String[] args) throws Exception {

    final Foo foo1 = new Foo();
    System.out.println("Before:\t" + foo1.getValue1() + "\t" + foo1.getValue2() + "\t" + foo1.getValue3());
    final File tempFile = File.createTempFile("test", null);
    // to arrange for a file created by this method to be deleted automatically
    tempFile.deleteOnExit();
    final FileOutputStream fos = new FileOutputStream(tempFile);
    final ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(foo1);
    oos.close();
    final FileInputStream fis = new FileInputStream(tempFile);
    final ObjectInputStream ois = new ObjectInputStream(fis);
    final Foo foo2 = (Foo) ois.readObject();
    ois.close();
    System.out.println("After:\t" + foo2.getValue1() + "\t" + foo2.getValue2() + "\t" + foo2.getValue3());

}

static class Foo implements Serializable {

    private static final long serialVersionUID = 1L;
    private String value1 = "HELLO";
    private transient String value2 = "FOO";
    private transient String value3;

    public Foo() {
        super();
        this.value3 = "BAR";
    }

    public String getValue1() {
        return this.value1;
    }

    public String getValue2() {
        return this.value2;
    }

    public String getValue3() {
        return this.value3;
    }
}

}

于 2009-11-11T15:32:05.187 に答える