重要接口—Serializable接口
原文作者:流氓小伙子
原文地址:java中類實現Serializable接口的原因
背景:
一個java中的類只有實現了Serializable接口,它的對象才是可序列化的。如果要序列化某些類的對象,這些類就必須實現Serializable接口。Serializable是一個空接口,沒有什么具體內容,它的目的只是簡單的標識一個類的對象可以被序列化。源碼如下:
//標識接口:空接口 //標志接口的作用:讓JVM去實現 public interface Serializable{}為什么要實現Serializable接口?
為了保存在內存中的各種對象的狀態(也就是實例變量,不是方法),并且可以把保存的對象狀態再讀出來,這是java中的提供的保存對象狀態的機制—序列化。
在什么情況下需要使用到Serializable接口呢??
- 當想把的內存中的對象狀態保存到一個文件中或者數據庫中時候;?
- 當想用套接字在網絡上傳送對象的時候;?
- 當想通過RMI傳輸對象的時候; ?
serialVersionUID?
serialVersionUID的取值是Java運行時環境根據類的內部細節自動生成的。如果對類的源代碼作了修改,再重新編譯,新生成的類文件的serialVersionUID的取值有可能也會發生變化。類的serialVersionUID的默認值完全依賴于Java編譯器的實現,對于同一個類,用不同的Java編譯器編譯,有可能會導致不同的serialVersionUID,也有可能相同。為了提高serialVersionUID的獨立性和確定性,強烈建議在一個可序列化類中顯示的定義serialVersionUID,為它賦予明確的值。顯式地定義serialVersionUID有兩種用途:?
- 在某些場合,希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有相同的serialVersionUID;?
- 在某些場合,不希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有不同的serialVersionUID。
代碼實現:?在這里 定義一個實現了Serializable接口的Person類
import java.io.Serializable;public class Person implements Serializable {private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;} }再定義一個SerializationUtils類來模擬 序列化和反序列化的過程
import java.io.*;public class SerializationUtils {private static String FILE_NAME = "f:/obj";//序列化 寫的過程public static void write(Serializable s){try {ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(FILE_NAME));objectOutputStream.writeObject(s);objectOutputStream.close();} catch (IOException e) {e.printStackTrace();}}//反序列化 讀的過程public static Object read(){Object obj=null;// 反序列化try {ObjectInput input = new ObjectInputStream(new FileInputStream(FILE_NAME));obj = input.readObject();input.close();} catch (Exception e) {e.printStackTrace();}return obj;} }測試函數
import com.txp.SerializationUtils; import org.junit.Test;public class testSerializable {@Testpublic void testWrite(){Person person=new Person();person.setId(1);person.setName("張丹");SerializationUtils.write(person);}@Testpublic void testRead(){Person p = (Person) SerializationUtils.read();System.out.println(p.getName());} }先運行testWrite()實現序列化持久化,再運行testRead()實現反序列化讀出數據 ,這一次的Person類中沒有給定serialVersionUID,結果會輸出‘張丹’。如果此時給Person類加一個屬性 age,運行testRead(),會拋出會拋出 java.io.InvalidClassException異常。因為JVM在反序列化時,會比較數據流中的serialVersionUID與類的serialVersionUID是否相同,如果相同,則認為類沒有發生改變,可以把數據流load為實例對象;如果不相同,對不起,JVM會拋異常InvalidClassException,這是JVM一個很好的一個校驗機制,確保類的一致性。但是如果顯式給定serialVersionUID(而隱式聲明則是我不聲明,編譯器在編譯的時候幫我生成。),即是 private static final long serialVersionUID = XXL;,修改Person類如下:
public class Person implements Serializable {private static final long serialVersionUID = 1L;private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;} }再進行同樣的操作過程,則不會拋出異常,會打印出結果。但是最好不要這樣操作,要在類修改后,先序列化,再但序列化。確保類的前后一致性。?
參考文章:?
https://www.cnblogs.com/yoohot/p/6019767.html?
https://blog.csdn.net/jaryle/article/details/52598296?
http://www.cnblogs.com/DreamDrive/p/5412931.html
總結
以上是生活随笔為你收集整理的重要接口—Serializable接口的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java常用代码总结
- 下一篇: Java并发—基础操作