Java反序列化如何忽略属性

时间:2016-10-25 05:48:30

标签: java serialization deserialization

我有一个序列化为文件的对象列表:

class MyClass implements Serializable {

    public String location;
    public SomeClass lastUpdatedAt;

}

不幸的是,我现在有了这个类的新版本,我们不再拥有SomeClass了;原因很复杂,但我需要将其序列化为这种新形式(这是一个示例类,而不是实际的类):

class MyClass implements Serializable {

    public String location;

}

简而言之,我想在反序列化时忽略一个属性。

请注意,我无法更改原始类源文件。我只有新的源文件

ObjectInputStream 在尝试在类路径中找到 SomeClass 时失败:

try {
    FileInputStream fis;
    ObjectInputStream is;
    File f = getSavedFile();
    if (f.exists()) {
        fis = new FileInputStream(f);
        is = new ObjectInputStream(fis);
        ArrayList<MyClass> result = (ArrayList<MyClass>) is.readObject(); //fails
        is.close();
        fis.close();
        }
    }
    catch (Exception e) {
        //ClassNotFound exception because SomeClass is not on the classpath.
        e.printStackTrace();

    }

我知道你可以扩展 ObjectInputStream 并在那里实现一些东西,但我不太熟悉序列化,并希望有人解决了同样的问题。

3 个答案:

答案 0 :(得分:1)

使其成为瞬态会将其从序列化中排除

public transient SomeClass lastUpdatedAt;

根据jls-8.3.1.3

  

变量可能会标记为瞬态,表示它们不属于某一部分   对象的持久状态。

答案 1 :(得分:1)

class MyClass implements Serializable {

    public String location;
    public transient SomeClass lastUpdatedAt;

}

也许你有成功。如果不起作用,则必须覆盖该方法。

出于这个原因,我不喜欢自动序列化,我手动执行:实现序列化的字段和方法。

每次更新代码时,如果使用内置功能,则会出现向后兼容性问题。

答案 2 :(得分:0)

ArrayList<MyClass> result = (ArrayList<MyClass>) is.readObject(); //fails

实际上这会失败,因为元素列表签名不匹配!因为MyClass有1个或多个字段已重命名,添加,删除,所以类型已更改。

MyClass { int a; }

MyClass { String a; } 

将打破反序列化。

您可以尝试覆盖equals()hashCode()方法,以使MyClassNew看起来像MyClass。

Here您可以看到更多如何覆盖所需的方法。这应该会给你一个解决方案。

   private void readObject(java.io.ObjectInputStream stream)
            throws IOException, ClassNotFoundException {
        location = (String) stream.readObject();
    }