JavaTM 2 Platform
Standard Ed. 6

java.io
介面 Serializable

所有已知子介面:
AdapterActivator, Attribute, Attribute, Attributes, BindingIterator, ClientRequestInfo, ClientRequestInterceptor, Codec, CodecFactory, Control, Current, Current, Current, CustomValue, DataInputStream, DataOutputStream, Descriptor, DHPrivateKey, DHPublicKey, DocAttribute, DomainManager, DSAPrivateKey, DSAPublicKey, DynAny, DynAnyFactory, DynArray, DynEnum, DynFixed, DynSequence, DynStruct, DynUnion, DynValue, DynValueBox, DynValueCommon, ECPrivateKey, ECPublicKey, ExtendedRequest, ExtendedResponse, Externalizable, IdAssignmentPolicy, IDLEntity, IDLType, IdUniquenessPolicy, ImplicitActivationPolicy, Interceptor, IORInfo, IORInterceptor, IORInterceptor_3_0, IRObject, Key, LifespanPolicy, Name, NamingContext, NamingContextExt, NotificationFilter, ObjectReferenceFactory, ObjectReferenceTemplate, ORBInitializer, ORBInitInfo, PBEKey, POA, POAManager, Policy, PolicyFactory, PrintJobAttribute, PrintRequestAttribute, PrintServiceAttribute, PrivateKey, PublicKey, QueryExp, RelationType, RemoteRef, RequestInfo, RequestProcessingPolicy, RSAMultiPrimePrivateCrtKey, RSAPrivateCrtKey, RSAPrivateKey, RSAPublicKey, RunTime, SecretKey, ServantActivator, ServantLocator, ServantManager, ServantRetentionPolicy, ServerRef, ServerRequestInfo, ServerRequestInterceptor, StreamableValue, SupportedValuesAttribute, ThreadPolicy, UnsolicitedNotification, ValueBase, ValueExp

public interface Serializable

類別通過實作 java.io.Serializable 介面以啟用其序列化功能。未實作此介面的類別將無法使其任何狀態序列化或反序列化。可序列化類別的所有子型別本身都是可序列化的。序列化介面沒有方法或欄位,僅用於標識可序列化的語義。

要允許不可序列化類別的子型別序列化,可以假定該子型別負責保存和恢復父級類別型的公用 (public)、受保護的 (protected) 和(如果可存取)包 (package) 欄位的狀態。僅在子型別擴展的類別有一個可存取的無參數建構子來初始化該類別的狀態時,才可以假定子型別有此職責。如果不是這種情況,則宣告一個類別為可序列化類別是錯誤的。該錯誤將在運行時檢測到。

在反序列化過程中,將使用該類別的公用或受保護的無參數建構子初始化不可序列化類別的欄位。可序列化的子類別必須能夠存取無參數建構子。可序列化子類別的欄位將從該串流中恢復。

當遍歷一個圖形時,可能會遇到不支持 Serializable 介面的物件。在此情況下,將拋出 NotSerializableException,並將標識不可序列化物件的類別。

在序列化和反序列化過程中需要特殊處理的類別必須使用下列準確簽章來實作特殊方法:

 private void writeObject(java.io.ObjectOutputStream out)
     throws IOException
 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;
 private void readObjectNoData() 
     throws ObjectStreamException;
 

writeObject 方法負責寫入特定類別的物件的狀態,以便相應的 readObject 方法可以恢復它。通過調用 out.defaultWriteObject 可以調用保存 Object 的欄位的預設機制。該方法本身不需要涉及屬於其父級類別或子類別的狀態。通過使用 writeObject 方法或使用 DataOutput 支持的用於基本資料型別的方法將各個欄位寫入 ObjectOutputStream,狀態可以被保存。

readObject 方法負責從串流中讀取並恢復類別欄位。它可以調用 in.defaultReadObject 來調用預設機制,以恢復物件的非靜態和非瞬態欄位。defaultReadObject 方法使用串流中的資訊來分派串流中通過當前物件中相應指定欄位保存的物件的欄位。這用於處理類別演化後需要添加新欄位的情形。該方法本身不需要涉及屬於其父級類別或子類別的狀態。通過使用 writeObject 方法或使用 DataOutput 支持的用於基本資料型別的方法將各個欄位寫入 ObjectOutputStream,狀態可以被保存。

在序列化串流不列出給定類別作為將被反序列化物件的父級類別的情況下,readObjectNoData 方法負責初始化特定類別的物件狀態。這在接收方使用的反序列化實例類別的版本不同於發送方,並且接收者版本擴展的類別不是發送者版本擴展的類別時發生。在序列化串流已經被篡改時也將發生;因此,不管源串流是「敵意的」還是不完整的,readObjectNoData 方法都可以用來正確地初始化反序列化的物件。

將物件寫入串流時需要指定要使用的替代物件的可序列化類別,應使用準確的簽章來實作此特殊方法:

 ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
 

此 writeReplace 方法將由序列化調用,前提是如果此方法存在,而且它可以通過被序列化物件的類別中定義的一個方法存取。因此,該方法可以擁有私有 (private)、受保護的 (protected) 和包私有 (package-private) 存取。子類別對此方法的存取遵循 java 存取規則。

在從串流中讀取類別的一個實例時需要指定替代的類別應使用的準確簽章來實作此特殊方法。

 ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
 

此 readResolve 方法遵循與 writeReplace 相同的調用規則和存取規則。

序列化運行時使用一個稱為 serialVersionUID 的版本號與每個可序列化類別相關聯,該序列號在反序列化過程中用於驗證序列化物件的發送者和接收者是否為該物件載入了與序列化相容的類別。如果接收者載入的該物件的類別的 serialVersionUID 與對應的發送者的類別的版本號不同,則反序列化將會導致 InvalidClassException。可序列化類別可以通過宣告名為 "serialVersionUID" 的欄位(該欄位必須是靜態 (static)、最終 (final) 的 long 型欄位)顯式宣告其自己的 serialVersionUID:

 ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
 
如果可序列化類別未顯式宣告 serialVersionUID,則序列化運行時將基於該類別的各個方面計算該類別的預設 serialVersionUID 值,如“Java(TM) 物件序列化規範”中所述。不過,強烈建議 所有可序列化類別都顯式宣告 serialVersionUID 值,原因是計算預設的 serialVersionUID 對類別的詳細資訊具有較高的敏感性,根據編譯器實作的不同可能千差萬別,這樣在反序列化過程中可能會導致意外的 InvalidClassException。因此,為保證 serialVersionUID 值跨不同 java 編譯器實作的一致性,序列化類別必須宣告一個明確的 serialVersionUID 值。還強烈建議使用 private 修飾符顯示宣告 serialVersionUID(如果可能),原因是這種宣告僅應用於直接宣告類別 -- serialVersionUID 欄位作為繼承成員沒有用處。陣列類別不能宣告一個明確的 serialVersionUID,因此它們總是具有預設的計算值,但是陣列類別沒有比對 serialVersionUID 值的要求。

從以下版本開始:
JDK1.1
另請參見:
ObjectOutputStream, ObjectInputStream, ObjectOutput, ObjectInput, Externalizable


JavaTM 2 Platform
Standard Ed. 6

提交錯誤或意見

版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only