什么是序列化、反序列化?
Serialization(序列化)是一種將對象以一連串的字節描述的過程;
反序列化deserialization是一種將這些字節重建成一個對象的過程。
序列化通俗一點說就是能將Java對象轉化成文本文件的一種方式。
什么情況下需要序列化 ?
a)當你想把的內存中的對象保存到一個文件中或者數據庫中時候;
b)當你想用套接字在網絡上傳送對象的時候;
c)當你想通過RMI傳輸對象的時候;
如何實現序列化 ?
將需要序列化的類實現Serializable接口就可以了。
public class ArrayList<E> implements java.io.Serializable{
}
ArrayList 這個類就實現了序列化,當然實現它的類很多,此處只舉個例子。
jdk源碼如下:
public interface Serializable {
}
是的,啥也沒有,Serializable接口中沒有任何方法,可以理解為一個標記,即表明這個類可以序列化。
所謂的Serializable,就是java提供的通用數據保存和讀取的接口。至於從什么地方讀出來和保存到哪里去都被隱藏在函數參數的背后了。這樣子,任何類型只要實現了Serializable接口,就可以被保存到文件中,或者作為數據流通過網絡發送到別的地方。也可以用管道來傳輸到系統的其他程序中。這樣子極大的簡化了類的設計。只要設計一個保存一個讀取功能就能解決上面說得所有問題。
序列化前和序列化后的對象的關系
是 "=="還是equal? or 是淺復制還是深復制?
答案:深復制,反序列化還原后的對象地址與原來的的地址不同
序列化前后對象的地址不同了,但是內容是一樣的,而且對象中包含的引用也相同。換句話說,通過序列化操作,我們可以實現對任何可Serializable對象的”深度復制(deep copy)"——這意味着我們復制的是整個對象網,而不僅僅是基本對象及其引用。對於同一流的對象,他們的地址是相同,說明他們是同一個對象,但是與其他流的對象地址卻不相同。也就說,只要將對象序列化到單一流中,就可以恢復出與我們寫出時一樣的對象網,而且只要在同一流中,對象都是同一個。
transient
它的作用簡單一句話,就是屏蔽該關鍵字修飾變量的序列化。
Java的serialization提供了一種持久化對象實例的機制。當持久化對象時,可能有一個特殊的對象數據成員,我們不想用serialization機制來保存它。為了在一個特定對象的一個域上關閉serialization,可以在這個域前加上關鍵字transient。當一個對象被序列化的時候,transient型變量的值不包括在序列化的表示中,然而非transient型的變量是被包括進去的。
package person.peng; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class MyTest implements Serializable { private static final long serialVersionUID = 1L; private String name="pengxuxiangfei"; private int age=22; public static void main(String[] args) {//以下代碼實現序列化 try { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("my.out"));//輸出流保存的文件名為 my.out ;ObjectOutputStream能把Object輸出成Byte流 MyTest myTest=new MyTest(); oos.writeObject(myTest); oos.flush(); //緩沖流 oos.close(); //關閉流 } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } fan();//調用下面的 反序列化 代碼 } public static void fan()//反序列的過程 { ObjectInputStream oin = null;//局部變量必須要初始化 try { oin = new ObjectInputStream(new FileInputStream("my.out")); } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } MyTest mts = null; try { mts = (MyTest ) oin.readObject();//由Object對象向下轉型為MyTest對象 } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } System.out.println("name="+mts.name); System.out.println("age="+mts.age); } }
總結:
a)當一個父類實現序列化,子類自動實現序列化,不需要顯式實現Serializable接口;
b)當一個對象的實例變量引用其他對象,序列化該對象時也把引用對象進行序列化;
c) static,transient后的變量不能被序列化;