我对java序列化的理解
通过ObjectOutputStream输出流保存实体类所产生的文件,每一个流都一个序列化ID,如果我们不设置UID的话,一旦我们修改代码,这个文件就会出现InvalidClassException异常,所以需要设置一个私有静态最终类的UID,这样才能保证我们的流不能被找到。
演示代码
第一步/编写Student实体类代码
/**
* @author Mxhlin
* @Email fuhua277@163.com
* @Date 2022/09/24/8:17
* @Version
* @Description 狐狸实体类 有一个名字 年龄的属性,toString/Get/Set/有/无参构造方法
*/
public class Fox {
private String name;
private int age;
@Override
public String toString() {
return "Fox{" +
"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;
}
public Fox(String name, int age) {
this.name = name;
this.age = age;
}
public Fox() {
}
}
第二步/编写序列化代码
package com.Mxhlin.io;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author Mxhlin
* @Email fuhua277@163.com
* @Date 2022/09/24/8:21
* @Version
* @Description 序列化Fox
*/
public class FoxSeria {
static String db = "db.dat";
static {// 初始化一个空元素
if (!new File(db).exists()) {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("db"))) {
List<Fox> list = new ArrayList<>();
oos.writeObject(list);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
// 第一次查询
System.out.println(rand());
}
/**
* @Description: 读取db.dat
* @Param: []
* @return: java.util.List<com.Mxhlin.io.Fox>
* @Author: Mxhlin
* @Date: 2022/9/24
*/
public static List<Fox> rand() {
List<Fox> list = new ArrayList<>();
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(db))) {
list = (List<Fox>) ois.readObject();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return list;
}
/**
* @Description: 输出文件
* @Param: [fox]
* @return: int
* @Author: Mxhlin
* @Date: 2022/9/24
*/
public static int write(Fox fox) {
List<Fox> list = new ArrayList<>();
list.add(fox);
int i = 0;
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(db))) {
oos.writeObject(list);
i = 1;
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
return i;
}
}
- 第一次运行
- 会一个找不到文件的异常
- 但是也会因为静态块判断是否有文件二初始化创建一个文件
- 执行序列化方法
- 会报错Fox不能被序列化
- 也会生成一个文件
- 这里给Fox实现序列化接口
- 再次执行wirte()方法
- 返回1,代表序列化成功
这样就成功了
- 那如果我把Fox的toString 去掉呢?
- 对实体类进行修改
- 再次读取
- 会报错实现我们这两个Uid不相容
- 每个ObjectOutputStream输出流都是有SerializableUID的
- 所以我们要给实体类设置UID
- 给他设置UID之后再次读取
- 修改实体类Fox再次运行
- IDEA有一个小功能,可以自动生成UID
- 把这个勾选上后
- 我们的实体类再次实现Serializable接口,就会提示
- 点击就会生成UID
- 序列化的好处就在于我们可以把数据保存在db.dat里面,不会关闭程序就重置,只要db.dat存在我们就可以保存上次我们所设置的实体类