33

Bar が Foo を拡張して実装する Foo と Bar という 2 つのクラスがあるとします。Serializable

class Foo {

public String name;

public Foo() {
    this.name = "Default";
}

public Foo(String name) {
    this.name = name;
}
}

class Bar extends Foo implements java.io.Serializable {

public int id;

public Bar(String name, int id) {
    super(name);
    this.id = id;
}
}

Foo は を実装していないことに注意してくださいSerializable。では、bar がシリアライズされるとどうなるでしょうか?

    public static void main(String[] args) throws Exception {

    FileOutputStream fStream=new FileOutputStream("objects.dat");
    ObjectOutputStream oStream=new ObjectOutputStream(fStream);
    Bar bar=new Bar("myName",21);
    oStream.writeObject(bar);

    FileInputStream ifstream = new FileInputStream("objects.dat");
    ObjectInputStream istream = new ObjectInputStream(ifstream);
    Bar bar1 = (Bar) istream.readObject();
    System.out.println(bar1.name + "   " + bar1.id);

} 

「デフォルト21」と出力されます。問題は、クラスがシリアル化されていないときにデフォルトのコンストラクターが呼び出されるのはなぜですか?

4

3 に答える 3

24

Serializable は、特定のクラスの単なる「マーカー インターフェイス」です。

ただし、そのクラスは特定の規則に従う必要があります。

http://docs.oracle.com/javase/1.5.0/docs/api/java/io/Serializable.html

シリアル化できないクラスのサブタイプをシリアル化できるようにするために、サブタイプは、スーパータイプの public フィールド、protected フィールド、および (アクセス可能な場合) package フィールドの状態を保存および復元する責任を負う場合があります。サブタイプは、それが拡張するクラスに、クラスの状態を初期化するためのアクセス可能な引数なしのコンストラクターがある場合にのみ、この責任を負うことができます。そうでない場合、Serializable クラスを宣言するとエラーになります。

コメントで尋ねられた@Sleiman Jneidiの質問に答えるには、上記のオラクルのドキュメントで、明確に言及されています

逆シリアル化中に、シリアル化できないクラスのフィールドは、クラスのパブリックまたは保護された引数なしのコンストラクターを使用して初期化されます。引数なしのコンストラクターは、シリアル化可能なサブクラスにアクセスできる必要があります。シリアライズ可能なサブクラスのフィールドは、ストリームから復元されます。

したがって、クラス Foo のデフォルトの引数のないコンストラクターが呼び出された結果、初期化されました。

于 2011-12-25T23:33:44.057 に答える
4

defaultWriteObject は、現在のクラスの非静的および非一時的なフィールドのみを書き込むことができる可能性があります。スーパークラスが Serializable インターフェイスを実装しないと、スーパークラスのフィールドをストリームにシリアル化できなくなります。

于 2013-08-07T13:13:46.370 に答える
0

実際には、親クラスのオブジェクトはまったくシリアル化されていないため、読み戻す場合..シリアル化されていないものについては、JVM は new キーワードを使用して新しいオブジェクトを作成するときと同じプロセスを実行します。

于 2013-12-25T05:48:09.227 に答える