`
qqdwll
  • 浏览: 131596 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java Serializable

    博客分类:
  • Java
阅读更多
  Java 的 Serialazable 虽然只要要在类上加个申明, 类就可以被Serializable了。 但其实, 它并不是想象中的这么简单。 他会有很多的问题, 这是应为object被Serialaized 之后,可以认为是输出的API了。  那么, 对这个类的修改, 就会产生很多问题。 比如, 删除某些fields, 都可能导致deserializing失败。 下面给出一些系列化要注意的地方。

1.  Serial version UIDs.
Every serializable
class has a unique identification number associated with it. If you do not specify
the identification number explicitly by declaring a private static final long field named
serialVersionUID, the system automatically generates it by applying a complex
deterministic procedure to the class. The automatically generated value is affected by
the class's name, the names of the interfaces it implements, and all of its public and protected
members. If you change any of these things in any way, for example,by adding a trivial convenience method, the automatically generated serial version UID changes. If you fail to
declare an explicit serial version UID, compatibility will be broken.

2.  Do not accept the default serialized form without first considering whether it is
appropriate. Accepting the default serialized form should be a conscious decision on your
part that this encoding is reasonable from the standpoint of flexibility, performance, and
correctness. 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 is 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. For example, the default serialized form
would be reasonable for the following class, which represents a person's name:
//Good candidate for default serialized form
public class Name implements Serializable {
/**
* Last name. Must be non-null.
* @serial
*/
private String lastName;
/**
* First name. Must be non-null.
* @serial
*/
private String firstName;
/**
* Middle initial, or '\u0000' if name lacks middle initial.
* @serial
*/
private char middleInitial;
... // Remainder omitted
}
Logically speaking, a name consists of two strings that represent a last name and first name
and a character that represents a middle initial. 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.


A reasonable serialized form for StringList is simply the number of strings in the list,
followed by the strings themselves. This constitutes the logical data represented by a
StringList, stripped of the details of its physical representation. 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:
//StringList with a reasonable custom serialized form
public class StringList implements Serializable {
private transient int size = 0;
private transient Entry head = null;
// No longer Serializable!
private static class Entry {
String data;
Entry next;
Entry previous;
}
// Appends the specified string to the list
public void add(String s) { ... }
/**
* Serialize this <tt>StringList</tt> instance.
*
* @serialData The size of the list (the number of strings
* it contains) is emitted (<tt>int</tt>), followed by all of
* its elements (each a <tt>String</tt>), in the proper
* sequence.
*/
private void writeObject(ObjectOutputStream s)
throws IOException {
s.defaultWriteObject();
s.writeInt(size);
// Write out all elements in the proper order.
for (Entry e = head; e != null; e = e.next)
s.writeObject(e.data);
}
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
int size = s.readInt();
// Read in all elements and insert them in list
for (int i = 0; i < size; i++)
add((String)s.readObject());
}
... // Remainder omitted
}
Note that the writeObject method invokes defaultWriteObject and the readObject
method invokes defaultReadObject, even though all of StringList's fields are transient. If
all instance fields are transient, it is technically permissible to dispense with invoking
defaultWriteObject and defaultReadObject, but it is not recommended. Even if all
instance fields are transient, invoking defaultWriteObject affects the serialized form,
resulting in greatly enhanced flexibility. The resulting serialized form makes it possible to add
nontransient instance fields in a later release while preserving backward and forward
compatibility. If an instance is serialized in a later version and deserialized in an earlier
version, the added fields will be ignored. Had the earlier version's readObject method failed
to invoke defaultReadObject, the deserialization would fail with
a StreamCorruptedException.
Note that there is a documentation comment on the writeObject method, even though it is
private. This is analogous to the documentation comment on the private fields in the Name
class. This private method defines a public API, the serialized form, and that public API
should be documented. Like the @serial tag for fields, the @serialData tag for methods
tells the Javadoc utility to place this documentation on the serialized forms page.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics