序列化版本号的用处:
在序列化存储/反序列化读取或者是序列化传输/反序列化接收时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。
1.首先演示一下序列化版本不一致导致的异常,首先请看下面一段代码:
//Serializable 标识性的接口,表示类为序列化的类
//创建的对象就是序列化对象
public class Student implements Serializable{
/**
* serialVersionUID序列化的版本号
*/
private static final long serialVersionUID = 4236678034618399185L;
private String name;
private int age;
//String sex;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
/* @Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}*/
}
//写对象到数据文件oos.txt
public static void test1() throws FileNotFoundException, IOException {
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("oos.txt"));
Student stu1=new Student("admin",18);
Student stu2=new Student("张三",18);
oos.writeObject(stu1);
oos.writeObject(stu2);
oos.close();
}
//读取对象
public static void test2() throws FileNotFoundException, IOException, ClassNotFoundException {
File file=new File("oos.txt");
if(!file.exists()) {
file.createNewFile();
}
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(file));
Student stu1=(Student)ois.readObject();
Student stu2=(Student)ois.readObject();
System.out.println(stu1);
System.out.println(stu2);
ois.close();
}
运行test1(),会得到一个oos.txt文件;
运行test2(),结果为:
Student [name=admin, age=18]
Student [name=张三, age=18]
接下来,修改上面的版本号
//修改版本号:
private static final long serialVersionUID = 3236678034618399185L;
//写对象到数据文件oos.txt
public static void test1() throws FileNotFoundException, IOException {
//FileOutputStream(File, boolean) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("oos.txt",true)); //这行代码做改动
Student stu1=new Student("admin",18);
Student stu2=new Student("张三",18);
oos.writeObject(stu1);
oos.writeObject(stu2);
oos.close();
}
这时候,再运行程序:
运行test1(),发现oos.txt多了内容。
运行test2()发现在读取数据时,结果报异常,提示版本号不同:
2.只要同一个版本号,修改属性,也能反序列化
当你序列化了一个类实例后,希望更改一个字段或添加一个字段,不设置serialVersionUID,所做的任何更改都将导致无法反序化旧有实例,并在反序列化时抛出一个异常。如果你添加了serialVersionUID,在反序列旧有实例时,新添加或更改的字段值将设为初始化值(对象为null,基本类型为相应的初始默认值),字段被删除将不设置
接下来就上面这段话,通过代码演示。(还是就上面那个代码做修改)
(1)添加一个字段,不设置serialVersionUID,如下面代码。
//private static final long serialVersionUID = 4236678034618399185L;
String sex;
运行上面的test2(),结果为:
(2)添加了serialVersionUID,新添加一个字段sex
private static final long serialVersionUID = 4236678034618399185L;
String sex;
@Override
//重写了toString()方法
public String toString() {
return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
结果为:
Student [name=admin, age=18, sex=null]
Student [name=张三, age=18, sex=null]