Java序列化Serializable和反序列化Deserializable詳解及代碼示例
概念介紹
- 序列化主要是針對對象而言,像字元串以及基本資料類型等可以通過常用的輸入輸出方法将其寫入到檔案中,需要時讀取檔案到記憶體中。
-
序列化:
Java 提供了一種對象序列化的機制,該機制中,一個對象可以被表示為一個位元組序列,該位元組序列包括該對象的資料、有關對象的類型的資訊和存儲在對象中資料的類型。
-
反序列化:
将序列化對象寫入檔案之後,可以從檔案中讀取出來,并且對它進行反序列化,也就是說,對象的類型資訊、對象的資料,還有對象中的資料類型可以用來在記憶體中建立對象。
- 整個過程都是 Java 虛拟機(JVM)獨立的,也就是說,在一個平台上序列化的對象可以在另一個完全不同的平台上反序列化該對象。
代碼示例
- 類 ObjectInputStream 和 ObjectOutputStream 是高層次的資料流,ObjectOutputStream 類包含很多寫方法來寫各種資料類型,但是一個特别的方法例外:
//這個方法序列化一個對象,并将它發送到輸出流。
public final void writeObject(Object x) throws IOException
- 同樣ObjectInputStream 類包含如下反序列化一個對象的方法:
//該方法從流中取出下一個對象,并将對象反序列化。它的傳回值為Object,是以,你需要将它轉換成合适的資料類型。
public final Object readObject() throws IOException, ClassNotFoundException
- 定義一個學生類Student,該類實作了Serializable 接口。
//Student.java 檔案代碼:
import java.io.Serializable;
public class Student implements Serializable {
private String number;
private String name;
private int sex;
private int age;
private int grades;
public Student(String number, String name, int sex, int age, int grades) {
this.number = number;
this.name = name;
this.sex = sex;
this.age = age;
this.grades = grades;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getGrades() {
return grades;
}
public void setGrades(int grades) {
this.grades = grades;
}
public void hello(){
System.out.println("你好,我是"+grades+"年級的"+name);
}
@Override
public String toString() {
return "Student{" +
"number='" + number + '\'' +
", name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
", grades=" + grades +
'}';
}
}
-
注意,一個類的對象要想序列化成功,必須滿足兩個條件:
1、該類必須實作 java.io.Serializable 接口。
2、該類的所有屬性必須是可序列化的。如果有一個屬性不是可序列化的,則該屬性必須注明是短暫的。
- 接下來序列化Student對象
//SerializeStudent.java 代碼:
//該程式執行後,就建立了一個名為 student.ser 檔案。注意: 當序列化一個對象到檔案時, 按照 Java 的标準約定是給檔案一個 .ser 擴充名。
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializeStudent {
public static void main(String[] args) {
Student stu1 = new Student("10001", "張三", 0, 18, 10);
try {
FileOutputStream fileOut = new FileOutputStream("D:\\aspring\\student.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(stu1);
out.close();
fileOut.close();
System.out.println("Student對象檔案已被儲存在:D:/aspring/student.ser");
}catch(IOException i) {
i.printStackTrace();
}
}
}
- 序列化檔案如圖:
- 反序列化Student對象
//DeserializeStudent.java 檔案代碼:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeserializeStudent {
public static void main(String[] args) {
Student stu1 = null;
try {
FileInputStream fis = new FileInputStream("D:\\aspring\\student.ser");
ObjectInputStream in = new ObjectInputStream(fis);
stu1 = (Student) in.readObject();
in.close();
fis.close();
System.out.println("反序列化的結果為:"+stu1.toString());
stu1.hello();
}catch(IOException e) {
e.printStackTrace();
return;
}catch(ClassNotFoundException e) {
e.printStackTrace();
return;
}
}
}
//執行結果如下:
反序列化的結果為:Student{number='10001', name='張三', sex=0, age=18, grades=10}
你好,我是10年級的張三
Process finished with exit code 0
- 注意:如果有屬性不想被序列化,那麼需要在Student對象的相應屬性前,加 transient 修飾,表示該屬性是短暫的。在序列化時,不會将 transient 修飾的屬性序列化到檔案中。示例如下: