Pao
2006-10-25 07:16:21 UTC
在物件導向當中,如何將物件裡的資料簡易方便的保存或傳輸,
而不用繁雜的訂定格式、解析資料等,不是個簡單的問題。
所幸在Java的世界裡有序列化這方便好用的功能。
輕易的將物件序列化後就可透過各種資料流保存或傳輸。
相信大家也對序列化都很熟悉了。
這邊想提的是最近我寫程式用到序列化時,忽略掉的細節。
「多個有互相參照的序列化物件儲存問題」
假設今天有兩個序列化的類別如下:
public class A implements Serializable
{
public B b;
}
public class B implements Serializable
{
public A a;
}
兩個物件互相參照:
A a = new A();
B b = new B();
a.b = b;
b.a = a;
想當然爾:
System.out.println(a.b == b);
System.out.println(a.b.a == a);
System.out.println(b.a == a);
System.out.println(b.a.b == b);
印出來的是:
true
true
true
true
分別寫入兩個檔案:
FileOutputStream fos = new FileOutputStream("a.object");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(a);
oos.close();
fos = new FileOutputStream("b.object");
oos = new ObjectOutputStream(fos);
oos.writeObject(b);
oos.close();
嗯,沒錯誤發生。
可見互相參考甚至是循環參考對物件的序列化是沒問題的。
在別的程式裡,讀出那兩個物件來:
FileInputStream fis = new FileInputStream("a.object");
ObjectInputStream ois = new ObjectInputStream(fis);
A a = (A)ois.readObject();
fis = new FileInputStream("b.object");
ois = new ObjectInputStream(fis);
B b = (B)ois.readObject();
此時:
System.out.println(a.b == b);
System.out.println(a.b.a == a);
System.out.println(b.a == a);
System.out.println(b.a.b == b);
印出來的是:
false
true
false
true
哎呀!參照居然變了!
那改成都在同一個資料流呢?
物件輸出資料流用同一個再寫一次:
A a = new A();
B b = new B();
a.b = b;
b.a = a;
FileOutputStream fos = new FileOutputStream("objects");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(a);
oos.writeObject(b);
oos.close();
在別的程式裡,讀出那兩個物件來:
FileInputStream fis = new FileInputStream("objects");
ObjectInputStream ois = new ObjectInputStream(fis);
A a = (A)ois.readObject();
B b = (B)ois.readObject();
ois.close();
此時:
System.out.println(a.b == b);
System.out.println(a.b.a == a);
System.out.println(b.a == a);
System.out.println(b.a.b == b);
印出來的是:
true
true
true
true
終於是原先要的結果了...XD
我想,在我們寫程式寫的忙得時候,
往往會忽略一些小細節。
所以發這篇提醒自己也提醒大家,
希望會有所幫助... ^^
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.113.65.151
而不用繁雜的訂定格式、解析資料等,不是個簡單的問題。
所幸在Java的世界裡有序列化這方便好用的功能。
輕易的將物件序列化後就可透過各種資料流保存或傳輸。
相信大家也對序列化都很熟悉了。
這邊想提的是最近我寫程式用到序列化時,忽略掉的細節。
「多個有互相參照的序列化物件儲存問題」
假設今天有兩個序列化的類別如下:
public class A implements Serializable
{
public B b;
}
public class B implements Serializable
{
public A a;
}
兩個物件互相參照:
A a = new A();
B b = new B();
a.b = b;
b.a = a;
想當然爾:
System.out.println(a.b == b);
System.out.println(a.b.a == a);
System.out.println(b.a == a);
System.out.println(b.a.b == b);
印出來的是:
true
true
true
true
分別寫入兩個檔案:
FileOutputStream fos = new FileOutputStream("a.object");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(a);
oos.close();
fos = new FileOutputStream("b.object");
oos = new ObjectOutputStream(fos);
oos.writeObject(b);
oos.close();
嗯,沒錯誤發生。
可見互相參考甚至是循環參考對物件的序列化是沒問題的。
在別的程式裡,讀出那兩個物件來:
FileInputStream fis = new FileInputStream("a.object");
ObjectInputStream ois = new ObjectInputStream(fis);
A a = (A)ois.readObject();
fis = new FileInputStream("b.object");
ois = new ObjectInputStream(fis);
B b = (B)ois.readObject();
此時:
System.out.println(a.b == b);
System.out.println(a.b.a == a);
System.out.println(b.a == a);
System.out.println(b.a.b == b);
印出來的是:
false
true
false
true
哎呀!參照居然變了!
那改成都在同一個資料流呢?
物件輸出資料流用同一個再寫一次:
A a = new A();
B b = new B();
a.b = b;
b.a = a;
FileOutputStream fos = new FileOutputStream("objects");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(a);
oos.writeObject(b);
oos.close();
在別的程式裡,讀出那兩個物件來:
FileInputStream fis = new FileInputStream("objects");
ObjectInputStream ois = new ObjectInputStream(fis);
A a = (A)ois.readObject();
B b = (B)ois.readObject();
ois.close();
此時:
System.out.println(a.b == b);
System.out.println(a.b.a == a);
System.out.println(b.a == a);
System.out.println(b.a.b == b);
印出來的是:
true
true
true
true
終於是原先要的結果了...XD
我想,在我們寫程式寫的忙得時候,
往往會忽略一些小細節。
所以發這篇提醒自己也提醒大家,
希望會有所幫助... ^^
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.113.65.151