java進階(35)–對象流、序列化與反序列化
文檔目錄:
一、基礎概念
二、舉例-序列化對象
三、舉例-反序列化對象
四、舉例-序列化與反序列化多個對象與
五、transient關鍵字
六、序列化版本號
—————————————分割線:正文——————————————————–
一、基礎概念
1、序列化:
關鍵詞為Serialize,Java對象的狀態保存下來的過程
2、反序列化:
關鍵詞為DeSerialize,將硬體上的數據重新恢復到記憶體當中,恢復成Java對象
3、Serializable介面
參與序列化與反序列化的對象必須實現Serializable介面
參與序列化的集合元素都要實現Serializable介面,Serializable為一種標誌介面
4、序列化版本號
Serializable是給Java虛擬機看的,會載入該類自動生成一個序列化版本號
二、舉例-序列化對象
1、創建實現Serializable的student類
1 package JAVAADVANCE;
2 import java.io.Serializable;
3 public class Student02 implements Serializable {
4 private int no;
5 private String name;
6 public Student02() {
7 }
8 public Student02(int no, String name) {
9 this.no = no;
10 this.name = name;
11 }
12 public int getNo() {
13 return no;
14 }
15 public void setNo(int no) {
16 this.no = no;
17 }
18 public String getName() {
19 return name;
20 }
21 public void setName(String name) {
22 this.name = name;
23 }
24 }
2、創建TestAdvance35TestObjectOutputStreamTest01類實現序列化對象
1 package JAVAADVANCE;
2 import java.io.FileOutputStream;
3 import java.io.IOException;
4 import java.io.ObjectOutputStream;
5 public class TestAdvance35TestObjectOutputStreamTest01 {
6 public static void main(String[] args) throws IOException {
7 //創建java對象
8 Student02 s=new Student02(1111,"zhangsan");
9 //創建流
10 ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("students"));
11 //序列化java對象
12 oos.writeObject(s);
13 //刷新
14 oos.flush();
15 //關閉
16 oos.close();
17 }
18
19 }
項目文件目錄下生成Students文件,存儲java對象,無法直接讀取,需要反序列化讀取
三、舉例-反序列化對象
1 package JAVAADVANCE;
2 import java.io.*;
3 public class TestAdvance35TestObjectInputStreamTest01 {
4 public static void main(String[] args) throws IOException, ClassNotFoundException {
5 //創建流
6 ObjectInputStream ois=new ObjectInputStream(new FileInputStream("students"));
7 //開始反序列化
8 Object obj=ois.readObject();
9 //反序列化回來的是一個student02對象,所有會調用student02對象的toString方法
10 System.out.println(obj);
11 ois.close();
12 }
13 }
查看運行結果:
Student02{no=1111, name=’zhangsan’}
四、舉例-序列化與反序列化多個對象
1、創建User類實現Serializable介面
1 import java.io.Serializable;
2
3 public class User implements Serializable {
4 private String name;
5 private int no;
6
7 public User() {
8 }
9
10 public User(String name, int no) {
11 this.name = name;
12 this.no = no;
13 }
14
15 @Override
16 public String toString() {
17 return "User{" +
18 "name='" + name + '\'' +
19 ", no=" + no +
20 '}';
21 }
22 }
2、序列化多個對象
1 package JAVAADVANCE;
2
3 import java.io.FileOutputStream;
4 import java.io.IOException;
5 import java.io.ObjectOutputStream;
6 import java.util.ArrayList;
7 import java.util.List;
8
9 public class TestAdvance35TestObjectOutputStreamTest02 {
10 public static void main(String[] args) throws IOException {
11 List<User> userList =new ArrayList<>();
12 userList.add(new User(1,"zhangsan"));
13 userList.add(new User(2,"lisi"));
14 userList.add(new User(3,"wanglu"));
15 ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("user"));
16 oos.writeObject(userList);
17 oos.flush();
18 oos.close();
19 }
20
21 }
3、反序列化多個對象
1 package JAVAADVANCE;
2
3 import java.io.FileInputStream;
4 import java.io.IOException;
5 import java.io.ObjectInputStream;
6 import java.util.List;
7
8 public class TestAdvance35TestObjectInputStreamTest02 {
9 public static void main(String[] args) throws IOException, ClassNotFoundException {
10 ObjectInputStream ois=new ObjectInputStream(new FileInputStream("user"));
11 // Object obj=ois.readObject();
12 // System.out.println(obj instanceof List);//返回true
13 List<User> userList=(List<User>)ois.readObject();
14 for(User user:userList){
15 System.out.println(user);
16 }
17 ois.close();
18 }
19 }
4、查看執行結果:
User{name=’zhangsan’, no=1}
User{name=’lisi’, no=2}
User{name=’wanglu’, no=3}
五、transient關鍵字
1、transient關鍵字
表示為遊離的狀態,如name加上transient代表name不參與序列化
2、舉例說明
以上例子User類name加上transient
1 package JAVAADVANCE;
2 import java.io.Serializable;
3 public class User implements Serializable {
4 private transient String name;
5 private int no;
6 public User() {
7 }
8
9 public User( int no,String name) {
10 this.no = no;
11 this.name = name;
12 }
13
14 @Override
15 public String toString() {
16 return "User{" +
17 "name='" + name + '\'' +
18 ", no=" + no +
19 '}';
20 }
21 }
3、查看結果:
再次執行反序列化
User{name=’null’, no=1}
User{name=’null’, no=2}
User{name=’null’, no=3}
六、序列化版本號
1、 背景:
當Student源程式碼發生改動後,需要重新編譯,會生成新的位元組碼文件,class文件再次運行的時候,java虛擬機生成的序列化版本號也會發生相應改變。
到導致java.io.InvaildClassException;SerialVersionUID不一致的情況。
2、java語言中如何區分類:
如果類名不一樣,不是同一個類;類名同樣的情況下,靠序列化版本號進行區分
3、建議:
凡是類實現了Serializable介面,建議給該類提供一個固定不變的序列化版本號,java虛擬機會認為是同一個類
private static final long serialVersionUID=1L;
4、Idea快速生成序列化版本號
class類,alt+回車實現
需要設置:File-Setting-Editor-Inspections-搜索serializable-Serializable class without serialVersionUID-Apply