Bits of Java (トップ)

目次  前へ  次へ

フィールドの値をコンストラクタで設定しているクラスの保存

コンストラクタの引数としてフィールドの値を受け取る場合がありますがこのようなクラスの場合には java.beans.PersistenceDelegate のサブクラスを作成しなくても java.beans.DefaultPersistenceDelegate を使って XML に保存できるようになります。 DefaultPersistenceDelegate クラスは JavaBeans のプロパティの書き出しを行い、コンストラクタは引数を取らないタイプの他に String[] を引数に取るタイプがオーバーロードされています。 この引数の String[] は XML に保存させるクラスのコンストラクタの引数となるプロパティ名あるいはフィールド名を格納した配列です。

例えば java.awt.Point クラスは API ドキュメントのクラス説明に

整数精度で指定される、(x, y) 座標空間での位置を表す点です。
とあります。この Point クラスにはデフォルトコンストラクタと座標の点 x と y の値を取得する getX と getY というメソッドは用意されていますが設定用の setX や setY メソッドは定義されていません。よってデフォルトではプロパティとして 内部状態を XML に保存することができません。 ですが、これらの内部状態は以下のコンストラクタで設定可能です。
    public Point(int x, int y)
このようなケースでは DefaultPersistenceDelegate を使えば PersistenceDelegate のサブクラスを作成しなくても簡単に XML に x や y の値が書き出されるようにできます。 以下のようなコードになります。
    XMLEncoder encoder = new XMLEncoder(
                                 new BufferedOutputStream(
                                     new FileOutputStream("data.xml")));
    DefaultPersistenceDelegate pd = new DefaultPersistenceDelegate(
                                                new String[]{"x", "y"});
    encoder.setPersistenceDelegate(java.awt.Point.class, pd);
これで encoder の writeObject メソッドが呼び出された際に Point オブジェクトを XML に保存できるようになります。

DefaultPersistenceDelegate の引数に指定している String[] ですが API ドキュメントには XML に保存するクラスのコンストラクタの引数となるプロパティ名と記述されていますが実際にはフィールド名の場合もあります。 まず最初にフィールド名と仮定して探し、フィールド名でない場合にはプロパティ名として対象クラスを探します。 プロパティの場合には getter メソッドが用意されている必要があります。(setter メソッドの有無は関係ありません。フィールド名の場合の例として java.awt.Insets があります)

下のプログラムは DefaultPersistenceDelegate を使ってコンストラクタの引数となるフィールドまたはプロパティの値を XML に保存可能にする例です。 Book を処理するための DefaultPersistenceDelegate オブジェクトを作成する際の引数となる String[] は

    new String[]{"author", "title", "price"}
ですが author はフィールド名でテストの為に private にしていますがそれでも値が書き出されます。 title はプロパティ名で実装はフィールド text の値を返しています。 price はテストの為にフィールドとプロパティの両方が Book クラスに存在します。 この場合には前述のように getPrice メソッドの値(price プロパティ)ではなくフィールド price の値が書き出されます。もし Book クラスにこれら以外に getter setter の両方が揃っているプロパティが存在する場合には (String, String, int) を引数にとるコンストラクタを実行した直後の値と等価でなければ保存時に XML にプロパティとして書き出されます。

/******************** Book.java ********************/
public class Book {
    private String author;
    private String text;
    private int yen;
    private int price = 1260;

    public Book(String author, String title, int price) {
        this.author = author;
        text = title;
        yen = price;
    }

    public String getTitle() {
        return text;
    }
    public int getPrice() {
        return yen;
    }
}

/******************** Test.java ********************/
import java.beans.*;
import java.io.*;

public class Test {
    public static void main(String[] args) throws FileNotFoundException {

        Book book = new Book("星新一", "きまぐれロボット", 357);
        XMLEncoder encoder = new XMLEncoder(
                                 new BufferedOutputStream(
                                     new FileOutputStream("sample.xml")));

        String[] fildNames = new String[]{"author", "title", "price"};
        DefaultPersistenceDelegate bookPersistenceDelegate =
                               new DefaultPersistenceDelegate(fildNames);
        encoder.setPersistenceDelegate(Book.class,
                                       bookPersistenceDelegate );
        encoder.writeObject(book);
        encoder.close();
    }
}

/******************** sample.xml ********************/
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.5.0_01" class="java.beans.XMLDecoder">
 <object class="Book">
  <string>星新一</string>
  <string>きまぐれロボット</string>
  <int>1260</int>
 </object>
</java>