关于序列化,serialVersionUID和不兼容的类

时间:2011-12-02 05:54:42

标签: java android

我在这里看到了一些相关的问题和答案,但它们似乎没有帮助。所以我想我需要在这里发布一个单独的问题:

我有一个可序列化的类MyDataClass,它包含一些可序列化的内部类。我使用FileOutputStreamObjectOutputStream将其保存到文件中。回读时,我有时会遇到异常(可能ClassNotFoundExceptionInvalidClassException,但我不确定),异常的消息是这样的:

12-01 18:44:16.479: D/My App Name(534): ***** exception occurred 
com.xyz.myapp.lib.am; Incompatible class (SUID): com.xyz.myapp.lib.am: 
static final long serialVersionUID =3894560643019408205L; but expected 
com.xyz.myapp.lib.am: static final long serialVersionUID =-4215454881436014736L;

MyDataClass是这样的:

public static class MyDataClass implements Serializable {

    private static final long serialVersionUID = 0x98F22BF5;
    .....
    public boolean bNoTitle;
    public short syncOption;
    .....

    public class InnerClass implements Serializable {
        private static final long serialVersionUID = 0x99D32720;
        double premium;
        double interest;
    }
}

然后我使用以下代码来阅读它:

MyDataClass oc;
FileInputStream fin = new FileInputStream(dataFile);
ObjectInputStream ois = new ObjectInputStream(fin);
oc = (MyDataClass)ois.readObject();
ois.close();
fin.close();

readObject抛出异常,而不是每次都抛出异常,但有时我到目前为止无法查明。我在某处读到,实际写入文件的serialVersionUID不是我在代码中指定的。因此,当它被回读时,UID不匹配,因此异常。是对的吗?如果是这样,我怎样才能确保没有异常并且按预期读回对象?

谢谢。

编辑:似乎从Eclipse调试时,一切都很好。但是在使用ant进行构建之后,问题就出现了。但不是每次ant构建之后,有时候。

编辑:我在另一篇文章中看到了:

你是在读文件吗?在这种情况下,如果您现在添加serialVersionUID并不重要,它与文件中存储的不同,并且会创建异常。一个快速的解决方案是将serialVersionUID设置为4209360273818925922L,这似乎是当时在那个文件中保存那些对象时由java自动生成的serialVersionUID。

当用户使用该应用程序时,我的文件将被多次保存/读取。如果Java每次分配一个不同的UID 文件保存,那么我怎样才能预先在代码中输入一个数字?我需要一个真正的静态UID,即使在ant构建之后也不会改变。

2 个答案:

答案 0 :(得分:2)

我同意AKJ:

我认为,对于你的第一个问题'找不到课' - 你可能会在一个不知道这个类的环境中反序列化该类。你也可能有2个环境,有2个班级副本。

AnyHow,序列化的UID是这样的: 如果你没有指定一个,它会在你每次编译/构建时自动生成一个 - 否则,如果你指定了一个,那么那个是UID。

请注意,在没有您知道的情况下,AJK可能是正确的 - 默认情况下,您的类中的每个类成员都会被序列化,除非在声明它时指定了transient。所以,如果你有短,长,字符串,myClass或其他什么,他们都将通过血清化。根据上面的解释,如果没有设置常量UID,每次编译ypu时都会得到一个不同的UID - 这很可能会导致你的问题。

祝你好运。

答案 1 :(得分:1)

当你明确声明serialVersionUID时,只要serialVersionUID没有改变(并且类没有彻底改变),序列化和反序列化应该没有问题。

从异常消息中我觉得你可能有一些也被序列化的成员类但没有明确的串行版本UID,所以你可能需要在该类中明确声明serialVersionUID。

另一种可能性是,在您放置显式serialVersionUID之前,您可能会意外地尝试读取已保存的文件。