JAVA序列化和發序列化
1、什麼是序列化和反序列化
序列化:物件序列化的最主要的用處就是在傳遞和儲存物件的時候,保證物件的完整性和可傳遞性。序列化是把物件轉換成有序位元組流,以便在網路上傳輸或者儲存在本地檔案中。序列化後的位元組流儲存了Java物件的狀態以及相關的描述資訊。序列化機制的核心作用就是物件狀態的儲存與重建。
反序列化:客戶端從檔案中或網路上獲得序列化後的物件位元組流後,根據位元組流中所儲存的物件狀態及描述資訊,通過反序列化重建物件。
2、為什麼需要序列化與反序列化
當兩個程序在進行遠端通訊時,彼此可以傳送各種型別的資料。無論是何種型別的資料,都會以二進位制序列的形式在網路上傳送。傳送方需要把這個物件轉換為位元組序列,才能在網路上傳送;接收方則需要把位元組序列再恢復為物件。其實序列化的目的就是跨程序傳遞格式化資料
3、如何實現序列化與發序列化
只有實現了Serializable和Externalizable介面的類的物件才能被序列化。然後j通過ObjectOutputStream的writeObject方法可對引數指定的obj物件進行序列化,把得到的位元組序列寫到一個目標輸出流中。通過jObjectInputStream的readObject()方法從一個源輸入流中讀取位元組序列,再把它們反序列化為一個物件,並將其返回。那我們先寫個Demo,程式碼如下:
public class Student implements Serializable { private static final long serialVersionUID =1l; 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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } } public class TestSerializeAndDeserialize { public static void main(String[] args) throws Exception { SerializePerson(); Student stu=DeserializePerson(); System.out.println(stu.getName()+" "+stu.getSex()+" "+stu.getAge()); } private static void SerializePerson() throws IOException { Student stu=new Student(); stu.setAge(10); stu.setName("xiaoming"); stu.setSex("man"); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("E:/Student.txt"))); oos.writeObject(stu); System.out.println("Student物件序列化成功"); oos.close(); } private static Student DeserializePerson()throws Exception,IOException{ ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("E:/Student.txt"))); Student stu=(Student)ois.readObject(); System.out.println("Student物件反序列化成功"); return stu; } }
程式執行結果:
4.serialVersionUID的作用
serialVersionUID: 序列化的版本號,凡是實現Serializable介面的類都應有一個表示序列化版本識別符號的靜態變數。如果沒有serialVersionUID會怎麼樣,我們去掉serialVersionUID後再執行程式結果如下:
下面我們在Student類新添一個score屬性,如下:
然後執行反序列操作,此時就會丟擲如下的異常資訊:
Exception in thread "main" java.io.InvalidClassException: com.lg.match.Student; local class incompatible: stream classdesc serialVersionUID = -379872992605699466, local class serialVersionUID = 8365482709425766029
如果新增serialVersionUID,再執行上面操作,執行結果如下:
serialVersionUID的取值是Java執行時環境根據類的內部細節自動生成的。如果對類的原始碼作了修改,再重新編譯,新生成的類檔案的serialVersionUID的取值有可能也會發生變化。類的serialVersionUID的預設值完全依賴於Java編譯器的實現,對於同一個類,用不同的Java編譯器編譯,有可能會導致不同的 serialVersionUID,也有可能相同。為了提高serialVersionUID的獨立性和確定性,強烈建議在一個可序列化類中顯示的定義serialVersionUID,為它賦予明確的值。
顯式地定義serialVersionUID有兩種用途:
1、 在某些場合,希望類的不同版本對序列化相容,因此需要確保類的不同版本具有相同的serialVersionUID;
2、 在某些場合,不希望類的不同版本對序列化相容,因此需要確保類的不同版本具有不同的serialVersionUID。