什麼叫序列化和反序列化?
序列化:對象轉化爲字節序列的過程叫做對象的序列化
反序列化:字節序列恢復爲對象的過程叫做對象的反序列化
爲啥要序列化?(序列化的用途)
-需要將對象永久的保存在硬盤中(比如Session對象)
-網絡傳輸對象的序列(網絡中的二進制序列)
過程:
序列化的過程:創建一個對象輸出流對象,調用對象的writeObject()函數
反序列化的過程,創建一個對象輸入流,調用readObject()函數
例子:
package Note; import java.io.*; /** * @author yintianhao * @createTime 20190218 21:46 * @description 序列化 */ public class People implements Serializable { //序列化id private static final long serialVersionUID = -5809782578272943999L; private int age; private String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static void main(String[] args) throws IOException,ClassNotFoundException { //序列化 People one = new People(); one.setAge(5); one.setName("張三"); ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(new File("G:/test.txt"))); stream.writeObject(one); stream.close(); //反序列化 ObjectInputStream stream1 = new ObjectInputStream(new FileInputStream(new File("G:/test.txt"))); People two = (People) stream1.readObject(); System.out.println("Name = "+two.getName()+"--age = "+two.getAge()); stream1.close(); } }
檢驗一下G盤是否有這個test.txt
再看Console
那麼問題來了:serialVersionUID是幹啥的?
看字面上的意思就是版本號嘛,那麼這個版本號是幹啥的呢
那麼就有必要了解一下序列化的過程了:
序列化操作的時候系統會把當前類的serialVersionUID寫入到序列化文件中,當反序列化時系統會去檢測文件中的serialVersionUID,判斷它是否與當前類的serialVersionUID一致,如果一致就說明序列化類的版本與當前類版本是一樣的,可以反序列化成功,否則失敗。
當然這裏是我自己指定的serialVersionUID,如果這裏我們不寫也是沒問題的,因爲如果我們自己沒定義serialVersionUID
jdk會自行給我們生成一個serialVersionUID,但是一般情況IDE會報個警告,不知道爲啥IDEA沒報,但是Eclipse是報了...
第一句是生成默認的版本ID,值爲
第二句是根據類的類名信息等生成的,值爲
但是如果我們不指定ID,那麼,如果我們修改了類中的信息,比如增加或者刪除某個屬性,那麼我們在反序列化之前的
對象的時候就會報錯,因爲這個修改後的類的serialVersionUID已經變了,所以不能反序列化第一次的對象
打個比方增加一個性別sex的選項,然後爲了驗證把之前的序列化的過程去掉,看改完後的這個能不能反序列化之前的
代碼如下:
package Note; import java.io.*; /** * @author yintianhao * @createTime 20190218 21:46 * @description 序列化 */ public class People implements Serializable { //序列化id private int age; private String name; private String sex; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static void main(String[] args) throws IOException,ClassNotFoundException { //反序列化 ObjectInputStream stream1 = new ObjectInputStream(new FileInputStream(new File("G:/test.txt"))); People two = (People) stream1.readObject(); System.out.println("Name = "+two.getName()+"--age = "+two.getAge()); stream1.close(); } }
運行,就報錯了
Exception in thread "main" java.io.InvalidClassException: Note.People; local class incompatible: stream classdesc serialVersionUID = 8716394284034362776, local class serialVersionUID = 5389077117487999490
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at Note.People.main(People.java:37)
這裏這個ID是由JDK的生成的,根據類的一些細節信息生成,具體怎麼生成的我們不管,但是像剛纔那樣我們是不願看見的,因爲不同的Java編譯器可能生成的
ID就不一樣,所以還是強烈建議自定義一個明確的serialVersionUID
參考博客:https://www.cnblogs.com/xdp-gacl/p/3777987.html
https://www.cnblogs.com/duanxz/p/3511695.html