關(guān)于Java序列化的一些高級用法
該說的都在注釋中說完了。直接給程序吧。[java] view plaincopyprint?
package test.javaPuzzler.p5;
import java.io.*;
import java.io.ObjectInputStream.GetField;
import java.io.ObjectOutputStream.PutField;
// 轉(zhuǎn)載請注明來自http://blog.csdn.net/sunxing007
// 一個(gè)類實(shí)現(xiàn)Serializable來表明自己可以被序列化;
// 有一點(diǎn)需要特別注意的是:
// 如果子類實(shí)現(xiàn)了Serializable,而父類沒有,則父類不會被序列化;
public class SerializableObject implements Serializable {
// 生成的序列化版本號會因?yàn)榫幾g環(huán)境,聲明的類名,成員名稱和數(shù)量的變化而不同;
// 也就是說這個(gè)版本號一定程度上記錄著類的定義性的信息,如果類的定義變化了,最好重新生成版本號;
// 如果新的代碼使用了舊的版本號,則在反序列化的時(shí)候,可以兼容讀取舊類的字節(jié)碼而不會報(bào)錯(cuò);
private static final long serialVersionUID = 9038542591452547920L;
public String name;
public String password;
// 如果你不希望某個(gè)非靜態(tài)成員被序列化,可以用transient來修飾它;
public transient int age;
// 靜態(tài)成員不會被序列化,因?yàn)樾蛄谢4娴氖菍?shí)例的狀態(tài)信息,而靜態(tài)成員是類的狀態(tài)信息;
public static int version = 1;
public SerializableObject(String name, String password) {
this.name = name;
this.password = password;
}
// 每個(gè)類可以寫一個(gè)writeObject方法,這個(gè)方法將會負(fù)責(zé)該類自身的序列化過程;
// 比如對于敏感信息如password,可以加密之后再序列化;
// 這個(gè)過程需要用到PutField,它可以指定哪些域會被序列化,怎么序列化(比如加密);
// 如果沒有定義這個(gè)方法,將會調(diào)用ObjectOutputStream 的 defaultWriteObject;
// 你可以注釋掉readObject方法,然后運(yùn)行測試用例來測試密碼是否被加密;
private void writeObject(ObjectOutputStream out) throws IOException {
PutField putFields = out.putFields();
putFields.put("name", name);
// 模擬加密密碼
putFields.put("password", "thePassword:" + password);
out.writeFields();
}
// 每個(gè)類可以寫一個(gè)readObjectb方法,該方法負(fù)責(zé)該類自身的反序列化過程;
// 比如對序列化時(shí)加密后的密碼解密;
// 這個(gè)過程需要用到GetField,他可以具體地讀取每個(gè)域;或執(zhí)行解密動作等等;
// 如果沒有定義這個(gè)方法,將會調(diào)用ObjectInputStream 的 defaultReadObject;
private void readObject(ObjectInputStream in)
throws ClassNotFoundException, IOException {
GetField readFields = in.readFields();
// 讀取到成員的值之后,直接賦給該域,即完成該域的反序列化;
name = (String) readFields.get("name", "defaultName");
// 模擬解密密碼
String encPassword = (String) readFields.get("password",
"thePassword:defaultValue");
password = encPassword.split(":")[1];
}
// 序列化
// 主要用到ObjectOutputStream;
public void save() throws IOException {
FileOutputStream fout = new FileOutputStream("e:obj");
ObjectOutputStream oout = new ObjectOutputStream(fout);
oout.writeObject(this);
oout.close();
fout.close();
}
// 反序列化
// 主要用到ObjectInputStream
public static SerializableObject load() throws IOException,
ClassNotFoundException {
FileInputStream fin = new FileInputStream("e:obj");
ObjectInputStream oin = new ObjectInputStream(fin);
Object o = oin.readObject();
return (SerializableObject) o;
}
@Override
public String toString() {
return "name: " + name + ", password: " + password;
}
// tb測試用例
public static void main(String[] args) throws IOException,
ClassNotFoundException {
SerializableObject so = new SerializableObject(
"http://blog.csdn.net/sunxing007", "123456");
so.save();
System.out.println(so);
System.out.println(SerializableObject.load());
}
}