2013-01-24 21 views
8

我有一個對象如下:的Java Seralization和Deseralization

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; 
     } 
} 

我已經收集了大量的數據,構造的對象,如上面的類,並將其seralized到磁盤。

我忘記包含在類文件中的一個轉儲事項是訪問每個對象的值的方法。例如,訪問特定對象的cId值。

我修改類定義添加這樣的方法,但後來我不能deseralize對象回記錄類和得到這個運行時錯誤:

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但不是很確定如何?任何想法都會受到歡迎!

+1

你會發現在這個問題上你的問題很好的解釋:http://stackoverflow.com/q/285793/1916110 – Tom

回答

9

嘗試添加以下到您的類:

private static final long serialVersionUID = -1232612718276774474L; 

這會帶給你的類的serialVersionUID與當實例連載使用的編譯器生成的價值線。

documentation以下報價是值得一讀(重點煤礦):

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:

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

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes.

+0

感謝您的答案和指針。它有幫助,而且有效。 – DotNet

0

您可以在類中聲明的串行版本ID如下:

private static final long serialVersionUID = -1232612718276774474L; 
+1

添加一個隨機serialVersionUID不會有幫助。 –

+0

爲什麼JB NIzet? – abhi

+0

@JBNizet是對的。隨機的serialVersionUID不起作用,甚至不會像上面的答案那樣匹配一個java編譯器。 – DotNet

0

是它是非常重要的你爲class指定serialversionId。否則,將很難識別序列化的類。

如果您這樣做,您也可以創建新的序列化對象,而不是使用舊的序列化對象。

Eclipse IDE會自動生成serialversionId嘗試使用它。

0

問題是,如果序列化數據時沒有在類中定義serialVersionUID。添加setter和getters是好的,不會影響序列化,但編譯器可能會在您重新編譯該類時生成另一個UID,這會在嘗試反序列化數據時導致異常。如果需要實際反序列化使用第一個版本的類序列化的數據,則需要知道編譯器第一次生成的UID:這可以在錯誤消息中看到,因此您需要將serialVersionUID設置爲-1232612718276774474L 。