對象的輸入輸出流 : 主要的作用是用于寫入對象資訊與讀取對象資訊。 對象資訊一旦寫到檔案上那麼對象的資訊就可以做到持久化了 對象的輸出流: ObjectOutputStream 對象的輸入流: ObjectInputStream
使用:
對象的輸出流将指定的對象寫入到檔案的過程,就是将對象序列化的過程,對象的輸入流将指定序列化好的檔案讀出來的過程,就是對象反序列化的過程。既然對象的輸出流将對象寫入到檔案中稱之為對象的序列化,那麼可想而知對象所對應的class必須要實作Serializable接口。(檢視源碼可得知:Serializable接口沒有任何的方法,隻是作為一個辨別接口存在)。
1、将User類的對象序列化
運作程式得到記事本中存入的資訊:可見已經序列化到記事本中
2、将序列化到記事本的内容反序列化


運作代碼得到的結果:
賬号:酒香逢 密碼:123 OK
但是,如果這時候這個obj.txt是我們項目中一個檔案,而項目到後期在原來User類的基礎上添加成員變量String userName;


這時候如果我們再反序列化,則會引發下面的異常:
Exception in thread "main" java.io.InvalidClassException: xuliehua.User; local class incompatible: stream classdesc serialVersionUID = 2161776237447595412, local class serialVersionUID = -3634244984882257127 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:604) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1601) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369) at xuliehua.Demo1.readObject(Demo1.java:48) at xuliehua.Demo1.main(Demo1.java:32)
異常資訊解讀:
serialVersionUID 是用于記錄class檔案的版本資訊的,serialVersionUID這個數字是JVM(JAVA虛拟界)通過一個類的類名、成員、包名、工程名算出的一個數字。而這時候序列化檔案中記錄的serialVersionUID與項目中的不一緻,即找不到對應的類來反序列化。
3、如果序列化與反序列化的時候可能會修改類的成員,那麼最好一開始就給這個類指定一個serialVersionUID,如果一類已經指定的serialVersionUID,然後 在序列化與反序列化的時候,jvm都不會再自己算這個 class的serialVersionUID了。
去掉剛才添加的成員變量userName;,并且在User類中指定一個serialVersionUID


重新序列化到obj.txt檔案中,然後再類中再将userName添加回來(将上面User類中userName字段解注釋),再一次執行反序列化操作,執行的結果跟之前反序列化的結果是一緻的。可見這樣解決後我們後期修改類也是可行的。
4、如果在User類中再添加成員變量,而這個變量為一個class ,如Address,那麼Address類也必須要實作Serializable接口。


5、最後再提一下關鍵字transient關鍵字,當你不想要某些字段序列化時候,可以用transient關鍵字修飾


最後總結一下對象輸入輸出流使用時需要注意:
1. 如果對象需要被寫出到檔案上,那麼對象所屬的類必須要實作Serializable接口。 Serializable接口沒有任何的方法,是一個辨別接口而已。 2. 對象的反序列化建立對象的時候并不會調用到構造方法的、(這點文中沒有說到,想要驗證的同學在構造方法後面加一句System.out.println("構造方法執行嗎?");,實際上構造方法是不執行的,自然這句話也沒有輸出了) 3. serialVersionUID 是用于記錄class檔案的版本資訊的,serialVersionUID這個數字是通過一個類的類名、成員、包名、工程名算出的一個數字。 4. 使用ObjectInputStream反序列化的時候,ObjeectInputStream會先讀取檔案中的serialVersionUID,然後與本地的class檔案的serialVersionUID 進行對比,如果這兩個id不一緻,反序列則失敗。 5. 如果序列化與反序列化的時候可能會修改類的成員,那麼最好一開始就給這個類指定一個serialVersionUID,如果一類已經指定的serialVersionUID,然後 在序列化與反序列化的時候,jvm都不會再自己算這個 class的serialVersionUID了。 6. 如果一個對象某個資料不想被序列化到硬碟上,可以使用關鍵字transient修飾。 7. 如果一個類維護了另外一個類的引用,則另外一個類也需要實作Serializable接口。