FindBugs - SE_BAD_FIELD规则,为什么忽略java.lang.Object?

时间:2011-05-05 14:49:51

标签: java serialization findbugs

来自SE_BAD_FIELD的描述:

  

可序列化类中的非瞬态非序列化实例字段

     

此Serializable类定义非原始实例字段,该字段既不是瞬态,也不是序列化,也不是java.lang.Object,并且似乎不实现Externalizable接口或readObject()和writeObject()方法。如果在此字段中存储非Serializable对象,则不会正确反序列化此类的对象。

为什么java.lang.Object是规则的例外?

2 个答案:

答案 0 :(得分: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(这可能是极为罕见的事件)的价值不值得误报。

答案 1 :(得分:1)

因为所有东西都可以反序列化为java.lang.Object,因为java中的每个类都扩展了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;
       }
    }

在此示例中,反序列化此类将导致nonUser为null,user为正确的SerializableUser类实例,而nonUserObj将为非null,但是它将丢失所有NonSerializableClass方法和字段,它们将不会被序列化。该序列化实例的唯一部分是属于Object的方法和字段。

值得注意的是,许多序列化库(例如ObjectOutputStream)会抱怨非序列化类,并且不会首先序列化此对象。这就是为什么我遗漏了序列化/反序列化步骤的细节。然而,许多xml框架仍将序列化这些类,这往往是这个错误让它成为头脑的情况。