mschayna
mschayna

Reputation: 1310

Java: accessing transient object fields inside class

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

Answers (3)

BalusC
BalusC

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

pgras
pgras

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

pgras
pgras

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

Related Questions