我有一个过滤项目的界面:
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);
}
以及包含KeyValFilter
类型成员的类。
public class KeyValFilterCollector extends KeyValCollectorSkeleton {
private static final long serialVersionUID = -3364382369044221888L;
KeyValFilter filter;
public KeyValFilterCollector(KeyValFilter filter) {
this.filter=filter;
}
}
当我尝试使用实施KeyValFilterCollector
的匿名类启动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:");
}
});
我得到一个例外:Exception in thread "main" java.io.NotSerializableException
。
如何创建我编写Serializable的匿名类?
答案 0 :(得分:27)
Joshua Bloch在他的书Effective Java, 2nd Edition中写道,第74项:
内部课程不应实施
Serializable
。它们使用编译器生成的合成字段来存储对封闭实例的引用,并存储来自封闭范围的局部变量的值。这些字段如何对应于类定义是未指定的,匿名和本地类的名称也是如此。因此,内部类的默认序列化形式是错误定义的。但是,静态成员类可以实现Serializable
。
答案 1 :(得分:11)
通常,序列化匿名类时遇到的问题是封闭类不可序列化(并且作者没有意识到序列化匿名类涉及序列化其封闭类)。
匿名类是非静态内部类。这意味着它有一个隐藏字段,它引用了封闭类的实例。当您使用new KeyValFilter(){ ... }
创建它时,如果没有明确限定它(例如something.new KeyValFilter(){ ... }
),则隐式使用this
作为封闭类的实例(就像您this.new KeyValFilter(){ ... }
一样)。因此,在序列化匿名类时,需要序列化其所有字段,其中一个是封闭类的实例,然后必须是可序列化的。
如果您不需要使用封闭类的任何字段或方法,则应使用静态内部类。 (但它不能匿名或在方法中定义。)
答案 2 :(得分:0)
您可以声明匿名类可序列化,但只有所有字段都可序列化时,该类才真正可序列化。
参见示例:
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
。