為什麼要實現serializable介面作用
阿新 • • 發佈:2019-02-01
序列化,就是把物件轉化為位元組流,才能進行網路傳輸。
把該位元組序列儲存起來(例如:儲存在一個檔案裡),以後可以隨時將該位元組序列恢復為原來的物件。甚至可以將該位元組序列放到其他計算機上或者通過網路傳輸到其他計算機上恢復,只要該計算機平臺存在相應的類就可以正常恢復為原來的物件。
具體實現:
要序列化一個物件,先要建立某些OutputStream物件,然後將其封裝在一個ObjectOutputStream物件內,再呼叫writeObject()方法即可序列化一個物件;反序列化也類似。
import java.io.*;
public class Person implements Serializable {
private String userName;
private String password;
public Person(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String toString() {
return "userName:" + userName + " password:" + password;
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//序列化一個物件(儲存到一個檔案)
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.out"));
oos.writeObject("Save a object:\n");
oos.writeObject(new Person("Bruce", "123456"));
oos.close();
//反序列化,將該物件恢復(儲存到一個檔案)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.out"));
String s = (String)ois.readObject();
Person p = (Person)ois.readObject();
System.out.println(s + p);
//序列化一個物件(儲存到位元組陣列)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos2 = new ObjectOutputStream(baos);
oos2.writeObject("Save another object:\n");
oos2.writeObject(new Person("Phil", "654321"));
oos2.close();
//反序列化,將該物件恢復(儲存到位元組陣列)
ObjectInputStream ois2 = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
s = (String)ois2.readObject();
p = (Person)ois2.readObject();
System.out.println(s + p);
}
}
//輸入如下資訊
Save a object:
userName:Bruce password:123456
Save another object:
userName:Phil password:654321
transient關鍵字:
自動序列化將物件的所有欄位都持久化了,有時候需要對某些欄位不進行自動化(如密碼,因為序列化會暴光密碼資訊),這個時候可以使用transient關鍵字(只能和Serializable物件一起使
用),其作用是不序列化某些欄位。將Person類的欄位改為如下定義,再執行上面的程式:
private String userName;
private transient String password;
//輸入如下資訊
Save a object:
userName:Bruce password:null
Save another object:
userName:Phil password:null
控制序列化欄位,甚至該欄位是被transient修飾的欄位也能將其序列化。手動序列化需要新增兩個私有(private)方法(writeObject()和readObject()),在該私有方法中控制序列花欄位。
import java.io.*;
public class Person implements Serializable {
private String userName;
private transient String password;
public Person(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String toString() {
return "userName:" + userName + " password:" + password;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject(); //序列化所有非transient欄位,必須是該方法的第一個操作
out.writeObject(password); //序列化transient欄位
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject(); //反序列化所有非transient欄位,必須是該方法的第一個操作
password = (String)in.readObject(); //反序列化transient欄位
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//序列化一個物件(儲存到一個檔案)
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.out"));
oos.writeObject("Save a object:\n");
oos.writeObject(new Person("Bruce", "123456"));
oos.close();
//反序列化,將該物件恢復(儲存到一個檔案)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.out"));
String s = (String)ois.readObject();
Person p = (Person)ois.readObject();
System.out.println(s + p);
}
}
//輸入如下資訊
Save a object:
userName:David password:13579
控制序列化欄位還可以使用Externalizable介面替代Serializable藉口。此時需要定義一個預設構造器,否則將為得到一個異常(java.io.InvalidClassException: Person; Person; no
valid constructor);還需要定義兩個方法(writeExternal()和readExternal())來控制要序列化的欄位。
import java.io.*;
public class Person implements Externalizable {
private String userName;
private String password;
public Person() {
System.out.println("default constructor invoked!");
}
public Person(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String toString() {
return "userName:" + userName + " password:" + password;
}
public void writeExternal(ObjectOutput out) throws IOException {
//序列化欄位
out.writeObject(userName);
out.writeObject(password);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
//反序列化欄位
userName = (String)in.readObject();
password = (String)in.readObject();
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//序列化一個物件(儲存到一個檔案)
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.out"));
oos.writeObject("Save a object:\n");
oos.writeObject(new Person("Leo", "1984"));
oos.close();
//反序列化,將該物件恢復(儲存到一個檔案)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.out"));
String s = (String)ois.readObject();
Person p = (Person)ois.readObject();
System.out.println(s + p);
}
}
//輸入如下資訊
default constructor invoked!
Save a object:
userName:Leo password:1984
以上方式只能恢復成Java物件,如果想要恢復成其他物件(如C++物件),那就要將Java物件轉換為XML格式,這樣可以使其被各種平臺和各種語言使用。可以使用隨JDK一起釋出的javax.xam.*類庫,或者使用開源XOM類庫(可以從www.xom.nu下載並獲得文件)。