40

Javaのシリアル化を理解することにつまずきました。Java では静的変数と一時変数をシリアライズできないという多くの文書や本を読んだことがあります。次のように serialVersionUid を宣言します。

private static final long serialVersionUID = 1L;

静的変数がシリアル化されていない場合、逆シリアル化プロセス中に例外が発生することがよくあります。

java.io.InvalidClassException

逆シリアル化されたオブジェクトからの serialVersionUID が抽出され、ロードされたクラスの serialVersionUID と比較されます。

私の知る限り、静的変数をシリアル化できないと思います。その例外のポイントはありません。まだ勉強中なので間違っているかもしれません。

「Javaの静的変数と一時変数はシリアル化できない」というのは神話ですか。私を訂正してください、私はこの概念について混乱しています。

4

9 に答える 9

69
  1. インスタンス変数:これらの変数はシリアル化されるため、逆シリアル化中にシリアル化された状態が返されます。

  2. 静的変数:これらの変数はシリアル化されていないため、逆シリアル化中に静的変数の値がクラスから読み込まれます (現在の値が読み込まれます)。

  3. 一時的な変数: transient変数はシリアル化されないため、逆シリアル化中に、これらの変数は対応するデフォルト値で初期化されます (例: オブジェクトnullの 、int 0)。

  4. スーパー クラス変数:スーパー クラスが Serializable インターフェイスも実装している場合、それらの変数はシリアル化されます。それ以外の場合、スーパー クラス変数はシリアル化されません。また、デシリアライズ中に、JVM はスーパー クラスでデフォルト コンストラクタを実行し、デフォルト値を設定します。すべてのスーパークラスで同じことが起こります。

于 2013-05-10T07:43:56.900 に答える
54

serialVersionUID は、シリアル化および逆シリアル化プロセスで使用される特別な静的変数で、ローカル クラスがオブジェクトのシリアル化に使用されるクラスと互換性があることを確認します。これは、間違いなくシリアル化されていない他の変数のような単なる静的変数ではありません。

クラスのオブジェクトが最初にシリアル化されると、特にクラス名とシリアル バージョン UID を含むクラス記述子がストリームに書き込まれます。これがデシリアライズされると、JVM は、ストリームから読み取ったシリアル バージョン UID がローカル クラスのものと同じかどうかをチェックします。そうでない場合は、クラスに互換性がないことがわかっているため、オブジェクトを逆シリアル化しようとさえしません。

于 2012-06-12T16:45:36.863 に答える
5

serialVersionUIDは特別であり、これらの規則の対象ではありません。自動バージョン チェックを実行するために、このフィールドを特に処理するシリアル化機構内のコードがあります。

于 2012-06-12T16:44:01.680 に答える
2

これを自分でテストできます。質問に答えるコードの例を次に示します。

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;

class TestJava implements Serializable{
  public static int k = 10;
  public int j = 5;

  public static void main(String[] args) {

    TestJava tj1= new TestJava();
    TestJava tj2;

        try{ //serialization
            FileOutputStream fos = new FileOutputStream("myclass.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(tj1);
            oos.close();
            fos.close();
            System.out.println("object serielized 1..."+tj1.j);
            System.out.println("object serielized 2..."+tj1.k);
            System.out.println("object serielized 3..."+k);
            k=++k; // 'k' value incrementd after serialization
          } catch(FileNotFoundException fnfe){
             fnfe.printStackTrace();
          } catch(IOException ioex){
             ioex.printStackTrace();
          }

          try{ //deserialization
              FileInputStream fis = new FileInputStream("myclass.ser");
              ObjectInputStream ois = new ObjectInputStream(fis);
              tj2 = (TestJava) ois.readObject();
              ois.close();
              fis.close();
              System.out.println("object DEEEEserielized 1..."+tj2.j);
              System.out.println("object DEEEEserielized 2..."+tj2.k); 
              System.out.println("object DEEEEserielized 3..."+k); 
            // in deserialization 'k' value is shown as incremented. 
            // That means Static varialbe 'K' is not serialized.
            // if 'K' value is serialized then, it has to show old value before incrementd the 'K' value.
            } catch(FileNotFoundException fnfe){
              fnfe.printStackTrace();
            } catch(IOException ioex){
              ioex.printStackTrace();
            } catch(ClassNotFoundException CNFE){
              CNFE.printStackTrace();                   
           }
      }
}

これにより、次のように出力されます。

object serielized 1...5
object serielized 2...10
object serielized 3...10
object DEEEEserielized 1...5
object DEEEEserielized 2...11
object DEEEEserielized 3...11

TestJavaそのため、 1 つの静的整数フィールドと 1 つの非静的フィールドを持つクラスのオブジェクトを作成します。オブジェクトをシリアル化し、シリアル化後に静的整数をインクリメントします。

後でオブジェクトを逆シリアル化すると、値が増加していることがわかります。これは、オブジェクトがシリアル化されていないことを意味します。

于 2015-02-01T17:15:48.947 に答える
0

以下の例は、静的、インスタンス、一時的、およびスーパークラスの変数のシリアライゼーションとその出力について説明しています。

シリアル化クラス:

public class SerializeEx extends SuperSerializeEx implements Serializable {

    private static final long serialVersionUID = 1L;
    public static int staticNumber = 1234;
    public int instanceNumber = 1234;

    public SerializeEx() {
        staticNumber = 0;
        instanceNumber = 0;
        System.out.println("---sub class constructor---");
    }

    public SerializeEx(int staticNumber, int instanceNumber, int superNumber) {
        super(superNumber);
        this.staticNumber = staticNumber;
        this.instanceNumber = instanceNumber;
    }
}

スーパークラス:

public class SuperSerializeEx {

    public int superNumber;

    public SuperSerializeEx() {
        System.out.println("---super class constructor---");
        this.superNumber = 1000;
    }

    public SuperSerializeEx(int superNumber) {
        this.superNumber = superNumber;
    }
}

シリアライゼーションとデシリアライゼーション:

public class MainSerialization {

    public static void main(String[] args) {
        String fileName = "testing.txt";
        serialize(fileName);
        deSerialize(fileName);
    }

    public static void serialize(String fileName) {
        System.err.println("Serialize.....");
        SerializeEx serializeMe = new SerializeEx(10, 10, 10);
        FileOutputStream fos = null;
        ObjectOutputStream out = null;
        try {
            fos = new FileOutputStream(fileName);
            out = new ObjectOutputStream(fos);
            out.writeObject(serializeMe);
            out.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static void deSerialize(String fileName) {
        System.err.println("DeSerialize.....");
        SerializeEx time = null;
        FileInputStream fis = null;
        ObjectInputStream in = null;
        try {
            fis = new FileInputStream(fileName);
            in = new ObjectInputStream(fis);
            time = (SerializeEx) in.readObject();
            in.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }
        System.err.println("Instance Numer = " + time.instanceNumber + " \tStatic Number= " + time.staticNumber + " \t Super Number= " + time.superNumber);
        SerializeEx serializeMe = new SerializeEx(1001, 1001, 1001); //Modifying the static and instnce variables
        System.err.println("Instance Numer = " + time.instanceNumber + " \tStatic Number= " + time.staticNumber + " \t Super Number= " + time.superNumber);
    }
}

出力:

---super class constructor---
Serialize.....
DeSerialize.....
Instance Numer = 10     Static Number= 10      Super Number= 1000
Instance Numer = 10     Static Number= 1001    Super Number= 1000
于 2013-05-10T07:54:02.533 に答える