java實體類中實現序列化接口有什么作用


目錄

1. 序言

2. 序列化的目的?

2.1 場景:

3. java實現Serializable接口

4. serialVersionUID 

4.1 private static final long serialVersionUID = 1L; 的意義

5. 為什么保存到數據庫或者文件中要序列化?

1. 序言
實體類是沒必須實現序列化接口的,實現的話可以用於通信之類的。

因為公司用的是JSON所以沒有必要

protostuff 來完成java的序列化和反序列化?

2. 序列化的目的?
為了保存在內存中的各種對象的狀態(也就是實例變量,不是方法),並且可以把保存的對象狀態再讀出來,這是java中的提供的保存對象狀態的機制—序列化。

2.1 場景:
  1、當想把的內存中的對象狀態保存到一個文件中或者數據庫中表(內存到數據庫)
  2、當想用套接字在網絡上傳送對象(網絡傳輸)(或者不同線程之間通訊)
  3、當想通過RMI傳輸對象的時候(分布式傳輸)

3. java實現Serializable接口
public interface Serializable {
}
其實並沒有需要去實現的方法,相當於一個標識,可以被序列化。

一個java中的類只有實現了Serializable接口,它的對象才是可序列化的。

4. serialVersionUID 
serialVersionUID的取值是Java運行時環境根據類的內部細節自動生成的。如果對類的源代碼作了修改,再重新編譯,新生成的類文件的serialVersionUID的取值有可能也會發生變化。

類的serialVersionUID的默認值完全依賴於Java編譯器的實現,對於同一個類,用不同的Java編譯器編譯,有可能會導致不同的serialVersionUID,也有可能相同。為了提高serialVersionUID的獨立性和確定性,強烈建議在一個可序列化類中顯示的定義serialVersionUID,為它賦予明確的值。
 

顯式地定義serialVersionUID有兩種用途: 
  a. 在某些場合,希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有相同的serialVersionUID; 
  b. 在某些場合,不希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有不同的serialVersionUID。

4.1 private static final long serialVersionUID = 1L; 的意義
語句本身可能就是顯示指定了UID的值,但是為什么看項目中都是給定了1L呢?

首先,不給定的話因為不同的JVM之間的序列化算法是不一樣的,不同的JDK也可能不一樣,不利於程序的移植,可能會讓反序列化失敗。

實現java.io.Serializable這個接口是為序列化,serialVersionUID 用來表明實現序列化類的不同版本間的兼容性。如果你修改了此類, 要修改此值。否則以前用老版本的類序列化的類恢復時會出錯。

 

但是為什么好多都給定的是1呢?

你可以隨便寫一個,在Eclipse中它替你生成一個,有兩種生成方式: 一個是默認的1L,比如:private static final long serialVersionUID = 1L; 一個是根據類名、接口名、成員方法及屬性等來生成一個64位的哈希字段,比如:private static final long serialVersionUID = -8940196742313994740L;之類的。

5. 為什么保存到文件中要序列化?
當我們想把的內存中的對象狀態保存到一個文件中或者數據庫中時候,Serializable接口能幫我們做些什么?

  如上所述,讀寫對象會有什么問題呢?比如:我要將對象寫入一個磁盤文件而后再將其讀出來會有什么問題嗎?別急,其中一個最大的問題就是對象引用!舉個例子來說:假如我有兩個類,分別是A和B,B類中含有一個指向A類對象的引用,現在我們對兩個類進行實例化{ A a = new A(); B b = new B(); },這時在內存中實際上分配了兩個空間,一個存儲對象a,一個存儲對象b,接下來我們想將它們寫入到磁盤的一個文件中去,就在寫入文件時出現了問題!因為對象b包含對對象a的引用,所以系統會自動的將a的數據復制一份到b中,這樣的話當我們從文件中恢復對象時(也就是重新加載到內存中)時,內存分配了三個空間,而對象a同時在內存中存在兩份,想一想后果吧,如果我想修改對象a的數據的話,那不是還要搜索它的每一份拷貝來達到對象數據的一致性,這不是我們所希望的!

   以下序列化機制的解決方案:

  1.保存到磁盤的所有對象都獲得一個序列號(1, 2, 3等等)

  2.當要保存一個對象時,先檢查該對象是否被保存了。

  3.如果以前保存過,只需寫入"與已經保存的具有序列號x的對象相同"的標記,否則,保存該對象通過以上的步驟序列化機制解決了對象引用的問題!

  在對對象進行實例化的過程中相關注意事項
  a)序列化時,只對對象的狀態進行保存,而不管對象的方法;
  b)當一個父類實現序列化,子類自動實現序列化,不需要顯式實現Serializable接口;
  c)當一個對象的實例變量引用其他對象,序列化該對象時也把引用對象進行序列化;
  d)並非所有的對象都可以序列化,至於為什么不可以,有很多原因了,比如:
  1.安全方面的原因,比如一個對象擁有private,public等field,對於一個要傳輸的對象,比如寫到文件,或者進行RMI傳輸  等等,在序列化進行傳輸的過程中,這個對象的private等域是不受保護的。
  2. 資源分配方面的原因,比如socket,thread類,如果可以序列化,進行傳輸或者保存,也無法對他們進行重新的資源分配,而且,也是沒有必要這樣實現。

原文鏈接:https://blog.csdn.net/pmdream/article/details/90175448


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM