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

 

 

posted @ 2021-02-02 01:14  Mrwhite86  阅读(190)  评论(0编辑  收藏  举报