2011-12-02 65 views
9

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

我有一个可序列化的类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不同,并且会创建异常。一个快速的解决方案可能是将serialVersionUID设置为4209360273818925922L,这似乎是当您在那个文件中保存那些对象时由java自动生成的serialVersionUID。

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

+0

您是否有意将整数指定为serialVersionUID?通常这不应该是一个问题,但通常你应该使用长的值。 – Robert

+0

@罗伯特,不是故意的,它恰好是如此。我不认为这是一个问题。 – wwyt

回答

1

由于您明确声明了serialVersionUID,所以只要serialVersionUID没有改变(并且类没有彻底改变),在序列化和反序列化中应该没有问题。

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

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

+0

感谢您的回复。这些确实是非常聪明的猜测,尤其是第二个。但我很确定这些不是这种情况。但是,谢谢你的指点。 – wwyt

2

我同意AKJ:

我认为,你的第一个问题,“找不到类” - 你可能反序列化类在enviornment不知道这个类。也有可能你有两个环境和两个班的副本。

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

请注意,AJK可能是正确的,而你不知道它 - 你的类中的每个类成员默认都是序列化的,除非声明它指定了瞬态。所以,如果你有短的,长的,String,myClass或者其他什么,他们都会通过serilization。根据上面的说明,如果没有设置常量UID,则每次编译ypu时都会得到不同的UID - 这很可能会导致您的问题。

祝你好运。