2011-05-05 149 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中(这可能是一个非常罕见的事件)是不值得的误报影响的值。