2013-07-23 75 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