简体   繁体   English

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

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

I have a class of this form: 我有这种形式的课程:

public class Foo implements Serializable {

    private static final long serialVersionUID = 20130605L;

    private Object fields[];

    // Methods, etc.
}

For some time this was ok, but now (for readability and maintenance) have been transformed to: 一段时间以来还可以,但现在(出于可读性和维护性考虑)已转换为:

public class Foo implements Serializable {

    private static final long serialVersionUID = 20130605L;

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

    // Methods, etc.
}

And the problem come when you tray to read old files with the new class version. 当您使用新的类版本读取旧文件时,就会出现问题。 If you use different serialVersionUID, aren't compatible. 如果使用其他serialVersionUID,则不兼容。 If you use the same serialVersionUID, I need to implement something to make it compatible. 如果您使用相同的serialVersionUID,则我需要实现一些使其兼容的东西。 And this is my aproach, overwrite private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException so I can check manually what version is the object in the file. 这是我的办法,重写private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException因此我可以手动检查文件中对象的版本。

The problem again come in that I want to use java.io.ObjectInputStream.defaultReadObject(); 问题再次出在我想使用java.io.ObjectInputStream.defaultReadObject(); so it automatically do its "magic" for next versions (in witch new fields will be optional). 因此它会自动对下一个版本进行“魔术处理”(在新字段中为可选字段)。 So I have something like: 所以我有这样的事情:

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();
        }
    }
}

And the problem is that as I have already read part of the stream, the defaultReadObject method crash. 问题是,因为我已经读取了部分流,所以defaultReadObject方法崩溃。

I have search for a Stream that let you read an object twice, but I don't found it. 我正在搜索一个Stream,该Stream可以让您两次读取一个对象,但找不到。 I also know that I can make the read totally manually, but then each time I add another field I will need to modify this (in defaultReadObject , as it write fields name, it can restore only the field that were read automatically). 我也知道我可以完全手动进行读取,但是每次添加另一个字段时,我都需要对此进行修改(在defaultReadObject ,由于它写入字段名称,因此只能还原自动读取的字段)。

So my question is ¿How can I make it? 所以我的问题是“我怎么做?

Note: I only need that compatibility is for read old class object from new class and new class object from new class object. 注意:我只需要兼容性是为了从新类读取旧类对象,并从新类对象读取新类对象。 Also I have read other question but they only answer how to plan a good class to have backguard compatibility (I should have read it before :-( ). 我也读过其他问题,但他们只回答了如何计划一个具有后卫兼容性的好班级(我应该在:-(之前读过它)。

The only solution that I have found is to maintain a reference to the old field. 我发现的唯一解决方案是维护对旧字段的引用。 Note that you can set it as transient because then it will not be read, so you must carry it for ever. 请注意,您可以将其设置为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