- Java 序列化:指的是將Java對象通過流的方式寫到磁盤上將其保存起來尿这。
最初是為了支持RMI(Remote Method Invocation)遠(yuǎn)程方法調(diào)用,它可以實現(xiàn)其它計算機訪問該對象就像自己的計算機訪問該對象那么的簡單碟摆,還有就是JavaBean這種對象在設(shè)計階段啟動時的狀態(tài)配置叨橱。一般將對象或者異常輸出到文件作持久化或者通過網(wǎng)絡(luò)傳輸?shù)狡渌嬎銠C進行處理。
- Java反序列化:序列化的逆過程嘉裤,將序列化到文件中的內(nèi)容反序列化成對象。
程序?qū)崿F(xiàn)
class Student implements Serializable {
public static int week;
private String name;
private int age;
// 使用transient關(guān)鍵字后不會序列化該字段
private transient String homeWork;
public Student(String name, int age, String homeWork, int weekday) {
this.name = name;
this.age = age;
this.homeWork = homeWork;
week = weekday;
}
@Override
public String toString() {
return "Student [" + "name=" + name + ", "
+ "age=" + age + ", homeWork=" + homeWork + ", "
+ "static week=" + week + "]";
}
}
private static void serializeStudent() throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/student"));
oos.writeObject(new Student("小明", 10, "做數(shù)學(xué)題", 2));
oos.close();
}
private static Student deserializeStudent() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/student"));
Student stu = (Student) ois.readObject();
ois.close();
return stu;
}
第一次測試
public static void main(String[] args) throws IOException, ClassNotFoundException {
serializeStudent();
System.out.println(deserializeStudent());//Student [name=小明, age=10, homeWork=null, static week=2]
}
嗯。仇让。看似很完美丧叽,先別急,接著第二次測試假瞬。迂尝。
public static void main(String[] args) throws IOException, ClassNotFoundException {
//serializeStudent();
//因為之前已經(jīng)序列化并且保存到磁盤了,現(xiàn)在直接進行反序列化操作
System.out.println(deserializeStudent());//Student [name=小明, age=10, homeWork=null, static week=0]
}
看到這里琴许,有沒有發(fā)覺程序結(jié)果發(fā)生了小小的變化溉躲?沒錯那就是week這個靜態(tài)變量。說到這里可能有人就有疑問了锻梳,那么之前的那個week怎么就沒錯呢?這個其實是因為static變量在經(jīng)類加載器加載過后會永駐內(nèi)存邦鲫,事實上不管你是否進行序列化和反序列化它都是那個值,也就是2庆捺。但第二次測試后,Jvm重新運行當(dāng)然要重新加載Student了捉腥,因為序列化并不會對static起作用你画,所以week這個變量并沒有保存,那么week自然就是默認(rèn)值坏匪,也就是0,
防止序列化和反序列化敦迄,當(dāng)調(diào)用writeObject(Object obj)方法時會檢查該對象是否具有writeObject()和readObject()方法如果有凭迹,則通過反射進行調(diào)用。
//防止序列化
private void writeObject(ObjectOutputStream os )throws IOException {
throw new RuntimeException("");
}
//防止反序列化
private void readObject(ObjectInputStream in) throws IOException {
throw new RuntimeException();
}