16

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

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);
}

和一个包含 type 成员的类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.

如何使我编写的匿名类可序列化?

4

3 回答 3

28

Joshua Bloch 在他的《 Effective Java, 2nd Edition , Item 74 》一书中写道:

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

于 2013-07-23T08:25:26.587 回答
11

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

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

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

于 2013-07-24T08:37:47.240 回答
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抛出。

于 2013-07-23T09:31:22.367 回答