必须使用某些代码控制从类中的任何方法访问私有瞬态对象字段。什么是最佳做法?
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();
或者更聪明,更安全或更强大的东西?
答案 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;
}
}
}