`
z_wang
  • 浏览: 4827 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

Consider using a custom serialized form

    博客分类:
  • Java
 
阅读更多
Generally speaking, you should accept the default serialized form only if it is largely identical to the encoding that you would choose if you were designing a custom serialized form

The default serialized form of an object is a reasonably efficient encoding of the physical representation of the object graph rooted at the object. In other words, it describes the data contained in the object and in every object that is reachable from this object. It also describes the topology by which all of these objects are interlinked. The ideal serialized form of an object contains only the logical data represented by the object. It's independent of the physical representation.

The default serialized form is likely to be appropriate if an object's physical representation is identical to its logical content.

The instance fields in Name precisely mirror this logical content.

Even if you decide that the default serialized form is appropriate, you often must provide a readObject method to ensure invariants and security.

The presence of the @serial tag tells the Javadoc utility to place this documentation on a special page that documents serialized forms.

Logically speaking, this class represents a sequence of strings. Physically, it represents the sequence as a doubly linked list. If you accept the default serialized form, the serialized form will painstakingly mirror every entry in the linked list and all the links between the entries, in both directions.

Using the default serialized form when an object's physical representation differs substantially from its logical data content has four disadvantages:

1. It permanently ties the exported API to the current internal representation.
2. It can consume excessive space.
3. It can consume excessive time.
4. It can cause stack overflows.

Here is a revised version of StringList containing writeObject and readObject methods implementing this serialized form. As a reminder, the transient modifier indicates that an instance field is to be omitted from a class's default serialized form.

Note that the first thing writeObject does is to invoke defaultWriteObject, and the first thing readObject does is to invoke defaultReadObject, even though all of the StringList's field are transient.

If all fields are transient, it's technically permissible to dispense with invoking defaultWriteObject and defaultReadObject, but it's not recommended

Consider the case of a hash table. The physical representation is a sequence of hash buckets containing key-value entries. The bucket that an entry resides in is a function of the hash code of its key, which is not, in general, guaranteed to be the same from JVM implementation to JVM implementation. In fact, it isn't even guaranteed to be the same from run to run. Therefore, accepting the default serialized form for a hash table would constitue a serious bug. Serializing and deserializing the hash table could yield an object whose invariants were seriously corrupt.

Whether or not you use the default serialized form, every instance field that is not labeled transient will be serialized when the defaultWriteObject method is invoked. Therefore, every instance filed that can be made transiant should be mode so.

Before deciding to make a field nontransient, convince yourself that its value is part of the logical state of the object

Regardless of what serialized form you choose, declare an explicit serial version UID in every serializable class you write. This eliminates the serial version UID as a potential source of incompatibility. There is also a small performance benefit. If no serial versino UID is provided, an expensive computation is required to generate one at runtime.

You can generate the value by running the serialver utility on the class, but it's also fine to pick a number out of thin air.

If you ever want to make a new version of a class that is incompatible with existing versions, merely change the value in the serial version UID declaration. This will cause attempts to deserialize serialized instances of previous versions to fail with InvalidClassException

To summary, when you have decided that a class should be serialable, think hard about what the serialized form should be. Use the default serialized form only if it is a reasonable description of the logical state of the object. Otherwise, design a custom serialized form that aptly describes the object.

You should allocate as much time to designing the serialized form of a class as you allocate the designing its exported methods

Just as you cannot eliminate exported methods from future versions, you cannot eliminate fields from the serialized from; they must be preserved forever to ensure serialization compatibility. Choosing the wrong serialized form can have a permanent, negative impact on the complexity and performance of a class.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics