我创建了一个带有两个int变量的简单类,它实现了Serializable接口。然后我为这个类创建了对象,并在我的本地文件系统中使用ObjectOutputStream进行了序列化。现在关键在于序列化后我通过删除一个变量修改了serilized类。
现在当我尝试反序列化对象时,它会抛出一个名为“java.io.InvalidClassException”的异常。
有没有办法限制修改序列化类。
这种情况在java /编程术语中称为什么。
先谢谢。
我的代码如下:
package sample;
import java.io.Serializable;
public class Serial implements Serializable{
int a,b;
public void disp(){
System.out.println(a+" "+b);
}
}
package sample;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class ser {
public static void main(String[] args) {
Serial ss=new Serial();
ss.a=10;
//ss.b=20;
try{
FileOutputStream fio=new FileOutputStream("D:\\abc.ggg");
ObjectOutputStream oos=new ObjectOutputStream(fio);
oos.writeObject(ss);
}
catch(Exception e){
e.printStackTrace();
}
}
}
package sample;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class Dser {
public static void main(String[] args) {
try {
FileInputStream fis=new FileInputStream("D:\\abc.ggg");
ObjectInputStream ois=new ObjectInputStream(fis);
Serial sss=(Serial)ois.readObject();
sss.disp();
System.out.println(sss.a+" ");
} catch (Exception e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:0)
每个可序列化类都有一个关联的serialVersionUID
。像
private static final long serialVersionUID = 1L;
要么提供它,要么JVM会在序列化类的实例时对其进行计算。通常,在修改类时,可以修改此ID,以便匹配类版本。当您不提供ID时,计算出的ID正在考虑您的实例变量,因此如果您更改类,这将是不同的,这是您获得java.io.InvalidClassException
的原因之一。
现在当你改变你的类时,即在你的情况下删除一个变量,你的文件中的序列化类仍然有旧的类实例。当它被反序列化时,实例状态从文件中提取并尝试使用 Reflection 注入新创建的对象。现在,当它尝试注入你已删除的变量的值时,它将抛出异常。
答案 1 :(得分:0)
我认为限制更改序列化类的最佳方法是通过javadoc和测试的组合。换句话说,你不能严格执行,没有人改变它,但你可以肯定强烈建议他们除非他们已经考虑过后果。
当你序列化一个类时,你可能会想要成为你的公共API的一部分而且你会被永远地锁定它。如果你还没有,我建议你查看Josh Bloch的书中的序列化章节" Effective Java" - 项目74-78。他进入了你可能遇到的无数陷阱以及如何避免其中的大量陷阱。