繁体   English   中英

从更改的类读取序列化对象的Java兼容性

[英]Java compatibility for serialized object read from changed class

我有这种形式的课程:

public class Foo implements Serializable {

    private static final long serialVersionUID = 20130605L;

    private Object fields[];

    // Methods, etc.
}

一段时间以来还可以,但现在(出于可读性和维护性考虑)已转换为:

public class Foo implements Serializable {

    private static final long serialVersionUID = 20130605L;

    private String field1;
    private String field2;
    private Boolean fiedl3;

    // Methods, etc.
}

当您使用新的类版本读取旧文件时,就会出现问题。 如果使用其他serialVersionUID,则不兼容。 如果您使用相同的serialVersionUID,则我需要实现一些使其兼容的东西。 这是我的办法,重写private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException因此我可以手动检查文件中对象的版本。

问题再次出在我想使用java.io.ObjectInputStream.defaultReadObject(); 因此它会自动对下一个版本进行“魔术处理”(在新字段中为可选字段)。 所以我有这样的事情:

public class Foo implements Serializable {

    private static final long serialVersionUID = 20130605L;

    private String field1;
    private String field2;
    private Boolean fiedl3;

    // Methods, etc.

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {


        Object obj = in.readObject();

            if (obj instanceof Object[]) {
            Object[] tmp = (Object[])obj;
            field1 = (String)obj[0];
            field2 = (String)obj[1];
            // ....
        } else {
            in.defaultReadObject();
        }
    }
}

问题是,因为我已经读取了部分流,所以defaultReadObject方法崩溃。

我正在搜索一个Stream,该Stream可以让您两次读取一个对象,但找不到。 我也知道我可以完全手动进行读取,但是每次添加另一个字段时,我都需要对此进行修改(在defaultReadObject ,由于它写入字段名称,因此只能还原自动读取的字段)。

所以我的问题是“我怎么做?

注意:我只需要兼容性是为了从新类读取旧类对象,并从新类对象读取新类对象。 我也读过其他问题,但他们只回答了如何计划一个具有后卫兼容性的好班级(我应该在:-(之前读过它)。

我发现的唯一解决方案是维护对旧字段的引用。 请注意,您可以将其设置为transient因为这样一来它就不会被读取,因此您必须永远携带它。

public class Foo implements Serializable {

    private static final long serialVersionUID = 20130605L;

    private Object fields[]; // So we can read it in old saved version.

    private String field1;
    private String field2;
    private Boolean fiedl3;

    // Methods, etc.

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {


        in.defaultReadObject();


        if (fields != null) {
            // If we have read an old version.
            field1 = (String)fields[0];
            field2 = (String)fields[1];
            field3 = (Boolean)fields[2];
            // ....

            // We set fields to null so no more space is waste than necessary.
            fields = null;
        }

    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM