EVALUATION
Object serialization only requires that a class defines a no-argument
constructor if it is externalizable. If the class is serializable (but not
externalizable), then the class itself does not need to define a no-argument
constructor--its closest non-serializable superclass, however, must define a
subclass-accessible no-argument constructor. For example, the following code
successfully serializes and deserializes an anonymous class instance; this is
possible because the anonymous class subclasses java.lang.Object, which defines
a public no-arg constructor:
import java.io.*;
public class Foo {
public static void main(String[] args) throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oout = new ObjectOutputStream(bout);
oout.writeObject(new Serializable() {
public String toString() { return "anonymous class instance"; }
});
oout.close();
ObjectInputStream oin = new ObjectInputStream(
new ByteArrayInputStream(bout.toByteArray()));
System.out.println("deserialized: " + oin.readObject());
}
}
Serialization of anonymous class instances, however, is discouraged due to
several known complications. These are spelled out in section 1.10 of the
serialization specification:
Note - Serialization of inner classes (i.e., nested classes that are not
static member classes), including local and anonymous classes, is strongly
discouraged for several reasons. Because inner classes declared in non-static
contexts contain implicit non-transient references to enclosing class
instances, serializing such an inner class instance will result in
serialization of its associated outer class instance as well. Synthetic
fields generated by javac (or other JavaTM compilers) to implement inner
classes are implementation dependent and may vary between compilers;
differences in such fields can disrupt compatibility as well as result in
conflicting default serialVersionUID values. The names assigned to local and
anonymous inner classes are also implementation dependent and may differ
between compilers. Since inner classes cannot declare static members other
than compile-time constant fields, they cannot use the serialPersistentFields
mechanism to designate serializable fields. Finally, because inner classes
associated with outer instances do not have zero-argument constructors
(constructors of such inner classes implicitly accept the enclosing instance
as a prepended parameter), they cannot implement Externalizable. None of the
issues listed above, however, apply to static member classes.
Foremost among these issues is the fact that anonymous classes do not have
well-defined names--it's up to the compiler to choose a name for the class.
This means that if you take an application that serializes an anonymous class,
and happen to compile the writing and reading ends of it with different
versions/implementations of javac, then serialization of the class may very
well fail, since there's no agreed name for the class (i.e., if the sender
uses the class name Foo$1 and the receiver uses Foo$2, serialization has no way
of knowing that Foo$1 should map to Foo$2). An easy workaround for this issue
is to use a named class instead of an anonymous class. In light of the issues
enumerated above, it's also recommended that this named class be either a
non-nested class, or, if it must be nested, a static member class.
###@###.### 2003-05-15
|