实验
先让Test类实现Serializable,然后在类中添加: private static final long serialVersionUID = 1L;
进行以下5次测试:
先进行序列化,然后改类名,再反序列化
//1.
Test01 test01 = new Test01();
toFIle(test01,path);
// 2. 修改类名
// 3.
System.out.println(toObj(path));
结果:
抛出ClassNotFoundException,显示找不到类
先进行序列化,然后修改类的字段名,但不修改类的序列化id,然后反序列化
//1.
Test01 test01 = new Test01();
toFIle(test01,path);
// 2. 修改字段名,其他不变
// 3.
System.out.println(toObj(path));
结果:
没有抛出异常,被修改的字段值为默认值,也就是在序列化后找不到与新字段对应的值
先进行序列化,然后删除该类A,再将另一个类B的序列化id该为这个类A,再反序列化
//1.
Test01 test01 = new Test01();
toFIle(test01,path);
// 2. 删除该类A,再将另一个类B的序列化id该为这个类A
// 3.
System.out.println(toObj(path));
结果:
报错,与实验一相同
先进行序列化,然后修改该类的序列化id,再反序列化
//1.
Test01 test01 = new Test01();
toFIle(test01,path);
// 2. 修改该类的序列化id
// 3.
System.out.println(toObj(path));
结果:
抛出异常:
java.io.InvalidClassException: io.Test01; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
显示序列化id不匹配
先把该类的序列化id去掉,进行序列化,再修改字段名,再反序列化
//1. 去掉序列化id
// 2.
Test01 test01 = new Test01();
toFIle(test01,path);
//3. 修改字段名
//4.
System.out.println(toObj(path));
结果:
与上同,序列化id不匹配
结论:
每次进行反序列化时,代码会从读到的类全限定名中找到对应的类,找不到直接报ClassNotFoundException,找到后会比较这个类的序列化id和自己读到的序列化id,不同则报InvalidClassException,然后会尽最大努力给对象赋值,(所谓尽最大努力就是将能匹配的字段全部匹配并赋值)
当没有序列化id字段时,JVM会在序列化时根据类信息自动创建一个,反序列化时同理
序列化id的应用场景
如果我们写了一个类,而又希望这个类能向下兼容(既可以从以前版本的序列化文件反序列化出对象),我们就给他加序列化id字段,并尽量不修改这个字段,
如果我们不希望向下兼容,就不加序列化id字段,每次修改类时,序列化id都不同, 或者加序列化id,并每次修改类时修改序列化id,也可以实现向下不兼容