views:

222

answers:

3

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?

A: 
BalusC
Yes, but transient fields are silently (aside of `readObject()` implementation) set to `null` during deserialization -- this is what I want to solve in my question. I should add it to my original text.
mschayna
They aren't set to `null`, they are ust left with their initial value.
Tom Hawtin - tackline
@Tom: in fact they are set to the type default value, thus to null for Object or to 0 for an int for example...
pgras
Exactly as Tom say. Nothing to worry about. Just handle them the normal way. The only difference is that they're never touched during normal (de)serialization.
BalusC
@BalusC: I just posted an another answer to show that transient fields are set to the types default value. In fact constructor is not called during deserialization...
pgras
I see what you mean. I stand corrected.
BalusC
+2  A: 

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...

pgras
Thanks, but I want make my fields transient and also late instancing (i.e. with lazy getter). I add it to question.
mschayna
A: 

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

}

pgras