序列化流和反序列化流的概述

序列化流 ObjectOutputStream類
使用步驟:
1.創(chuàng)建ObjectOutputStream對象,構造方法中傳遞字節(jié)輸出流
2.使用ObjectOutputStream對象中的方法writeObject,把對象寫入到文件中
3.釋放資源
/*
java.io.ObjectOutputStream extends OutputStream
ObjectOutputStream:對象的序列化流
作用:把對象以流的方式寫入到文件中保存
構造方法:
ObjectOutputStream(OutputStream out) 創(chuàng)建寫入指定 OutputStream 的 ObjectOutputStream。
參數(shù):
OutputStream out:字節(jié)輸出流
特有的成員方法:
void writeObject(Object obj) 將指定的對象寫入 ObjectOutputStream。
使用步驟:
1.創(chuàng)建ObjectOutputStream對象,構造方法中傳遞字節(jié)輸出流
2.使用ObjectOutputStream對象中的方法writeObject,把對象寫入到文件中
3.釋放資源
*/
public class Demo01ObjectOutputStream {
public static void main(String[] args) throws IOException {
//1.創(chuàng)建ObjectOutputStream對象,構造方法中傳遞字節(jié)輸出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("10_IO\\person.txt"));
//2.使用ObjectOutputStream對象中的方法writeObject,把對象寫入到文件中
oos.writeObject(new Person("小美女",18));
//3.釋放資源
oos.close();
}
}
必須給相應類標記,如果沒有標記。就會拋出NotSerializableException沒有序列化異常

/*
序列化和反序列化的時候,會拋出NotSerializableException沒有序列化異常
類通過實現(xiàn) java.io.Serializable 接口以啟用其序列化功能。未實現(xiàn)此接口的類將無法使其任何狀態(tài)序列化或反序列化。
Serializable接口也叫標記型接口
要進行序列化和反序列化的類必須實現(xiàn)Serializable接口,就會給類添加一個標記
當我們進行序列化和反序列化的時候,就會檢測類上是否有這個標記
有:就可以序列化和反序列化
沒有:就會拋出 NotSerializableException異常
去市場買肉-->肉上有一個藍色章(檢測合格)-->放心購買-->買回來怎么吃隨意
static關鍵字:靜態(tài)關鍵字
靜態(tài)優(yōu)先于非靜態(tài)加載到內存中(靜態(tài)優(yōu)先于對象進入到內存中)
被static修飾的成員變量不能被序列化的,序列化的都是對象
private static int age;
oos.writeObject(new Person("小美女",18));
Object o = ois.readObject();
Person{name='小美女', age=0}
transient關鍵字:瞬態(tài)關鍵字
被transient修飾成員變量,不能被序列化
private transient int age;
oos.writeObject(new Person("小美女",18));
Object o = ois.readObject();
Person{name='小美女', age=0}
*/
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
//private static int age;
//private transient int age;
public int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
反序列化流 ObjectInputStream類
使用步驟:
1.創(chuàng)建ObjectInputStream對象,構造方法中傳遞字節(jié)輸入流
2.使用ObjectInputStream對象中的方法readObject讀取保存對象的文件
3.釋放資源
4.使用讀取出來的對象(打印)
readObject方法聲明拋出了ClassNotFoundException(class文件找不到異常)
當不存在對象的class文件時拋出此異常
反序列化的前提:
1.類必須實現(xiàn)Serializable
2.必須存在類對應的class文件
/*
java.io.ObjectInputStream extends InputStream
ObjectInputStream:對象的反序列化流
作用:把文件中保存的對象,以流的方式讀取出來使用
構造方法:
ObjectInputStream(InputStream in) 創(chuàng)建從指定 InputStream 讀取的 ObjectInputStream。
參數(shù):
InputStream in:字節(jié)輸入流
特有的成員方法:
Object readObject() 從 ObjectInputStream 讀取對象。
使用步驟:
1.創(chuàng)建ObjectInputStream對象,構造方法中傳遞字節(jié)輸入流
2.使用ObjectInputStream對象中的方法readObject讀取保存對象的文件
3.釋放資源
4.使用讀取出來的對象(打印)
readObject方法聲明拋出了ClassNotFoundException(class文件找不到異常)
當不存在對象的class文件時拋出此異常
反序列化的前提:
1.類必須實現(xiàn)Serializable
2.必須存在類對應的class文件
*/
public class Demo02ObjectInputStream {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//1.創(chuàng)建ObjectInputStream對象,構造方法中傳遞字節(jié)輸入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("10_IO\\person.txt"));
//2.使用ObjectInputStream對象中的方法readObject讀取保存對象的文件
Object o = ois.readObject();
//3.釋放資源
ois.close();
//4.使用讀取出來的對象(打印)
System.out.println(o);
Person p = (Person)o;
System.out.println(p.getName()+p.getAge());
}
}
static關鍵字:靜態(tài)關鍵字
靜態(tài)優(yōu)先于非靜態(tài)加載到內存中(靜態(tài)優(yōu)先于對象進入到內存中)
被static修飾的成員變量不能被序列化的,序列化的都是對象
private static int age;
oos.writeObject(new Person("小美女",18));
Object o = ois.readObject();
Person{name='小美女', age=0}
transient關鍵字:瞬態(tài)關鍵字
被transient修飾成員變量,不能被序列化
private transient int age;
oos.writeObject(new Person("小美女",18));
Object o = ois.readObject();
Person{name='小美女', age=0}
序列號沖突異常的原理和解決方案(InvalidClassException 異常)

解決方案:
無論是否對類的定義進行修改,都不能重新生成新的序列號
可以手動給類添加一個序列號

練習:序列化集合
- 將存有多個自定義對象的集合序列化操作,保存到 list.txt 文件中。
- 反序列化 list.txt ,并遍歷集合,打印對象信息。
/*
練習:序列化集合
當我們想在文件中保存多個對象的時候
可以把多個對象存儲到一個集合中
對集合進序列化和反序列化
分析:
1.定義一個存儲Person對象的ArrayList集合
2.往ArrayList集合中存儲Person對象
3.創(chuàng)建一個序列化流ObjectOutputStream對象
4.使用ObjectOutputStream對象中的方法writeObject,對集合進行序列化
5.創(chuàng)建一個反序列化ObjectInputStream對象
6.使用ObjectInputStream對象中的方法readObject讀取文件中保存的集合
7.把Object類型的集合轉換為ArrayList類型
8.遍歷ArrayList集合
9.釋放資源
*/
public class Demo03Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//1.定義一個存儲Person對象的ArrayList集合
ArrayList<Person> list = new ArrayList<>();
//2.往ArrayList集合中存儲Person對象
list.add(new Person("張三",18));
list.add(new Person("李四",19));
list.add(new Person("王五",20));
//3.創(chuàng)建一個序列化流ObjectOutputStream對象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("10_IO\\list.txt"));
//4.使用ObjectOutputStream對象中的方法writeObject,對集合進行序列化
oos.writeObject(list);
//5.創(chuàng)建一個反序列化ObjectInputStream對象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("10_IO\\list.txt"));
//6.使用ObjectInputStream對象中的方法readObject讀取文件中保存的集合
Object o = ois.readObject();
//7.把Object類型的集合轉換為ArrayList類型
ArrayList<Person> list2 = (ArrayList<Person>)o;
//8.遍歷ArrayList集合
for (Person p : list2) {
System.out.println(p);
}
//9.釋放資源
ois.close();
oos.close();
}
}