I have an interface for filtering items:
public interface KeyValFilter extends Serializable {
public static final long serialVersionUID = 7069537470113689475L;
public boolean acceptKey(String iKey, Iterable<String> iValues);
public boolean acceptValue(String iKey, String value);
}
and a class containing a member of type KeyValFilter
.
public class KeyValFilterCollector extends KeyValCollectorSkeleton {
private static final long serialVersionUID = -3364382369044221888L;
KeyValFilter filter;
public KeyValFilterCollector(KeyValFilter filter) {
this.filter=filter;
}
}
When I try to initiate the KeyValFilterCollector
with an anonymous class implementing KeyValFilter
:
new KeyValFilterCollector(new KeyValFilter() {
private static final long serialVersionUID = 7069537470113689475L;
public boolean acceptKey(String iKey, Iterable<String> iValues) {
for (String value : iValues) {
if (value.startsWith("1:"))
return true;
}
return false;
}
public boolean acceptValue(String iKey, String value) {
return value.startsWith("0:");
}
});
I get an exception: Exception in thread "main" java.io.NotSerializableException
.
How do I make the anonymous class I wrote Serializable?
Joshua Bloch writes in his book Effective Java, 2nd Edition, Item 74:
You can declare anonymous class serializable, but the class is only then really serializable, if all its fields are serializable.
See the example:
If you comment the line
The code finished with success, otherwise
NotSerializableException
is thrown.Usually, the problem seen when serializing anonymous class is that the enclosing class is not serializable (and the author failed to realize that serializing an anonymous class involves serializing its enclosing class).
An anonymous class is a non-static inner class. That means it has a hidden field which references an instance of the enclosing class. When you create it with
new KeyValFilter(){ ... }
, without explicit qualifying it (e.g.something.new KeyValFilter(){ ... }
), thenthis
is implicitly used as the instance of the enclosing class (as if you didthis.new KeyValFilter(){ ... }
). So when you serialize the anonymous class, that requires serializing all its fields, one of which is the instance of the enclosing class, which then must be serializable.If you don't need to use any fields or methods of the enclosing class, you should use a static inner class instead. (It can't be anonymous or defined inside a method however.)