2009-11-11 71 views
2

從類中的任何方法訪問私有瞬態對象字段必須使用某些代碼進行控制。最佳做法是什麼?Java:訪問類中的瞬態對象字段

private transient MyClass object = null; 

內部get方法:

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

瞬態場在系列化丟失,但你只反序列化後需要他們,所以你必須將它們還原到你在的readObject方法需要什麼...

+0

謝謝,但我想讓我的領域暫時,也遲到實例(即與懶惰的getter)。我把它添加到問題。 – mschayna 2009-11-11 13:42:10

0

最安全(正常)的方式將直接對其進行初始化:

private transient MyClass object = new MyClass(); 

或使用干將構造

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

延遲加載(如你在你的例子一樣)是僅當MyClass的構造函數和/或初始化塊執行相當昂貴的操作時纔有用,但它不是線程安全的。

transient修飾符沒有任何區別。只有當對象即將被序列化時,它纔會跳過該字段。

編輯:不再相關。正如其他人所證明的那樣,他們確實沒有重新開始反序列化(不過有趣的想法,但實際上只有在他們被宣佈爲static時纔會發生)。我會繼續使用延遲加載方法,或者在反序列化之後直接通過setter重置它們。

+2

是的,但短暫的領域是默默(預留的readObject()'執行')反序列化過程中設置爲'null' - 這是我想在我的問題來解決什麼。我應該把它添加到我原來的文本中。 – mschayna 2009-11-11 13:37:19

+1

他們沒有設置爲'null',他們只剩下他們的初始值。 – 2009-11-11 13:41:57

+0

@Tom:事實上,它們被設置爲默認值類型,因此對於null爲Object或對於int爲0,例如... – pgras 2009-11-11 13:52:27

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

}