Java序列化和反序列化

时间:2013-01-24 15:01:04

标签: java serialization deserialization object-serialization

我有一个如下对象:

    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 个答案:

答案 0 :(得分:9)

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

private static final long serialVersionUID = -1232612718276774474L;

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

documentation的以下引用值得一读(强调我的):

  

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

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

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

答案 1 :(得分:0)

您可以在类中声明序列版本ID,如下所示:

private static final long serialVersionUID = -1232612718276774474L;

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

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