|
Description
|
A DESCRIPTION OF THE REQUEST :
Java does not allow anonymous classes to be serialized.
This is due to the fact that the constructor generated by the compiler for an anonymous class is done so automatically, and a no-argument constructor is not constructed; furthermore, the compiler prevents the developer from defining their own no-argument contructor for the anonymous class.
Object serialization requires that a no-argument constructor be defined.
JUSTIFICATION :
There are many cases where it is desireable to have fields assigned objects using anonymous classes.
Correspondingly, it is oven desireable to serialize information (e.g., for network transport or for customer ).
Preventing the developer from serializing all anyonmous classes is a severe restriction.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The simplest solution is to automatically generate a no-argument constructor for all anonymous classes.
ACTUAL -
The current behavior prohibits the serialization of all anyonmous classes.
(Review ID: 185561)
======================================================================
|
|
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.
xxxxx@xxxxx 2003-05-15
|
|
Comments
|
Submitted On 12-FEB-2009
Anonymous object of an anonymous class can be serialized iff parent interface or class implements seriazable. if its not,it will throw java.io.NotSerializableException as there is no way of implementing a serializable interface through anonymous class implementation
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 TestInterface() {
public String toString() { return "TestInterface class instance"; }
public void print() {
System.out.println("My Name is TestInterface");
}
});
oout.close();
ObjectInputStream oin = new ObjectInputStream(
new ByteArrayInputStream(bout.toByteArray()));
System.out.println("deserialized: " + oin.readObject());
}
}
public interface TestInterface extends Serializable {
public void print();
}
Thanks
Jit Sen
mail.jitsen@gmail.com
Submitted On 12-FEB-2009
As per posted by Jit I agree. Only adding to his comments objects that are transferred over network are also elligible for Serializable. Hence in web projects also you can face this issue while writing a customized class. We faced this issue while using the apache trinidad <tr:validateDateRestriction> tag and it's attribute inValidDays. This required to implement org.apache.myfaces.trinidad.model.DateListProvider which does not implement the java.io.Serializable interface!
Anirban Datta
adcal15@yahoo.com
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|