I’ve just encountered an interesting problem related to Java serialization.
It seems that if my map is defined like this:
Map<String, String> params = new HashMap<String, String>() {{
put("param1", "value1");
put("param2", "value2");
}};
And I try to serialize it to a file with ObjectOutputStream:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(outputFile));
oos.writeObject(params);
…I get java.io.NotSerializableException.
However, if instead I put values to the map the standard way:
Map<String, String> params = new HashMap<String, String>();
params.put("param1", "value1");
params.put("param2", "value2");
…then serialization work fine.
Can anybody tell me why it happens and what’s the difference between these statements? I think they should work the same, but apparently I’m missing something.
The first example is creating an anonymous inner class. How ?
would create a new class derived from
HashMap(note the following braces, in which you can put methods, members etc.)Your map initialisation then declares an initialiser block thus:
and in that you call your population methods.
This idiom is fine, but you have to be aware that you’re creating a new class, not just a new object.
Because this class is an inner class, it’ll have an implicit
thispointer to the containing outer class. Your anonymous class would be serialisable due to its derivation from a serialisable class. However your outer class (referenced by thethispointer) isn’t.Tools like
XStream, which serialise to XML via reflection, will discover thethispointer and attempt to serialise the surrounding object, which is similarly confusing.