objectInputstream的readObject方法在更改类包时抛出ClassNotFoundException

时间:2013-12-09 03:01:06

标签: java serialization

我知道这个问题是基本的,但我在例外情况下遇到了一些问题。

我使用ObjectOutputStream来保存计算机中的prooerties对象。不幸的是,在特殊情况下更改为类包名时,我得到了ClassNotFoundException。

我的问题很重要:

如何将旧课程中的旧属性添加到我更改的课程中?

我必须解决问题,因为我需要旧的属性来保持我的应用程序正常工作。我确定属性正确,只有类名不同。

感谢所有回复。

2 个答案:

答案 0 :(得分:3)

有一种解决方法:

class Workaround extends ObjectInputStream {
    String className;

    public Workaround(InputStream in, Class<?> cls) throws IOException {
        super(in);
        this.className = cls.getName();
    }

    @Override
    protected ObjectStreamClass readClassDescriptor() throws IOException,
            ClassNotFoundException {
        ObjectStreamClass cd = super.readClassDescriptor();
        try {
            Field f = cd.getClass().getDeclaredField("name");
            f.setAccessible(true);
            f.set(cd, className);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return cd;
    }
}

现在我可以编写一个Test1实例并将其作为Test2的实例读取

class Test1 implements Serializable {
    private static final long serialVersionUID = 1L;
    int i;
}

class Test2 implements Serializable {
    private static final long serialVersionUID = 1L;
    int i;
}

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("1"));
Test1 test1 = new Test1();
oos.writeObject(test1);
oos.close();
Workaround x = new Workaround(new FileInputStream("1"), Test2.class);
Test2 test2 = (Test2)x.readObject();

答案 1 :(得分:1)

  

不幸的是,在特殊情况下更改为类包名称时,我得到了ClassNotFoundException

将其更改回来。您可以在不破坏现有序列的情况下更改类的许多内容,但包名称不是其中之一。您需要研究Versioning of Serializable Objects chapter of the Object Serialization Specification以了解您能够做什么和不能改变什么。在您已经完成一些序列化之后,确实在您部署应用程序之后,对包名称有了第二个想法,为时已晚。保持原状。

还有其他方法,但我希望你不需要它们。