Java的對象的序列化將那些實現(xiàn)了serializable接口的對象轉(zhuǎn)換成一個字節(jié)序列,并能夠在以后將這個字節(jié)序列恢復(fù)為原來的對象
(序列化能通過網(wǎng)絡(luò)進(jìn)行,彌補(bǔ)不同操作系統(tǒng)之間的差異)
簡而言之:
對象序列化就是講object轉(zhuǎn)換成byte序列,反之叫對象的反序列化。
具體步驟:
序列化:
- 創(chuàng)建OutputStream對象
- 封裝在一個ObjectOutputStream對象內(nèi)。
- 調(diào)用writeObject()方法,并將其發(fā)送給OutputStream
String file = "demo/obj.dat";
//1.對象的序列化
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(file));
Student stu = new Student("10001", "張三", 20);
oos.writeObject(stu);
oos.flush();
oos.close();
反序列化:
- 創(chuàng)建InputStream對象
- 封裝在一個ObjectIntputStream對象內(nèi)。
- 調(diào)用readObject()方法,并將其發(fā)送給InputStream
String file = "demo/obj.dat";
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(file));
Student stu = (Student)ois.readObject();
System.out.println(stu);
ois.close();
transient(順時)關(guān)鍵字
當(dāng)我們隊序列化進(jìn)行控制時,可能某個特定子對象不想讓Java的序列化機(jī)制自動保存與恢復(fù)如果子對象表示的是我們不希望將其序列化的敏感信息(如密碼),通常就會面臨這種情況。及時對象中的這些信息是private屬性,一經(jīng)序列化處理,人們就可以通過讀取文件或者攔截網(wǎng)絡(luò)傳輸?shù)姆绞降玫剿?br> 為了能夠加以控制,可以用transient關(guān)鍵字逐個字段地關(guān)閉序列化他的意思是不用麻煩保存或者回復(fù)數(shù)據(jù),我自己會處理好。
示例:
//該元素不會進(jìn)行jvm默認(rèn)的序列化,也可以自己完成這個元素的序列化 private transient int stuage;
可以自己進(jìn)行序列化和反序列化:
實現(xiàn)了Serializable接口的對象,并添加(不是覆蓋或者實現(xiàn))writeObject()和readObject()(private)方法。如此,一旦對象被序列化和反序列化時,會自動調(diào)用這兩個方法,而不是默認(rèn)的反序列化機(jī)制。
此外:在兩個方法內(nèi)部可以分別調(diào)用defaultWriteObject()來執(zhí)行默認(rèn)的writeObject(),defaultReadObject()來執(zhí)行默認(rèn)的readObject()
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
s.defaultWriteObject();//把jvm能默認(rèn)序列化的元素進(jìn)行序列化操作
s.writeInt(stuage);//自己完成stuage的序列化
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException{
s.defaultReadObject();//把jvm能默認(rèn)反序列化的元素進(jìn)行反序列化操作
this.stuage = s.readInt();//自己完成stuage的反序列化操作
}
序列化中子類和父類構(gòu)造函數(shù)的調(diào)用問題
結(jié)論一. 序列化會依次調(diào)用父類構(gòu)造函數(shù)
測試對象:
class Foo implements Serializable{
public Foo(){
System.out.println("foo...");
}
}
class Foo1 extends Foo {
public Foo1(){
System.out.println("foo1...");
}
}
class Foo2 extends Foo1{
public Foo2(){
System.out.println("foo2...");
}
}
class Bar{
public Bar(){
System.out.println("bar");
}
}
class Bar1 extends Bar{
public Bar1(){
System.out.println("bar1..");
}
}
class Bar2 extends Bar1 implements Serializable{
public Bar2(){
System.out.println("bar2...");
}
結(jié)論二. 對子類對象進(jìn)行反序列化操作時, 如果其父類沒有實現(xiàn)序列化接口, 那么其父類的構(gòu)造函數(shù)會被調(diào)用*
測試代碼: