匿名类上的NotSerializableException

我有一个过滤项目的界面:

public interface KeyValFilter extends Serializable{ public static final long serialVersionUID = 7069537470113689475L; public boolean acceptKey(String iKey, Iterable iValues); public boolean acceptValue(String iKey, String value); } 

以及包含KeyValFilter类型成员的类。

 public class KeyValFilterCollector extends KeyValCollectorSkeleton { /** * */ private static final long serialVersionUID = -3364382369044221888L; KeyValFilter filter; public KeyValFilterCollector(KeyValFilter filter){ this.filter=filter; } 

当我尝试使用实现KeyValFilter的匿名类启动KeyValFilterCollector时:

  new KeyValFilterCollector(new KeyValFilter(){ private static final long serialVersionUID = 7069537470113689475L; public boolean acceptKey(String iKey, Iterable iValues){ for (String value : iValues) { if (value.startsWith("1:")) return true; } return false; } public boolean acceptValue(String iKey, String value){ return value.startsWith("0:"); } }); 

我得到一个exception:线程“main”中的exceptionjava.io.NotSerializableException如何创建我编写Serializable的匿名类?

Joshua Bloch在他的书Effective Java,第2版 ,第74项中写道:

内部类不应该实现Serializable 。 它们使用编译器生成的合成字段来存储对封闭实例的引用,并存储来自封闭范围的局部变量的值。 这些字段如何对应于类定义是未指定的,匿名和本地类的名​​称也是如此。 因此, 内部类的默认序列化forms是未定义的 。 但是, 静态成员类可以实现Serializable

通常,序列化匿名类时遇到的问题是封闭类不可序列化(并且作者没有意识到序列化匿名类涉及序列化其封闭类)。

匿名类是非静态内部类 。 这意味着它有一个隐藏字段,它引用了封闭类的实例。 当你使用new KeyValFilter(){ ... }创建它时,没有明确限定它(例如something.new KeyValFilter(){ ... } ),那么this被隐式地用作封闭类的实例(就像你做了this.new KeyValFilter(){ ... } )。 因此,在序列化匿名类时,需要序列化其所有字段,其中一个是封闭类的实例,然后必须是可序列化的。

如果您不需要使用封闭类的任何字段或方法,则应使用静态内部类。 (但它不能匿名或在方法中定义。)

您可以声明匿名类可序列化,但只有所有字段都可序列化时,该类才真正可序列化。

看例子:

 public static void main(String[] args) throws Exception { Object myObj = new Serializable() { private static final long serialVersionUID = 1L; private String str = "something"; private Object ns = new Object(){}; }; ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(myObj); oos.close(); System.out.println("Success!"); } 

如果你评论该行

 private Object ns = new Object(){}; 

代码成功完成,否则抛出NotSerializableException