2013-07-23 79 views
12

我有用于过滤项的接口:NotSerializableException匿名类

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

我得到一个异常:异常在线程“主要” java.io.NotSerializableException 我怎么做匿名类我写了Serializable?

回答

22

约书亚布洛赫在书中写道Effective Java, 2nd Edition,项74:

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

+2

我将成员过滤器定义为静态,并解决了问题。 – Shaharg

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被抛出。

+0

这描述了需要在实现Serializable类的类上进行序列化的所有非瞬态字段的一般情况,而不是一个匿名类。 –

8

通常,序列化匿名类时出现的问题是,封闭类不可序列化(并且作者未能认识到序列化匿名类涉及序列化它的封闭类)。

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

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

+0

“,作者未能认识到序列化匿名类涉及序列化其封闭类”。这正是我的问题。感谢这个提示。 – asmaier