摘要:序列化機制使得對象可以脫離程序的運行而獨立存在。普通序列化接口是一個標記接口,不用實現(xiàn)任何方法。如果此對象已經(jīng)序列化過,則直接輸出編號即可。圖示上述序列化過程。
一、序列化的含義、意義及使用場景二、序列化實現(xiàn)的方式1、Serializable1.1 普通序列化1.2 成員是引用的序列化1.3 同一對象序列化多次的機制1.4 java序列化算法潛在的問題1.5 可選的自定義序列化2、Externalizable:強制自定義序列化3、兩種序列化對比三、序列化版本號serialVersionUID四、總結(jié)
一、序列化的含義、意義及使用場景如果需要將某個對象保存到磁盤上或者通過網(wǎng)絡(luò)傳輸,那么這個類應(yīng)該實現(xiàn)Serializable接口或者Externalizable接口之一。
Serializable接口是一個標記接口,不用實現(xiàn)任何方法。一旦實現(xiàn)了此接口,該類的對象就是可序列化的。
步驟一:創(chuàng)建一個ObjectOutputStream輸出流;
步驟二:調(diào)用ObjectOutputStream對象的writeObject輸出可序列化對象。
public class Person implements Serializable {
private String name;
private int age;
//我不提供無參構(gòu)造器
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name=" + name + +
", age=" + age +
};
}
}
public class WriteObject {
public static void main(String[] args) {
try (//創(chuàng)建一個ObjectOutputStream輸出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"))) {
//將對象序列化到文件s
Person person = new Person("9龍", 23);
oos.writeObject(person);
} catch (Exception e) {
e.printStackTrace();
}
}
}
步驟一:創(chuàng)建一個ObjectInputStream輸入流;
步驟二:調(diào)用ObjectInputStream對象的readObject()得到序列化的對象。
我們將上面序列化到person.txt的person對象反序列化回來
public class Person implements Serializable {
private String name;
private int age;
//我不提供無參構(gòu)造器
public Person(String name, int age) {
System.out.println("反序列化,你調(diào)用我了嗎?");
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name=" + name + +
", age=" + age +
};
}
}
public class ReadObject {
public static void main(String[] args) {
try (//創(chuàng)建一個ObjectInputStream輸入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"))) {
Person brady = (Person) ois.readObject();
System.out.println(brady);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//輸出結(jié)果
//Person{name=9龍, age=23}
waht);
如果一個可序列化的類的成員不是基本類型,也不是String類型,那這個引用類型也必須是可序列化的;否則,會導(dǎo)致此類不能序列化。
看例子,我們新增一個Teacher類。將Person去掉實現(xiàn)Serializable接口代碼。
public class Person{
//省略相關(guān)屬性與方法
}
public class Teacher implements Serializable {
private String name;
private Person person;
public Teacher(String name, Person person) {
this.name = name;
this.person = person;
}
public static void main(String[] args) throws Exception {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("teacher.txt"))) {
Person person = new Person("路飛", 20);
Teacher teacher = new Teacher("雷利", person);
oos.writeObject(teacher);
}
}
}
我們看到程序直接報錯,因為Person類的對象是不可序列化的,這導(dǎo)致了Teacher的對象不可序列化
同一對象序列化多次,會將這個對象序列化多次嗎?答案是否定的。
public class WriteTeacher {
public static void main(String[] args) throws Exception {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("teacher.txt"))) {
Person person = new Person("路飛", 20);
Teacher t1 = new Teacher("雷利", person);
Teacher t2 = new Teacher("紅發(fā)香克斯", person);
//依次將4個對象寫入輸入流
oos.writeObject(t1);
oos.writeObject(t2);
oos.writeObject(person);
oos.writeObject(t2);
}
}
}
依次將t1、t2、person、t2對象序列化到文件teacher.txt文件中。
注意:反序列化的順序與序列化時的順序一致。
public class ReadTeacher {
public static void main(String[] args) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("teacher.txt"))) {
Teacher t1 = (Teacher) ois.readObject();
Teacher t2 = (Teacher) ois.readObject();
Person p = (Person) ois.readObject();
Teacher t3 = (Teacher) ois.readObject();
System.out.println(t1 == t2);
System.out.println(t1.getPerson() == p);
System.out.println(t2.getPerson() == p);
System.out.println(t2 == t3);
System.out.println(t1.getPerson() == t2.getPerson());
} catch (Exception e) {
e.printStackTrace();
}
}
}
//輸出結(jié)果
//false
//true
//true
//true
//true
從輸出結(jié)果可以看出,Java序列化同一對象,并不會將此對象序列化多次得到多個對象。
所有保存到磁盤的對象都有一個序列化編碼號
當程序試圖序列化一個對象時,會先檢查此對象是否已經(jīng)序列化過,只有此對象從未(在此虛擬機)被序列化過,才會將此對象序列化為字節(jié)序列輸出。
如果此對象已經(jīng)序列化過,則直接輸出編號即可。
圖示上述序列化過程。
由于java序利化算法不會重復(fù)序列化同一個對象,只會記錄已序列化對象的編號。如果序列化一個可變對象(對象內(nèi)的內(nèi)容可更改)后,更改了對象內(nèi)容,再次序列化,并不會再次將此對象轉(zhuǎn)換為字節(jié)序列,而只是保存序列化編號。
public class WriteObject {
public static
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/7161.html
摘要:序列化機制使得對象可以脫離程序的運行而獨立存在。普通序列化接口是一個標記接口,不用實現(xiàn)任何方法。如果此對象已經(jīng)序列化過,則直接輸出編號即可。圖示上述序列化過程。一、序列化的含義、意義及使用場景二、序列化實現(xiàn)的方式1、Serializable1.1 普通序列化1.2 成員是引用的序列化1.3 同一對象序列化多次的機制1.4 java序列化算法潛在的問題1.5 可選的自定義序列化2、Extern...
摘要:動態(tài)地代理,可以猜測一下它的含義,在運行時動態(tài)地對某些東西代理,代理它做了其他事情。所以動態(tài)代理的內(nèi)容重點就是這個。所以下一篇我們來細致了解下的到底是怎么使用動態(tài)代理的。 之前講了《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》,本來打算下一篇講講Srping的AOP的,但是其中會涉及到Java的動態(tài)代理,所以先單獨一篇來了解下Java的動態(tài)代理到底是什么,Java是怎么實現(xiàn)它的。 ...
摘要:序列化機制使得對象可以脫離程序的運行而獨立存在。普通序列化接口是一個標記接口,不用實現(xiàn)任何方法。如果此對象已經(jīng)序列化過,則直接輸出編號即可。圖示上述序列化過程。一、序列化的含義、意義及使用場景二、序列化實現(xiàn)的方式1、Serializable1.1 普通序列化1.2 成員是引用的序列化1.3 同一對象序列化多次的機制1.4 java序列化算法潛在的問題1.5 可選的自定義序列化2、Extern...
摘要:手動創(chuàng)建執(zhí)行線程存在以上問題,而線程池就是用來解決這些問題的。線程池詳解上面我們已經(jīng)知道了線程池的作用,而對于這樣一個好用,重要的工具,當然已經(jīng)為我們提供了實現(xiàn),這也是本篇文章的重點。,線程池一旦空閑超過時間,線程都將被回收。 showImg(https://segmentfault.com/img/remote/1460000018476903); 本文原創(chuàng)地址,我的博客:https...
摘要:注解在類上為類提供一個全參的構(gòu)造方法,加了這個注解后,類中不提供默認構(gòu)造方法了。這個注解用在類上,使用類中所有帶有注解的或者帶有修飾的成員變量生成對應(yīng)的構(gòu)造方法。 轉(zhuǎn)載請注明原創(chuàng)地址:http://www.54tianzhisheng.cn/2018/01/07/lombok/ showImg(http://ohfk1r827.bkt.clouddn.com/blog/180107/7...
閱讀 713·2023-04-25 19:43
閱讀 3910·2021-11-30 14:52
閱讀 3784·2021-11-30 14:52
閱讀 3852·2021-11-29 11:00
閱讀 3783·2021-11-29 11:00
閱讀 3869·2021-11-29 11:00
閱讀 3558·2021-11-29 11:00
閱讀 6105·2021-11-29 11:00