簡體   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