背景
序列化
在編碼過程中,我們也會遇到將使用的對象信息通過網絡傳輸到另一端,又或者將對象信息保存下來,存儲成文件形式保存在電腦硬盤上,以供下次提取使用,我們把 抽取對象信息並轉化爲二進制形式流的過程稱之爲序列化過程。
持久化
將信息持久化指的是將信息存儲在不易失媒介上,內存上的信息在電腦斷電後都會消失,而諸如硬盤、磁帶等設備上的信息不會丟失,所以稱這些數據是持久的,所以和數據庫相關的層也會被稱爲持久化層,因爲他們的工作就是將數據持久化存儲。
transient 意義
transient,英文名字就是瞬態的意思,意思是這個信息只是暫時在這個特定情況有意義,和計算機中持久的相對,需要持久化的信息代表這個信息在長遠有一定意義。
java中對transient關鍵字的作用有如下描述:
Variables may be marked
transient
to indicate that they are not part of the persistent state of an object. —— 摘自java手冊當類成員字段被表明爲transient時,則表明這個字段信息不具有將其持久保存或轉化的意義。
transient只能用在類字段上,如果加上,表示該字段不需要轉化,否則將其轉化。
Attention:不是所有的對象都能轉化,只有實現了serialiable接口的類成員對象才能轉化
class Point implements Serializable{
int x, y; //這兩個會被序列化
transient float rho, theta; //這兩個字段信息不會被轉化
}
serializable接口
transient關鍵字與serialiable接口 意義區分
java使用serializable接口來標記一個類是否可以序列化。
transient關鍵字則說明了某個字段是否需要序列化。
必須實現了serializable接口的類中再去使用transient關鍵字,否則沒意義啊!畢竟你要先決定這個類可不可以序列化,再去決定需要序列化哪些信息。
serializable的實現
去看java源代碼,發現serializable接口中並沒有任何方法,是一個空的接口。
空的接口沒什麼意義啊,爲什麼要這麼做呢?經查詢,原來這個接口只是起到一個標記的作用,不具有其他意義,他告訴jvm這個類是可以序列化的。
那麼具體的序列化是怎麼實現的呢?
通過ObjectOutputStream和ObjectInputStream兩個類實現。
objectOutputStream.writeObject(object /*參數爲需要序列化的類*/); // 序列化
objectInputStream.readObject(object); // 解序列化
例子
class NameStore implements Serializable{
private String firstName;
private transient String middleName; //這個字段不會被序列化
private String lastName;
public NameStore (String fName, String mName, String lName){
this.firstName = fName;
this.middleName = mName;
this.lastName = lName;
}
public String toString(){
StringBuffer sb = new StringBuffer(40);
sb.append("First Name : ");
sb.append(this.firstName);
sb.append("Middle Name : ");
sb.append(this.middleName);
sb.append("Last Name : ");
sb.append(this.lastName);
return sb.toString();
}
}
public class TransientExample{
public static void main(String args[]) throws Exception {
NameStore nameStore = new NameStore("Steve", "Middle","Jobs");
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("nameStore"));
// writing to object
o.writeObject(nameStore);
o.close();
ArrayList
// reading from object
ObjectInputStream in = new ObjectInputStream(new FileInputStream("nameStore"));
NameStore nameStore1 = (NameStore)in.readObject();
System.out.println(nameStore1);
}
}
輸出:
First Name : Steve Middle Name : null Last Name : Jobs
可見,MiddleName沒有被序列化。
FAQ
-
什麼樣的數據可以序列化,什麼樣的不可以呢?
什麼樣的對象從根本來說都可以序列化,但是有的對象序列化是沒有意義的,比如socket和文件等,所以這些類沒有實現Serializable接口,也就不能序列化。
-
很多類種有SerialVersionUID,它是用來幹嘛的?
這個UID爲每個類生成了一個唯一標識符,如此jvm可以利用這個標識符來比較序列化和解序列化過程中兩個類是不是相同,以確保解序列化時的類加載正確。如果你沒有自己主動生成,jvm會自動幫你制定一個。
參考
1.java規範說明
2.Java: What can and what can’t be serialized?