本文的參考文章:https://www.cnblogs.com/szlbm/p/5504166.html
平時我們在Java內存中的對象,是無法進行IO操作或者網絡通信的,因爲在進行IO操作或者網絡通信的時候,人家根本不知道內存中的對象是個什麼東西,因此必須將對象以某種方式表示出來,即存儲對象中的狀態。一個Java對象的表示有各種各樣的方式,Java本身也提供給了用戶一種表示對象的方式,那就是序列化。換句話說,序列化只是表示對 象的一種方式而已。
序列化:將一個對象轉換成一串二進制表示的字節數組,通過保存或轉移這些字節數據來達到持久化的目的。
反序列化:將字節數組重新構造成對象。
默認實現序列化的方法:
序列化只需要實現java.io.Serializable接口就可以了。序列化的時候有一個serialVersionUID參數,Java序列化機制是通過在運行時判斷類的serialVersionUID來驗證版本一致性的。 在進行反序列化,Java虛擬機會把傳過來的字節流中的serialVersionUID和本地相應實體類的serialVersionUID進行比較, 如果相同就認爲是一致的實體類,可以進行反序列化,否則Java虛擬機會拒絕對這個實體類進行反序列化並拋出異常。
如果實現 java.io.Serializable接口的實體類沒有顯式定義一個名爲serialVersionUID、類型爲long的變量時,Java序列化 機制會根據編譯的.class文件自動生成一個serialVersionUID,如果.class文件沒有變化,那麼就算編譯再多 次,serialVersionUID也不會變化。
java實現默認的序列化方法就是ObjectOutputStream的defaultWriteObject方法和ObjectInputStream的defaultReadObject方法。
public class SerializableObject implements Serializable
{
private static final long serialVersionUID = 1L;
private String str0;
private transient String str1;
private static String str2 = "abc";
public SerializableObject(String str0, String str1)
{
this.str0 = str0;
this.str1 = str1;
}
public String getStr0()
{
return str0;
}
public String getStr1()
{
return str1;
}
}
public static void main(String[] args) throws Exception
{
File file = new File("D:" + File.separator + "s.txt");
OutputStream os = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(new SerializableObject("str0", "str1"));
oos.close();
InputStream is = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(is);
SerializableObject so = (SerializableObject)ois.readObject();
System.out.println("str0 = " + so.getStr0());
System.out.println("str1 = " + so.getStr1());
ois.close();
}
輸出結果爲:
str0 = str0
str1 = null
原因是:str1被關鍵字transient修飾了,所以他並沒有被序列化,所以結果爲null。
Java中transient關鍵字的作用,簡單地說,就是讓某些被修飾的成員屬性變量不被序列化,這一看好像很好理解,就是不被序列化,那麼什麼情況下,一個對象的某些字段不需要被序列化呢?如果有如下情況,可以考慮使用關鍵字transient修飾:
1、類中的字段值可以根據其它字段推導出來,如一個長方形類有三個屬性:長度、寬度、面積(示例而已,一般不會這樣設計),那麼在序列化的時候,面積這個屬性就沒必要被序列化了;
2、看具體業務需求;
其目的主要是節省存儲空間。可能還有壞處(有些字段可能需要重新計算,初始化什麼的),總的來說,利大於弊。
進行序列化、反序列化時,虛擬機會首先試圖調用對象裏的writeObject和readObject方法,進行用戶自定義的序列化和反序列化。如果沒有這 樣的方法,那麼默認調用的是ObjectOutputStream的defaultWriteObject以及ObjectInputStream的 defaultReadObject方法。換言之,利用自定義的writeObject方法和readObject方法,用戶可以自己控制序列化和反序列 化的過程。
具體實現參考文章:https://www.cnblogs.com/szlbm/p/5504166.html
序列化的學習就解釋了爲什麼我在做springboot項目的過程中需要將javabean實現序列化接口Serializable,其目的就是爲了對象信息能在網絡中傳輸。
更多參考資料:https://www.cnblogs.com/chenpi/p/6185773.html