2011-04-15 48 views
0

我正在閱讀Java中的思考第4版。 有描述transient領域的系列化一個奇怪的解決方法:瞬時字段的Java序列化

import java.io.*; 

public class SerializationTest implements Serializable { 
    private String firstData; 
    //transient field, shouldn't be serialized. 
    transient private String secondData; 

    public SerializationTest(String firstData, String test2) { 
     this.firstData = firstData; 
     this.secondData = test2; 
    } 

    /** 
    * Private method, same signature as in Serializable interface 
    * 
    * @param stream 
    * @throws IOException 
    */ 
    private void writeObject(ObjectOutputStream stream) throws IOException { 
     stream.defaultWriteObject(); 
     stream.writeObject(secondData); 
    } 

    /** 
    * Private method, same signature as in Serializable interface 
    * 
    * @param stream 
    * @throws IOException 
    */ 
    private void readObject(ObjectInputStream stream) 
      throws IOException, ClassNotFoundException { 
     stream.defaultReadObject(); 
     secondData = (String) stream.readObject(); 

    } 

    @Override 
    public String toString() { 
     return "SerializationTest{" + 
       "firstData='" + firstData + '\'' + 
       ", secondData='" + secondData + '\'' + 
       '}'; 
    } 

    public static void main(String[] args) throws IOException, ClassNotFoundException { 
     FileOutputStream fos = null; 
     ObjectOutputStream oos = null; 
     try { 
      fos = new FileOutputStream("object.out"); 
      oos = new ObjectOutputStream(fos); 
      SerializationTest sTest = new SerializationTest("First Data", "Second data"); 
      oos.writeObject(sTest); 
     } finally { 
      oos.close(); 
      fos.close(); 
     } 
     FileInputStream fis = null; 
     ObjectInputStream ois = null; 
     try { 
      fis = new FileInputStream("object.out"); 
      ois = new ObjectInputStream(fis); 
      SerializationTest sTest = (SerializationTest) ois.readObject(); 
      System.out.println(sTest); 
     } finally { 
      ois.close(); 
      fis.close(); 
     } 
     //Output: 
     //SerializationTest{firstData='First Data', secondData='Second data'} 
    } 
} 

正如你所看到的,也有實現的私有方法writeObjectreadObject

的問題是:

爲了什麼的ObjectOutputStream和ObjectInputStream的使用反射來訪問私有方法?

Java中包含了多少這樣的後門?

+3

不是後門,但http://twitteroverflow.com/questions/15496/hidden-features-of-java – OscarRyz 2011-04-15 21:11:07

+0

順便說一句,你的資源處理不正確。標準格式爲:'資源資源=獲取();嘗試{使用(資源); } finally {resource.release(); }'。您應該爲每個資源單獨執行此操作。在Java SE 6中,您可以編寫'try(Resource resource = acquire()){use(resource);在大多數情況下。不需要關閉對象流,除了僅在快樂案例中刷新ObjectOutputStream(也就是說,在「try」的主體中;在finally中的刷新也會在錯誤情況下執行) ,這不是你想要的)。 – 2011-04-15 21:30:55

+0

@Tom:'try(...){'語法已經在Java SE 6中?這對我來說是新的,我認爲這將是隻有7. – 2011-04-15 23:34:12

回答

6

後門?它一直在規範中。這是實現對象的非默認序列化的唯一方法。

非默認序列化使您進入序列化驅動程序的位置。您可以將任何內容寫入輸出流,只要您可以讀取它並在流的另一端構建對象,就可以。

這個人決定序列化瞬態字段的事實不是問題,問題是如果你正在實現自己的序列化方案,你可以做任何你想做的事情。

3

呃,它不是一個「後門」......你實現了一個自定義的序列化,在調用忽略它們的默認序列化之後,將瞬態字段輸出到輸出流。

1

可序列化接口是標記接口。所以它像一個標籤來解釋java編譯器。還有其他標記界面,如Clonable等。有關更多信息,請參閱here。 但是現在使用@annotations的日子更多。