- 只有自己寫的 Java 程式會用到這些資料 => 加以序列化(serialization)
- 資料需要被其他程式引用 => 存於固定格式的資料媒體中(例如:試算表、資料庫 ..... etc)
2、serialize 後的檔案室很難一般人閱讀的,但比純文字更容易讓程式恢復原本的狀態,也比較安全
3、Serialization 的步驟:
- 建構出 FileOutputStream
- 製作 ObjectOutputStream
- 寫入 object
- 關閉 ObjectOutputStream
4、stream 要兩兩連接才能做出有意義的事情 - 其中一個表示連結,另一個則是要被呼叫
以上面 object serialization 為例,由於 FileOutputStream 是很低階的(連結 stream 通常都很低階),可以直接寫入 byte 至檔案中。
但一般的作法不會直接寫入 byte;此時為了保持良好的 OO 設計,需要以物件層次的觀點來寫入,因此需要高階的 stream,即為上面的 ObjectOutputStream,由 ObjectOutputStream 將 object 轉換為 byte,再由 FileOutputStream 將 byte 寫入至檔案。
5、當 object serialization 進行時,除了該 object 的 instance variable 會進行 serialize,所有被參考的 object 也會進行 serialize,而且是全自動化
6、如果要讓 class 能夠被 serialize,就必須實作 Serializable interface(裡面沒有 method 需要實作,僅為標示之用)
import java.io.*;
//沒有 method 需要實作,只是告訴 JVM 它可以被 serialize
public class Box implements Serializable {
//serialize 後,這兩個值會被保留起來
private int width;
private int height;
public void setWidth(int w) {
width = w;
} //close setWidth
public void setHeight(int h) {
height = h;
} //close setHeight
public static void main(String[] args) {
Box myBox = new Box();
myBox.setWidth(50);
myBox.setHeight(20);
try {
FileOutputStream fs = new FileOutputStream("foo.ser");
ObjectOutputStream os = new ObjectOutputStream(fs); //設定連結 stream
os.writeObject(myBox);
os.close();
} catch(Exception ex) {
ex.printStackTrace();
}
} //close main
} //close Box
7、Serialize 是全有或全無的
若物件參考兼有任何一個 class 沒有實作 Serializable interface,就無法進行 serialize,因為 JVM 必須確定 object 狀態能夠完整被保留
8、如果某個 instance variable 不能或不應該 serialize,就將其標示為 transient
transient 的 instance variable,不論儲存當時的值為何,回復之後都會變成 null(object reference) 或是預設值(primitive type)。
但這樣可能會有問題,因此解決方式可以有兩種:
(1) 當 object 被帶回來時,重新初始化 instance variable
(2) 若 transient instance variable 的值很重要,就需要將它的值保存下來,將 object 帶回來的時後才有辦法復原import java.net.*;
class Chat implements Serializable {
transient String currentID; //此 instance variable 就不會被 serialize 了!
String userName; //這個 instance variable 會被 serialize
//........
//........
}
9、Deserialization 的步驟:
- 建構 FileInputStream
- 建構 ObjectInputStream
- 讀取 object (每次讀出一個 object,讀取順序與當初寫入順序是相同的,次數超過會拋出例外)
- 轉換 object type (回傳的 type 為 Object,因此必須轉換)
- 關閉 ObjectInputStream
10、object deserialization 的過程:
- object 從 stream 中讀取出來
- JVM 透過儲存的資訊判斷 object 的 class type
- JVM 會嘗試尋找並載入 object 所屬的 class,若找不到或無法載入,則會拋出例外
- 新的 object 會被配置在 heap 上,但 constructor 不會被執行(執行就會初始化了)
- 若繼承樹中有包含不可 serialize 的 superclass,則從第一個不可 serialize 的 superclass 開始,全部的 constructor 都會執行(r即為初始化)
- object 的 instance variable 會被還原為 serialize 時的狀態,transient instance variable 會被指派為 null、0、false .... etc
11、正常情況下,不會將 class 也進行 serialize,而會使用 RMI(Remote Method Invocation) 來解決
12、static variable 不會被 serialize,因為所有 object 都是共用同一份 static variable 的值
13、File 物件可以作的事情:(不僅是單純的 file 而已)
- 建構出代表現存檔案的 object => Constructor
- 建立新目錄 => mkdir()
- 列出目錄下的內容 => isDirectory() 、list()
- 取得檔案或目錄的絕對路徑 => getAbsolutePath()
- 刪除目錄或檔案 => delete()
14、buffer 的奧妙在於使用了會提升程式運作的效率
藉由 BufferedWriter 與 FileWriter 的連結,BufferedWriter 可以暫存一堆資料,當 buffer 滿的時後再寫入磁碟,這樣可以減少磁碟操作的次數,將強效率
15、使用「serialVersionUID」可避免因為修改 class 而造成 deserialize 時發生無法正確還原的錯誤 (亦即版本控制)
若要查詢 serialVersionUID,可以使用 JDK 提供的「serialver」程式來查詢
沒有留言:
張貼留言