一、 概念
序列化 反序列化 概念可分為 狹義 廣義(個人觀點)
狹義概念:
指javabean實作serializable 或 externalizable接口 進行byte流和javabean之間互轉。
java 串行化技術可以使你将一個對象的狀态寫入一個byte 流裡,并且可以從其它地方把該byte 流 裡的資料讀出來,重新構造一個相同的對象。
廣義的概念:
将javabean對象轉換為便于儲存或傳輸的形式,如轉換為xml 或 json等
實作這個技術有很多種常見有 1 java 通過實作序列化接口 2 javabean轉換為xml 3 javabean轉換為json
二 、java對象實作序列化的條件:(java内在序列化機制進行說明)
1)對象要實作serializable 或 externalizable接口 如果父類不進行序列化(沒有實作接口)則需要提供無參構造函數
2)序列化 和反序列化對象 serialversionuid 要一緻
最好顯示聲明 serialversionuid = -8832150336623636846l; 因為同一個對象在不同jvm中可能計算出的值是不一緻的
3)序列化和反序列化的類名要一直 以及包路徑也要一緻
4)如果要求類名不一緻則可以自己寫方法進行轉換 或 寫 objectinput子類 在下面會進一步介紹
用途:利用對象的串行化實作儲存應用程式的目前工作狀态,下次再啟動的時候将自動地恢複到上次執行的狀态
更常用的用途是用于傳輸資料。
三.實作serializable接口
objectoutputstream隻能對serializable接口的類的對象進行序列化。
預設情況下,objectoutputstream按照預設方式序列化,這種序列化方式僅僅對對象的非transient的執行個體變量進行序列化,而不會序列化對象的transient的執行個體變量,也不會序列化靜态變量。
當objectoutputstream按照預設方式序列化時,具有如下特點
1)沒有實作接口的父類則不會序列化
2)聲明為static和transient類型的成員資料不能被串行化。因為static代表類的狀态, transient代表對象的臨時資料;
當objectoutputstream按照預設方式反序列化時,具有如下特點:
1) 如果在記憶體中對象所屬的類還沒有被加載,那麼會先加載并初始化這個類。如果在classpath中不存在相應的類檔案,那麼會抛出classnotfoundexception;
2) 實作了序列化的對象在反序列化時不會調用類的任何構造方法。沒有實作接口的父類則會調用父類無參構造構造器
注意:在預設的轉換下序列化和反序列化對象名 稱和路徑名要一緻,但對象屬性可以不一緻。
對于父類是否實作序列化可以不一緻,但同樣的父類名(包名也一緻)都實作序列化那麼serialversionuid就必須一樣
有些對象中包含一些敏感資訊,這些資訊不宜對外公開。如果按照預設方式對它們序列化,那麼它們的序列化資料在網絡上傳輸時,可能會被不法份子竊取。
對于這類資訊,可以對它們進行加密後再序列化,在反序列化時則需要解密,再恢複為原來的資訊。
這就要求對讀出和寫入的流進行處理,java中提供如下方法 ,以objectinputstream為例
可以寫一個objectinput子類
/**
* 寫此類時
* 隻能調用 父類的無參構造器 因為父類無參構造器會将enableoverride置為true
* objectinput此時在調用父類的readobject()方法時 會根據enableoverride調用readobjectoverride()
* 同樣objectout writeobject() 調用readobjectoverride()
* 在此方法裡重寫readobjectoverride() writeobjectoverride() 在序列化和反序列化時
* 對流進行特殊處理
*
*/
public class objectinputstreamnew extends objectinputstream{
private static objectinput in;
public objectinputstreamnew(fileinputstream file) throws ioexception, securityexception {
super();
this.in = new objectinputstream(file);
}
@override
public object readobjectoverride(){
try {
object ob = in.readobject();
propertyutils.copyproperties(this,ob);
} catch (exception e) {
e.printstacktrace();
}
return this;
}
}
四. 可序列化類的不同版本的序列化相容性
凡是實作serializable接口的類都有一個表示序列化版本辨別符的靜态變量:
private static final long serialversionuid;
以上serialversionuid的取值是java運作時環境根據類的内部細節自動生成的。如果對類的源代碼作了修改,再重新編譯,新生成的類檔案的serialversionuid的取值有可能也會發生變化。
類的serialversionuid的預設值完全依賴于java編譯器的實作,對于同一個類,用不同的java編譯器編譯,有可能會導緻不同的serialversionuid,也有可能相同。為了提高哦啊serialversionuid的獨立性和确定性,強烈建議在一個可序列化類中顯示的定義serialversionuid,為它賦予明确的值。顯式地定義serialversionuid有兩種用途:
1) 在某些場合,希望類的不同版本對序列化相容,是以需要確定類的不同版本具有相同的serialversionuid;
2) 在某些場合,不希望類的不同版本對序列化相容,是以需要確定類的不同版本具有不同的serialversionuid。
public static void serializabletest() throws exception{
single.one.dog dogone = new single.one.dog();
dogone.setname("tomcat");
dogone.setsex("m");
fileoutputstream fos = new fileoutputstream("c:/zkg/services.txt");
objectoutputstream oos = new objectoutputstream(fos);
oos.writeobject(dogone);
oos.close();
fileinputstream in = new fileinputstream("c:/zkg/services.txt");
objectinputstream ois = new objectinputstream(in);
dogtwo = (single.one.dog)ois.readobject();
system.out.println(dogtwo.getname());
ois.close();