Bits of Java (トップ)

目次  前へ  次へ

Serializable オブジェクトを直列化しようとした際のエラー

Serializable インターフェイスの実装はどのクラスでも implements 節でできますが実際にそのクラスのインスタンスが直列化できるかどうかはそのクラスの設計によります。 下のプログラムの Book クラスは Serializable インターフェイスを実装しており3つのフィールドを持っています。 この Book クラスのインスタンスを ObjectOutputStream#writeObject メソッドで直列化しようとすると失敗してしまいます。 ObjectOutputStream#writeObject メソッドで直列化できるのはプリミティブ型か Serializable インターフェイスを実装したオブジェクトでなければなりません。 Book クラスのフィールド object は Object クラスのインスタンスで Serializable インターフェイスは実装されていません。 よって SerializationSample を実行すると

Exception in thread "main" java.io.NotSerializableException: java.lang.Object
        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
        at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
        at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
        at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
        at java.io.ObjectOutputStream.writeObject(Unknown Source)
        at SerializationSample.main(SerializationSample.java:11)
このような例外が発生してしまいます。 (ただし Sun の J2SE1.4.2 では ObjectOutputStream#writeObject メソッドで直列化しようとした際に Book オブジェクトのフィールド object が null の場合にはこの例外は発生しません。 つまり直列化しようとしたフィールドが Serializable オブジェクトではない時にその参照が null の場合と null ではない場合では例外が発生したりしなかったりします。 ドキュメントにこれに関する記述を見つけられなかったのでこれは仕様ではない可能性があります。 よって将来のバージョンでは違う動作になる可能性もありますのでこの振る舞いに依存したコードは書かない方がよいと思われます。)

ObjectOutputStream#writeObject メソッドは transient フィールドと static フィールドに関する直列化は行いません。 static フィールドはロードされたクラスに属するフィールドでオブジェクトごとに存在するのではないので直列化されません。 transient キーワードに関しては次のページで説明します。

/**************************** Book.java ****************************/
public class Book implements java.io.Serializable {
    protected String title;
    protected String author;
    protected Object object = new Object();

    public Book() {}

    public Book(String title, String author) {
        this.title  = title;
        this.author = author;
    }
//--------------------------------------------------------------------
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
//--------------------------------------------------------------------
    public String toString() {
        return "Book title:" + title + "  author:" + author +
               "  object:" + object;
    }
}


/********************* SerializationSample.java *********************/
import java.io.*;

public class SerializationSample {
    public static void main(String[] args) throws Exception {
        Book book = new Book("きまぐれロボット", "星新一");
        ObjectOutputStream out = null;
        try {
            out = new ObjectOutputStream(new BufferedOutputStream(
                                         new FileOutputStream("data")));
            out.writeObject(book);
            out.flush();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {}
            }
        }
    }
}