8

我有一个对象如下:

    public class Records implements java.io.Serializable{
        private int cId;
        private int pId;
        private int vlaue;
        private int tag;

        public Records(int c, int p, int v, int t){
                this.cId=c;
                this.pId=p;
                this.value=v;
                this.tag=t;
        }
}

我已经收集了大量数据,在上面的类中构造了对象并将它们序列化到磁盘。

我忘记包含在类文件中的一件事是访问每个对象的值的方法。例如,访问特定对象的 cId 值。

我修改了类定义以添加此类方法,但后来我无法将对象反序列化回 Records 类并得到此运行时错误:

java.io.InvalidClassException: Records; local class incompatible: stream classdesc serialVersionUID = -1232612718276774474, local class serialVersionUID = -8244963718951538904
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:579)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1600)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1513)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1749)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368)
    at DeSerialise.main(DeSerialise.java:21)

我想我需要告诉java它们是相同的定义并修改serialVersionUID但不太确定如何?任何想法都会受到欢迎!

4

4 回答 4

9

尝试将以下内容添加到您的课程中:

private static final long serialVersionUID = -1232612718276774474L;

这将使您的类serialVersionUID与实例序列化时使用的编译器生成的值一致。

文档中的以下引用值得一读(强调我的):

序列化运行时与每个可序列化类关联一个版本号,称为 serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已加载与序列化兼容的该对象的类。如果接收者为对象加载了一个类,该对象的 serialVersionUID 与相应发送者的类不同,则反序列化将导致 InvalidClassException。可序列化的类可以通过声明一个名为“serialVersionUID”的字段来显式声明自己的serialVersionUID,该字段必须是静态的、最终的和long类型:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

如果可序列化类没有显式声明 serialVersionUID,则序列化运行时将根据类的各个方面为该类计算默认的 serialVersionUID 值,如 Java(TM) 对象序列化规范中所述。但是,强烈建议所有可序列化的类都显式声明 serialVersionUID 值,因为默认的 serialVersionUID 计算对类细节高度敏感,这些细节可能因编译器实现而异,因此可能在反序列化期间导致意外的 InvalidClassExceptions。因此,为了保证在不同的 java 编译器实现中具有一致的 serialVersionUID 值,可序列化的类必须声明一个显式的 serialVersionUID 值。还强烈建议显式 serialVersionUID 声明尽可能使用 private 修饰符,因为此类声明仅适用于立即声明的类——serialVersionUID 字段不能用作继承成员。数组类不能显式声明 serialVersionUID,因此它们始终具有默认的计算值,但数组类不需要匹配 serialVersionUID 值。

于 2013-01-24T15:02:27.743 回答
0

您可以在您的类中声明串行版本 ID,如下所示:

private static final long serialVersionUID = -1232612718276774474L;
于 2013-01-24T15:03:17.160 回答
0

是的,为类指定 serialversionId 非常重要。否则很难识别序列化的类。

如果您这样做,您还可以创建新的序列化对象而不是使用旧的序列化对象。

Eclipse IDE 会自动生成 serialversionId 尝试使用它。

于 2013-01-24T15:05:16.743 回答
0

问题是您在没有在类中定义 serialVersionUID 的情况下对数据进行了序列化。添加 setter 和 getter 是可以的,并且不会影响序列化,但是当您重新编译该类时,编译器可能会生成另一个 UID,这会在您尝试反序列化数据时导致异常。如果需要实际反序列化您使用类的第一个版本序列化的数据,您需要知道编译器第一次生成的 UID:这可以在错误消息中看到,因此您需要将 serialVersionUID 设置为 -1232612718276774474L .

于 2013-01-24T15:10:13.880 回答