1 對象序列化基本概念
幾乎只要是Java開發就一定會存在有序列化的概念,而正是因爲序列化的概念逐步發展,慢慢也有了更多序列化的標準。
所謂的對象序列化指的是將內存中保存的對象以二進制數據流的形式進行處理,可以實現對象的保存或者是網絡傳輸。
然而並不是所有的對象都可以被序列化,在Java裏面有一個強制性的要求:如果要序列化的對象,那麼對象所在的類一定要實現java.io.Serializable父接口,作爲序列化的標記,這個接口並沒有任何的方法,因爲它描述的是一種類的能力。
範例:定義一個可以被序列化的類
class Person implements Serializable{
private String name;
private int age;
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
此時Person類產生的每一個對象都可以實現二進制的數據傳輸,屬於可以被序列化的程序類。
2 序列化與反序列化處理
有了序列化的支持類之後如果想實現序列化與反序列化的操作則就可以利用以下兩個類完成:
(1)序列化:ObjectOutputStream
|——類定義:
public class ObjectOutputStream
extends OutputStream
implements ObjectOutput, ObjectStreamConstants
|——構造方法:public ObjectOutputStream(OutputStream out) throws IOException
|——操作方法:public final void writeObject(Object obj) throws IOException
(2)反序列化:ObjectInputStream
|——類定義:
public class ObjectInputStream
extends InputStream
implements ObjectInput, ObjectStreamConstants
|——構造方法:public ObjectInputStream(InputStream in) throws IOException
|——操作方法:public final Object readObject() throws IOException, ClassNotFoundException
範例:實現序列化與反序列化
package cn.victor.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class JavaAPIDemo {
private static final File SAVE_FILE = new File("d:" + File.separator + "hy" + File.separator + "temp.person");
public static void main(String[] args) throws Exception{
// saveObject(new Persons("lks", 23));
System.out.println(loadObject());
}
public static void saveObject(Object obj) throws FileNotFoundException, IOException {
ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
oss.writeObject(obj);
oss.close();
}
public static Object loadObject() throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(SAVE_FILE));
Object obj = ois.readObject();
ois.close();
return obj;
}
}
@SuppressWarnings("serial")
class Persons implements Serializable{
private String name;
private int age;
public Persons() {}
public Persons(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
在Java中的對象序列化與反序列化必須使用內部提供的對象操作流,因爲這裏面牽扯到二進制數據的格式,所以不能夠自定義處理,另外如果要想實現一組對象的序列化,則可以使用對象數組完成。
在很多的實際項目的開發過程中,開發者很少能夠見到ObjectOutputStream、ObjectInputStream類的直接操作,因爲會有一些容器幫助開發者自動實現。
3 transient關鍵字
默認情況下當執行了對象序列化的時候會將類中的全部屬性內容進行全部的序列化操作,但是很多情況下有一些屬性可能並不需要序列化的處理,這個時候就可以在屬性定義上使用transient關鍵子來完成。
package cn.victor.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class JavaAPIDemo {
private static final File SAVE_FILE = new File("d:" + File.separator + "hy" + File.separator + "temp.person");
public static void main(String[] args) throws Exception{
// saveObject(new Persons("lks", 23));
System.out.println(loadObject());
}
public static void saveObject(Object obj) throws FileNotFoundException, IOException {
ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
oss.writeObject(obj);
oss.close();
}
public static Object loadObject() throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(SAVE_FILE));
Object obj = ois.readObject();
ois.close();
return obj;
}
}
@SuppressWarnings("serial")
class Persons implements Serializable{
private String name;
private transient int age;
public Persons() {}
public Persons(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
在進行序列化處理的時候name屬性的內容是不會被保存下來的,換言之,讀取的數據name將是其對應數據類型的默認值(null)。如果假設類之中有一些是需要計算保存的屬性內容往往是不需要被序列化的,這個時候就可以使用tansient,但是在實際開發之中大部分需要被序列化的類往往都是簡單Java類,所以這一個關鍵字的出現頻率並不高。