2

从类中的任何方法访问私有瞬态对象字段必须通过一些代码来控制。最佳做法是什么?

private transient MyClass object = null;

内部获取方法:

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();
}

getter 中的延迟加载(如您在示例中所做的那样)仅在构造函数和/或初始化块MyClass正在做相当昂贵的事情时才有用,但它不是线程安全的。

transient修饰符没有任何区别。它只在对象即将被序列化时跳过该字段。

编辑:不再相关。正如其他人所证明的那样,它们确实不会在反序列化时重新初始化(尽管有趣的想法,实际上只有在声明它们时才会发生static)。我会继续使用延迟加载方法,或者在反序列化后直接通过它们的设置器重置它们。

于 2009-11-11T13:28:02.540 回答
0

必须发布关于瞬态的新答案,因为评论太长了。以下代码打印

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 回答