Reputation: 1310
Accessing private transient object fields from any method in class must be controlled with some code. What is the best practice?
private transient MyClass object = null;
internal get method:
private MyClass getObject() {
if (object == null)
object = new MyClass();
return object;
}
// use...
getObject().someWhat();
or "make sure" method:
private void checkObject() {
if (object == null)
object = new MyClass();
}
// use...
checkObject();
object.someWhat();
or something clever, more safe or more powerful?
Upvotes: 2
Views: 1000
Reputation: 1109432
Most safe (and normal) way would be either directly initializing it:
private transient MyClass object = new MyClass();
or using the constructor
public ParentClass() {
this.object = new MyClass();
}
Lazy loading in getters (as you did in your example) is only useful if the constructor and/or initialization blocks of MyClass
is doing fairly expensive stuff, but it is not threadsafe.
The transient
modifier doesn't make any difference. It only skips the field whenever the object is about to be serialized.
Edit: not relevant anymore. As proven by someone else, they indeed don't get reinitialized on deserialization (interesting thought though, it will actually only happen if they are declared static
). I'd go ahead with the lazy loading approach or by resetting them through their setters directly after deserialization.
Upvotes: 0
Reputation: 12780
Have to post a new answer about transient because it's too long for a comment. Following code prints
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;
}
}
}
Upvotes: 0
Reputation: 12780
Transient fields are lost at serialization but you need them only after deserialization, so you have to restore them to what you need in the readObject method...
Upvotes: 3