Java學習筆記(十三)--序列化、反序列化與無參建構函式
阿新 • • 發佈:2019-01-24
概念
- 序列化:將物件儲存到磁碟中,或允許在網路中直接傳輸物件,物件序列化機制允許把記憶體中的Java物件轉換成平臺無關的二進位制,從而可以持久的儲存在磁碟上,也可以在網路中傳輸。
- 反序列化:程式一旦獲得了序列化的物件,則這種二進位制流都可以恢復成原來的
如何實現序列化
1.Serializable
要序列化的物件,實現該介面,無需重寫任何方法
2.Externalizable
要序列化的物件實現該介面,並且需要實現writeExternal和readExternal方法
簡單物件的序列化
1.單一的物件序列化
- 建立一個Person類
public class Person implements Serializable{ private String id; public Person(String id) { System.out.println("youcacn"); this.id = id; } @Override public String toString() { return "Person{" + "id='" + id + '\'' + '}'; } public String getId() { return id; } public void setId(String id) { this.id = id; } }
注意:1.Person類實現了Serializable介面
2.該實體類沒有提供無參建構函式
- 寫一個測試類,測試一下序列化與反序列化
try { //序列化 ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("2.txt")); Person person = new Person("111"); objectOutputStream.writeObject(person); //反序列化 ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("2.txt")); Person person1 = (Person) objectInputStream.readObject(); System.out.println(person1.toString()); } catch (Exception e) { e.printStackTrace(); }
- 執行結果
- Person類去掉實現序列化介面(即,將public class Person implements Serializable修改為public class Person),重新執行
2.存在繼承關係,但並無引用關係的物件序列化
- 建立Student類,繼承Person類
public class Student extends Person implements Serializable{ private int no; @Override public String toString() { return "Student{" + "no=" + no + '}'; } public Student(String id ,int no) { super(id); this.no = no; } public int getNo() { return no; } public void setNo(int no) { this.no = no; } }
- Person類物件既沒實現序列化介面,又沒有提供無參建構函式
public class Person{
private String id;
// public Person() {
// }
public Person(String id) {
System.out.println("youcacn");
this.id = id;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
- 執行序列化與反序列化
- 另Person物件實現序列化介面,再次執行,結果成功
public class Person implements Serializable{
private String id;
// public Person() {
// }
public Person(String id) {
System.out.println("youcacn");
this.id = id;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
- 不實現序列化介面,提供無參建構函式,執行結果成功
public class Person {
private String id;
public Person() {
}
public Person(String id) {
System.out.println("youcacn");
this.id = id;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
結論:存在繼承關係時,若想序列化子類物件,一併序列化父類物件,則負責型別必須實現序列化介面或者提供無參建構函式物件引用的序列化
- Student類繼承Person類,並有物件引用關係
public class Student extends Person implements Serializable {
private int no;
private Person person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
return "Student{" +
"no=" + no +
'}';
}
public Student(String id, int no) {
super(id);
this.no = no;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
}
- 一個demo序列化Student例項與反序列化Student例項
try {
//序列化
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("2.txt"));
Person person = new Person("111");
Student stuB = new Student("B", 163);
stuB.setPerson(person);
objectOutputStream.writeObject(stuB);
//反序列化
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("2.txt"));
Student student = (Student) objectInputStream.readObject();
System.out.println(student.getPerson());
} catch (Exception e) {
e.printStackTrace();
}
- Person類不實現序列化介面,也不提供無參建構函式,執行結果如下:
- Person類不實現序列化介面,提供無參建構函式,執行結果如下:
- Person類實現序列化介面,但不提供無參建構函式,執行結果如下:
結論
- 單一物件,無繼承關係:若想實現序列化與反序列化,則必須實現序列化介面,否則報異常:NotSerializableException
- 物件間有繼承關係,但無引用關係,若想實現序列化與反序列化,則父類必須實現序列化介面或提供無參建構函式,否則報invalidClassException
- 物件間有繼承關係,並且有引用關係,若想實現序列化與反序列化,則父類必須實現序列化介面