Java Serializable(序列化)
阿新 • • 發佈:2021-01-30
序列化的意義
序列化機制將Java物件轉換為位元組序列,這些位元組序列可以儲存在磁碟上,或通過網路傳輸。序列化機制使得java物件可以脫離程式而獨立存在。
Java講究萬物皆物件,資訊大多數都儲存在物件內部(屬性),所以需要儲存物件至關重要。然而儲存物件的前提是物件已經進行了序列化。
使用場景
- 把物件進行網路傳輸
- 把物件儲存到磁碟
- 資料快取
可序列化的類
- 如果父類是可序列化的,那麼子類可以序列化
- 如果類的全部成員是可序列化的,那麼類可以序列化
序列化和反序列化的Demo
Person類
//Student繼承Serializable,可以進行序列化
public class Student implements Serializable {
//無參建構函式
public Student() {
}
//有參建構函式
public Student(String name) {
this.name = name;
}
/*
name是Student的成員變數,name的型別是String(可序列化),所以Student可以正常序列化。
*/
private String name;
//get
public String getName() {
return name;
}
//set
public void setName(String name) {
this.name = name;
}
//重寫equlas
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return name.equals(student.name);
}
//重寫hashcode
@Override
public int hashCode() {
return Objects.hash(name);
}
//重寫tostring
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
'}';
}
}
主函式
/*
1、引數
file是檔案物件
object是寫入的物件
2、主要功能
把物件序列化後寫入檔案,規則:一個檔案只寫一個物件
*/
public static void writer(File file, Object object) {
//檔案不存在就建立檔案
if (!file.exists()) {
try {
//建立檔案
file.createNewFile();
System.out.println("檔案不存在,建立檔案成功...");
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("開始寫檔案...");
try {
//例項化FileOutputStream物件
FileOutputStream fileOutputStream = new FileOutputStream(file);
//例項化objectOutputStream物件
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
//把物件寫入檔案
objectOutputStream.writeObject(object);
//關閉流
objectOutputStream.close();
fileOutputStream.close();
System.out.println("寫入結束,關閉流成功...");
} catch (IOException e) {
System.out.println("寫入失敗!");
e.printStackTrace();
}
}
/*
1、引數
file是檔案物件
2、主要功能
把序列化後的檔案轉換為物件
3、返回值
一個Object類的物件
*/
public static Object reader(File file) {
//如果檔案不存在退出程式
if (!file.exists()) {
System.out.println("讀取的檔案不存在!");
//退出程式
System.exit(1);
}
System.out.println("開始讀檔案...");
try {
//例項化FileInputStream物件
FileInputStream fileInputStream = new FileInputStream(file);
//例項化ObjectInputStream物件
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
//讀取物件
Object object = null;
try {
object = objectInputStream.readObject();
} catch (ClassNotFoundException e) {
System.out.println("讀取失敗!");
e.printStackTrace();
}
//關閉連線
objectInputStream.close();
fileInputStream.close();
System.out.println("讀取結束,關閉流成功...");
//返回讀取的物件
return object;
} catch (IOException e) {
System.out.println("讀取失敗!");
e.printStackTrace();
}
//發生異常返回null
return null;
}
public static void main(String[] args) {
//例項化多個物件
Student a = new Student("小紅");
Student b = new Student("小藍");
Student c = new Student("小黃");
//定義集合
List<Student> list = new ArrayList<>();
//把物件加入集合
list.add(a);
list.add(b);
list.add(c);
//檔案路徑
String filePath = "object.txt";
//例項化File物件
File file = new File(filePath);
//把集合物件序列化後寫入檔案
writer(file, list);
//把檔案進行反序列化轉為物件
Object reader = reader(file);
//把物件進行強制轉換,因為返回的是Object類
List<Student> students = (List<Student>) reader;
//遍歷輸出物件
for (Student student : students) {
System.out.println(student);
}
}
總結
- 反序列化不會呼叫構造方法(感覺這個結論有點傻)
- 一個物件不會被多次序列化
比如:你把物件A序列化後寫入檔案,然後又一次把物件A序列化寫入檔案,這時,系統發現A已經存在於檔案中,只會寫入A的編號(指標的感覺)。
帶來的bug:如果A先寫入檔案,然後A屬性值發生了改變,這時想更新檔案中的A,再把A寫入檔案,系統儲存的是修改前的屬性值(A第一次存入檔案的屬性)。