Java: доступ к полям временного объекта внутри класса - PullRequest
2 голосов
/ 11 ноября 2009

Доступ к частным полям временного объекта из любого метода в классе должен контролироваться с помощью некоторого кода. Какова лучшая практика?

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 ]

3 голосов
/ 11 ноября 2009

Временные поля теряются при сериализации, но они нужны только после десериализации, поэтому вам нужно восстановить их до того, что вам нужно в методе readObject ...

0 голосов
/ 11 ноября 2009

Необходимо опубликовать новый ответ о переходном процессе, потому что это слишком долго для комментария. Следующий код печатает

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

}

0 голосов
/ 11 ноября 2009

Самый безопасный (и нормальный) способ - это либо прямая инициализация:

private transient MyClass object = new MyClass();

или используя конструктор

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

Ленивая загрузка в геттеры (как вы делали в вашем примере) полезна только в том случае, если конструктор и / или блоки инициализации MyClass делают довольно дорогие вещи, но не безопасны для потоков.

Модификатор transient не имеет никакого значения. Поле пропускается только всякий раз, когда объект собирается сериализоваться.

Редактировать : больше не актуально. Как доказано кем-то другим, они действительно не получают повторную инициализацию при десериализации (хотя интересно, что это произойдет, только если они объявлены static). Я бы продолжил ленивую загрузку или сбросил их через установщики сразу после десериализации.

...