3

クラス メンバー (静的) はシリアル化できません。その理由は明らかです。それらはクラスのオブジェクトによって保持されていません。これらは (クラスのオブジェクトではなく) クラスに関連付けられているため、オブジェクトとは別に格納されます。

serialVersionUIDjava.io.Serializable次のようなインターフェイスを実装するクラス内の静的フィールドとして宣言されます。

private static final long serialVersionUID = 1L;

クラスのバージョン管理として使用されSerializableます。明示的に宣言されていない場合は、Java(TM) Object Serialization SpecificationSerializableで説明されているように、クラスのさまざまな側面に基づいて JVM によって自動的に実行されます。

インターフェイスを実装するクラス内で明示的に宣言されていない場合Serializable、警告が発行されることがあります。

シリアライズ可能なクラスは型のフィールドをSomeClass宣言していませんstatic final serialVersionUIDlong

とはいえシリアライズされているのですがstatic、どうですか、それともシリアライズの例外ですか?

4

4 に答える 4

4

シリアライゼーションは「魔法のように」行われ、多くのリフレクションが行われ、あらゆる種類の特別な動作が行われます。たとえば、クラスの静的な検索が含まれます。 serialVersionUID

于 2012-12-17T17:30:59.353 に答える
2

それserialVersionUID自体はシリアライズされていません。少なくとも、オブジェクトの他のプロパティと同じ方法ではありません。代わりに、書き込まれるオブジェクトを再構築するために必要な情報を含む特別な「ヘッダー」の一部として、出力先に書き出されます。

于 2012-12-17T17:43:07.360 に答える
2

serialVersionUIDファイルへの/からのオブジェクトの書き込みおよび読み取り中に使用することを明確にしましょう。

以下のコードでは、2 つの関数writeObject()readObj()

writeObject()オブジェクトをファイルに書き込むためのものです

readObj()ファイルからオブジェクトを読み取るためのものです

package com.msq;

import java.io.Serializable;

public class A implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    int a;
    transient int b;

    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
    public int getB() {
        return b;
    }
    public void setB(int b) {
        this.b = b;
    }
}
package com.msq;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class B implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 123L ;
    /**
     * 
     */
    String name;
    A a;

    public B() {

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }

    public static void main(String[] args) {

        //writeObject();
        readObj();
    }

    static void writeObject() {
        B b = new B();
        b.setName("Musaddique");
        A a2 = new A();
        a2.setA(5);
        a2.setB(10);
        b.setA(a2);
        ObjectOutputStream write = null;

        try {
            write = new ObjectOutputStream(new FileOutputStream(
                    "D:\\serObj.bat"));
            write.writeObject(b);
            write.flush();
            write.close();

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    static void readObj() {
        ObjectInputStream reader = null;

        try {
            reader = new ObjectInputStream(
                    new FileInputStream("D:\\serObj.bat"));
            B b1 = (B) reader.readObject();
            System.out.println("name: "+b1.getName());
            System.out.println("value of a: "+b1.getA().getA());
            System.out.println("value of b: "+b1.getA().getB());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

ここではserialVersionUID = 123L、クラス B とserialVersionUID = 1Lクラス A に使用transientし、変数 b にもキーワードを使用して、b の値をファイルに保存するように制限しています。

1)データをファイルに書き込み、ファイルを読み取り、次の出力を取得します

name: Musaddique
value of a: 5
value of b: 0

b にトランジェントを使用したため、b: 0 の値が得られます。

テストのために、同じ呼び出しでオブジェクトを書き込もうとしますが、変更の読み取り中serialVersionUID = 765Lに例外が発生します

java.io.InvalidClassException: com.msq.B; local class incompatible: stream classdesc serialVersionUID = 123, local class serialVersionUID = 765
    at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
    at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
    at java.io.ObjectInputStream.readClassDesc(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at com.msq.B.readObj(B.java:81)
    at com.msq.B.main(B.java:46)

serialVersionUIDそのため、ファイルからオブジェクトを読み書きするときに同じものを使用する必要があります。

また、あるマシンから別のマシンまたはシステムにクラスを組み込むときに、RMI 呼び出しで使用されます。

于 2015-06-30T12:18:05.440 に答える
1

serialVersionUIDシリアル化されるオブジェクト データの一部ではなく、クラス記述の一部と考えてください。クラス名がシリアライゼーション ストリームの一部であるのと同じ方法です。ストリーム形式の詳細については、Grammar for the Stream Format に記載されています。

于 2012-12-17T17:46:42.430 に答える