Java:访问类中的临时对象字段

时间:2009-11-11 13:24:19

标签: java object field transient

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

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

或者更聪明,更安全或更强大的东西?

3 个答案:

答案 0 :(得分:3)

瞬态字段在序列化时丢失,但只有在反序列化后才需要它们,所以你必须将它们恢复到readObject方法所需的内容......

答案 1 :(得分:0)

最安全(和正常)的方式是直接初始化它:

private transient MyClass object = new MyClass();

或使用构造函数

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

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

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

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

答案 2 :(得分: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;
    }
}

}