2011-05-05 153 views
6

SE_BAD_FIELD的描述:在序列化類FindBugs - SE_BAD_FIELD規則,它爲什麼忽略java.lang.Object?

非瞬態不可序列實例字段

這Serializable類定義了一個非原始實例字段既不是瞬時的,序列化的,或java.lang中.Object,並且不會實現Externalizable接口或readObject()和writeObject()方法。如果在此字段中存儲不可序列化的對象,則此類的對象將不會正確反序列化。

爲什麼java.lang.Object是規則的例外?

+0

也許筆者預計,如果您任意選擇java.lang.Object作爲一個屬性(最普遍的類型,對此你不能假設任何事情)的類型,而不是某種特定類型的,你已經清楚地知道該序列不能在這方面合理工作。但我同意這個例外很奇怪:畢竟,這個錯誤很可能是因爲你簡單地忘記了瞬態修飾符! – 2011-05-05 15:14:45

+0

它可能有一些做與鎖定的對象。 – Matt 2011-05-05 15:19:30

+0

或者可能是數組。 – 2011-05-05 15:43:30

回答

1

由於java中的每個類都擴展了java.lang.Object,因此一切都可以反序列化回java.lang.Object。如果您設法序列化具有不可序列化字段的對象,則無法知道反序列化中該字段的類。因爲每個類都是一個對象,所以你總是可以回到Object類。

class NonSerializableUser {} 
    class SerializableUser implements Serializable{} 

    class SomeObject implements Serializable{ 
     public NonSerializableUser nonUser; 
     public SerializableUser user; 
     public Object nonUserObj; 

     public SomeObject(SerializableUser u, NonSerializableUser uu, NonSerializableUser uuu){ 
      user = u; 
      nonUser = uu; 
      nonUserObj = uuu; 
     } 
    } 

在這個例子中反序列化這個類會導致非用戶被空,用戶是正確的SerializableUser類的實例,並nonUserObj將是非零但它已經失去了所有的NonSerializableClass方法和字段,他們將不會有已連載。該實例中唯一被序列化的部分是屬於Object的方法和字段。

值得一提的是,大量的序列化庫(ObjectOutputStream的爲例)會抱怨非序列化類,並在第一時間將不序列化此對象。這就是爲什麼我忽略了序列化/反序列化步驟的細節。但是大量的XML框架仍將序列化這些類,這往往是哪裏這個bug撫養它的頭的情況。

2

誤報的數量將是潛在的高,如

public void writeIt(Object o, ObjectOutputStream oos) { 
    oos.writeObject(o); 
} 

可以是完全正常的,因爲呼叫方總是通過在一個派生類是可序列化的一個實例。

現在的問題是,爲什麼不是上面的方法簽名

public void writeIt(Serializable o, ObjectOutputStream oos) { 
    oos.writeObject(o); 
} 

的答案是,那麼各種通過傳遞作爲第一個參數的接口定義的對象會出錯。

Map m = ..... 
writeIt(m, oos); 

如此醒目序列化java.lang.Object中(這可能是一個非常罕見的事件)是不值得的誤報影響的值。