关于java class 版本的兼容问题
A 
总的来说:
因为序列化自动生成的UID要求严格,一个很小的改动就认为是不同的class,自己设置这个用来强制系统认为这两个不完全相同的类是同一个,就是 两个版本兼容
serialVersionUID 域是不同版本间兼容的标记,SerialVersionUID不同,发生了什么?
不兼容版本的异常被抛出
B 
解决问题:版本兼容性
采用显式声明 serialVersionUID 并且保证需要兼容的class 拥有相同的 serialVersionUID 。
格式:private static final long serialVersionUID = -5288121327143580980L;
C 
隐式 serialVersionUID 的特性:
同一个类的不兼容版本有不同的 serialVersionUID
如果您不提供一个值,将回自动产生一个
生成的值是基于类的"形状"
●类的名字。
●域的名字。
●方法的名字。
●已实现的接口。
改动上述任意一项内容(无论是增加或删除),都会引起编码值变化,从而引起类似的异常警报
D :)
具体的情况下的兼容:
o 如果值匹配,反序列化过程将为存在的域尽量提供值
o 只有同时存在于两个版本的域才会被恢复
当前版本所没有的域被忽略
当前版本新出现的域被置空
E :)
下面用一个例子说明问题:
1、 带能参数的构造函数初始化对象
2、 Writeobj()将当前对象写入test.txt 文件中
3、 Readobj()将test.txt文件中的对象读出来
4、 Printout()将对象及其值打印出来
-
-
package ser;
-
-
import java.io.FileInputStream;
-
import java.io.FileNotFoundException;
-
import java.io.FileOutputStream;
-
import java.io.IOException;
-
import java.io.ObjectInputStream;
-
import java.io.ObjectOutputStream;
-
import java.io.Serializable;
-
-
-
private static final long serialVersionUID = -5288121327143580980L;
-
-
//default
-
private int a ;
-
-
public char b ;
-
-
// protected long c ;
-
-
public test ( ) {
-
super ( );
-
// TODO Auto-generated constructor stub
-
}
-
-
public test ( int at, char bt, long ct ) {
-
//initial
-
this. a = at;
-
this. b = bt;
-
// this.c = ct;
-
}
-
-
public void printout ( ) {
-
//print the object member
-
// System.out.println("c = " + c + "/n");
-
}
-
-
public void writeobj ( ) {
-
ObjectOutputStream out;
-
try {
-
-
out. writeObject ( this );
-
out. close ( ); // Also flushes output
-
// TODO Auto-generated catch block
-
e. printStackTrace ( );
-
// TODO Auto-generated catch block
-
e. printStackTrace ( );
-
}
-
-
}
-
-
try {
-
test tr = (test ) in. readObject ( );
-
tr. printout ( );
-
in. close ( );
-
// TODO Auto-generated catch block
-
e. printStackTrace ( );
-
// TODO Auto-generated catch block
-
e. printStackTrace ( );
-
}
-
-
}
-
-
/**
-
* @param args
-
*/
-
// TODO Auto-generated method stub
-
test tst = new test ( 206, 'a', 112233445566L );
-
tst. writeobj ( );
-
try {
-
readobj ( );
-
// TODO Auto-generated catch block
-
e. printStackTrace ( );
-
}
-
-
}
-
-
}
-
F :)
1、 执行程序,a和b正常写入,查看文件
2、 将tst.writeobj()注释掉,执行,正常读出对象,然后再改变SerialVersionUID的值,执行,抛出异常:java.io.InvalidClassException,这说明了:“serialVersionUID 域是不同版本间兼容的标记”
现在我们再将serialVersionUID改回原值,将// protected long c ; 及下面有关变量c的注释打开,此时同样是注释掉tst.writeojb(),不写文件。这个升了级的类中增加了一个成员,执行读老版本类写的文件,我们可以看到: c = 0 这说明了:“在serialVersionUID保证版本兼容的同时,当前版本新出现的域被置空”
3、“当前版本所没有的域被忽略 ”可以用写a、b、c三个成员,读其中的两个成员的方法验证。
本文详细探讨了Java class版本兼容问题,尤其是序列化时遇到的挑战。核心在于serialVersionUID字段,其在不同版本间的不一致会导致不兼容异常。解决方法是显式设置相同serialVersionUID以确保兼容。当类的结构如名字、域、方法或接口等发生变化时,系统会自动生成不同的serialVersionUID。反序列化时,只有存在于两个版本中的域会被恢复,新出现或缺失的域则会被处理。通过实例展示了如何进行序列化和反序列化操作。

373

被折叠的 条评论
为什么被折叠?



