匿名类上的NotSerializableException

Sha*_*arg 16 java serialization hadoop interface anonymous-class

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

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);
}
Run Code Online (Sandbox Code Playgroud)

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

public class KeyValFilterCollector extends KeyValCollectorSkeleton {
    private static final long serialVersionUID = -3364382369044221888L;
    KeyValFilter filter;
    public KeyValFilterCollector(KeyValFilter filter) {
        this.filter=filter;
    }
}
Run Code Online (Sandbox Code Playgroud)

当我尝试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:");
        }
});
Run Code Online (Sandbox Code Playgroud)

我得到一个例外:Exception in thread "main" java.io.NotSerializableException.

如何创建我编写Serializable的匿名类?

Mar*_*ler 28

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

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

  • 我将成员过滤器定义为静态,它解决了问题. (3认同)

new*_*cct 11

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

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

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