Serializable接口初探
類通過實(shí)現(xiàn) java.io.Serializable 接口以啟用其序列化功能。未實(shí)現(xiàn)此接口的類將無法使其任何狀態(tài)序列化或反序列化。可序列化類的所有子類型本身都是可序列化的。序列化接口沒有方法或字段,僅用于標(biāo)識(shí)可序列化的語義。
Java的"對象序列化"能讓你將一個(gè)實(shí)現(xiàn)了Serializable接口的對象轉(zhuǎn)換成一組byte,這樣日后要用這個(gè)對象時(shí)候,你就能把這些byte數(shù)據(jù)恢復(fù)出來,并據(jù)此重新構(gòu)建那個(gè)對象了。
要想序列化對象,你必須先創(chuàng)建一個(gè)OutputStream,然后把它嵌進(jìn)ObjectOutputStream。這時(shí),你就能用writeObject( )方法把對象寫入OutputStream了。
writeObject 方法負(fù)責(zé)寫入特定類的對象的狀態(tài),以便相應(yīng)的 readObject 方法可以還原它。通過調(diào)用 out.defaultWriteObject 可以調(diào)用保存 Object 的字段的默認(rèn)機(jī)制。該方法本身不需要涉及屬于其超類或子類的狀態(tài)。狀態(tài)是通過使用 writeObject 方法或使用 DataOutput 支持的用于基本數(shù)據(jù)類型的方法將各個(gè)字段寫入 ObjectOutputStream 來保存的。
讀的時(shí)候,你得把InputStream嵌到ObjectInputStream里面,然后再調(diào)用readObject( )方法。不過這樣讀出來的,只是一個(gè)Object的reference,因此在用之前,還得先下傳。readObject 方法負(fù)責(zé)從流中讀取并還原類字段。它可以調(diào)用 in.defaultReadObject 來調(diào)用默認(rèn)機(jī)制,以還原對象的非靜態(tài)和非瞬態(tài)字段。
? 最后結(jié)果如下:
??? node 0
? node 1
node 2
node 3
? node 4
node5
node 6
class?tree?implements?java.io.Serializable?{
????public?tree?left;
????public?tree?right;
????public?int?id;
????public?int?level;
????private?static?int?count?=?0;
????public?tree(int?depth)?{
????????id?=?count++;
????????level?=?depth;
????????if?(depth?>?0)?{
????????????left?=?new?tree(depth?-?1);
????????????right?=?new?tree(depth?-?1);
????????}
????}
????public?void?print(int?levels)?{
????????for?(int?i?=?0;?i?<?level;?i++)
????????????System.out.print("????");
????????System.out.println("?node??"?+?id);
????????if?(level?<=?levels?&&?left?!=?null)
????????????left.print(levels);
????????if?(level?<=?levels?&&?right?!=?null)
????????????right.print(levels);
????}
????public?static?void?main(String?argv[])?{
????????try?{
????????????/**?*//**//*?創(chuàng)建一個(gè)文件寫入序列化樹。?*/
????????????FileOutputStream?ostream?=?new?FileOutputStream("?tree.tmp?");
????????????/**?*//**//*?創(chuàng)建輸出流?*/
????????????ObjectOutputStream?p?=?new?ObjectOutputStream(ostream);
????????????/**?*//**//*?創(chuàng)建一個(gè)二層的樹。?*/
????????????tree?base?=?new?tree(2);
????????????p.writeObject(base);?//?將樹寫入流中。
????????????p.writeObject("?LiLy?is?惠止南國?");
????????????p.flush();
????????????ostream.close();?//?關(guān)閉文件。
????????????/**?*//**//*?打開文件并設(shè)置成從中讀取對象。?*/
????????????FileInputStream?istream?=?new?FileInputStream("?tree.tmp?");
????????????ObjectInputStream?q?=?new?ObjectInputStream(istream);
????????????/**?*//**//*?讀取樹對象,以及所有子樹?*/
????????????tree?new_tree?=?(tree)?q.readObject();
????????????new_tree.print(2);?//?打印出樹形結(jié)構(gòu)的最上面?2級
????????????String?name?=?(String)?q.readObject();
????????????System.out.println("???"?+?name);
????????}?catch?(Exception?ex)?{
????????????ex.printStackTrace();
????????}
????}
}
可以看到,在序列化的時(shí)候,writeObject與readObject之間的先后順序。readObject將最先write的object read出來。用數(shù)據(jù)結(jié)構(gòu)的術(shù)語來講就姑且稱之為先進(jìn)先出吧!
在序列化時(shí),有幾點(diǎn)要注意的:
1:當(dāng)一個(gè)對象被序列化時(shí),只保存對象的非靜態(tài)成員變量,不能保存任何的成員方法和靜態(tài)的成員變量。
????????2:如果一個(gè)對象的成員變量是一個(gè)對象,那么這個(gè)對象的數(shù)據(jù)成員也會(huì)被保存。
3:如果一個(gè)可序列化的對象包含對某個(gè)不可序列化的對象的引用,那么整個(gè)序列化操作將會(huì)失敗,并且會(huì)拋出一個(gè)NotSerializableException。我們可以將這個(gè)引用標(biāo)記為transient,那么對象仍然可以序列化
還有我們對某個(gè)對象進(jìn)行序列化時(shí)候,往往對整個(gè)對象全部序列化了,比如說類里有些數(shù)據(jù)比較敏感,不希望序列化,一個(gè)方法可以用transient來標(biāo)識(shí),另一個(gè)方法我們可以在類里重寫
private???void??readObject(java.io.ObjectInputStream?stream)??????throws??IOException,?ClassNotFoundException;
private???void??writeObject(java.io.ObjectOutputStream?stream)
??????throws??IOException這二個(gè)方法!
示例:
import?java.io.*;
class?ObjectSerialTest?{
????public?static?void?main(String[]?args)?throws?Exception?{
????????Employee?e1?=?new?Employee("?zhangsan?",?25,?3000.50);
????????Employee?e2?=?new?Employee("?lisi?",?24,?3200.40);
????????Employee?e3?=?new?Employee("?wangwu?",?27,?3800.55);
????????FileOutputStream?fos?=?new?FileOutputStream("?employee.txt?");
????????ObjectOutputStream?oos?=?new?ObjectOutputStream(fos);
????????oos.writeObject(e1);
????????oos.writeObject(e2);
????????oos.writeObject(e3);
????????oos.close();
????????FileInputStream?fis?=?new?FileInputStream("?employee.txt?");
????????ObjectInputStream?ois?=?new?ObjectInputStream(fis);
????????Employee?e;
????????for?(int?i?=?0;?i?<?3;?i++)?{
????????????e?=?(Employee)?ois.readObject();
????????????System.out.println(e.name?+?"?:?"?+?e.age?+?"?:?"?+?e.salary);
????????}
????}
}
class?Employee?implements?Serializable?{
????String?name;
????int?age;
????double?salary;
????transient?Thread?t?=?new?Thread();
????public?Employee(String?name,?int?age,?double?salary)?{
????????this.name?=?name;
????????this.age?=?age;
????????this.salary?=?salary;
????}
????private?void?writeObject(java.io.ObjectOutputStream?oos)?throws?IOException?{
????????oos.writeInt(age);
????????oos.writeUTF(name);
????????System.out.println("?Write?Object?");
????}
????private?void?readObject(java.io.ObjectInputStream?ois)?throws?IOException?{
????????age?=?ois.readInt();
????????name?=?ois.readUTF();
????????System.out.println("?Read?Object?");
????}
}
http://www.blogjava.net/supercrsky/articles/167111.html
轉(zhuǎn)載于:https://www.cnblogs.com/alionxd/articles/3099948.html
總結(jié)
以上是生活随笔為你收集整理的Serializable接口初探的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: int数组,找小于右边所有数,大于左边所
- 下一篇: 魔兽全屏改键工具