目次


Eclipse Galileo でJava コーディングを迅速に行う

新しい toString() 生成プログラムを使う

Comments

コード生成のヒントを紹介するこの記事では、Eclipse Galileo で導入された新しい機能を使います。ただし、この記事で説明する手法の一部、例えばゲッターとセッターの生成などは、古いバージョンの Eclipse (Ganymede など) でも使用することができます。

コード生成の概要

私が Eclipse で日常的に使用する機能のうち、最も頻繁に使う機能は、「Source (ソース)」メニューの中にあるコード生成のための項目です。それらの項目の効果的な使い方を理解するまで少し時間がかかりましたが、理解できてしまうと、Java クラスを極めて迅速に作成できるようになりました。

例えば新しいクラスを作成する場合、まったく時間をかけずにセッターとゲッター (アクセサー) を作成できるようになりました。コンストラクターを作成することはほとんどなくなり、代わりに、作成したクラスの中で使用するプライベート変数をすぐに宣言して型付けします (リスト 1)。

リスト 1. プライベート変数
public class Automobile {

    private String make;
    private String model;
    private String year;

}

それが終わったら、「Source (ソース)」 > 「Generate Getters and Setters (getter および setter の生成)」の順にクリックし、パブリック・アクセサーを使って公開する予定のプライベート変数 (先ほど型付けしたプライベート変数) を選択します。それらのプライベート変数の一部を、コンストラクターを使って初期化するためには、「Source (ソース)」 > 「Generate Constructor using Fields (フィールドを使用してコンストラクターを生成)」の順にクリックします。すると、すぐにコンストラクターが作成されます。そのクラスを使って何をするかによりますが、数回マウスをクリックするだけでほとんど完全なクラスが出来上がります (リスト 2)。何よりも良いことに、新しく作成されたコードは、Eclipse の「Preferences (設定)」に設定されたコード・フォーマットのルールに従ったものになります。

リスト 2. コンストラクターとアクセサーを自動的に作成する
public class Automobile {

    private String make;
    private String model;
    private String year;

    public String getMake() {
        return make;
    }

    public Automobile(String make, String model, String year) {
        super();
        this.make = make;
        this.model = model;
        this.year = year;
    }

    public void setMake(String make) {
        this.make = make;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

}

「Source (ソース)」メニューの中にある項目を使って生成できるコードの他にも、さまざまなコードを生成することができます。「Ctrl+スペース」のショートカットを使うと、一般的なコード・ブロックの多くを作成することができます。特定のブロックを生成するために必要な名前を知るためには、「Preferences (設定)」ウィンドウを調べます。例えば、「lazy」と入力してから「Ctrl+スペース」を押すと、遅延ローディングに使用できる Java コードが生成されます。

コード生成のための設定

新しいメソッドに対するコード生成の設定を変更するためには、「Preferences (設定)」ウィンドウで「Java」 > 「Code Style (コード・スタイル)」 > 「Code Templates (コード・テンプレート)」の順に選択します。

図 1. 「Preferences (設定)」ウィンドウで「Java」 > 「Code Style (コード・スタイル)」 > 「Code Templates (コード・テンプレート)」の順に選択する
「Preferences (設定)」ウィンドウで「Java」 > 「Code Style (コード・スタイル)」 > 「Code Templates (コード・テンプレート)」の順に選択する
「Preferences (設定)」ウィンドウで「Java」 > 「Code Style (コード・スタイル)」 > 「Code Templates (コード・テンプレート)」の順に選択する

Preferences (設定)」ウィンドウで「Java」 > 「Editor (エディター)」 > 「Templates (テンプレート)」の順に選択すると、名前順にテンプレートのリストが表示されます (図 2)。Eclipse に同梱されているテンプレートを探します。独自のテンプレートを追加することもでき、さらにはテンプレートをインポートすることもできます。

図 2. 「Preferences (設定)」ウィンドウで「Java」 > 「Editor (エディター)」 > 「Templates (テンプレート)」の順に選択する
「Preferences (設定)」ウィンドウで「Java」 > 「Editor (エディター)」 > 「Templates (テンプレート)」の順に選択する
「Preferences (設定)」ウィンドウで「Java」 > 「Editor (エディター)」 > 「Templates (テンプレート)」の順に選択する

toString() 生成機能を使う

Eclipse Galileo での新しい機能として、toString() メソッドを生成することができます。toString() メソッドはデフォルトでクラスの表現を出力しますが、その表現の中には実際にユーザーが見たいと思っているプロパティーが表示されないかもしれません。リスト 3 の Main メソッドを考えてみてください。

リスト 3. toString() を使って Automobile を出力する
public class Main {
    public static void main(String[] args) {
        Automobile auto = new Automobile("Toyota", "Corolla", "1993");
        System.out.println(auto.toString());
    }
}

このアプリケーションの出力をリスト 4 に示します。

リスト 4. Main メソッドの出力Main method
Automobile@77df38fd

Galileo が登場する前は、toString() メソッドは手動でコーディングしなければなりませんでした。この例のように簡単なクラスの場合にはそれほど大変ではありませんが、もっと多くのフィールドがあるクラスの場合には、作成に長い時間がかかります。また、単純に値を連結する以上のことをしなければならない場合や、ヌルをチェックしたい場合、さらには StringBuilder を使ってパフォーマンスを高めたい場合があるかもしれません。しかし Galileo では、そうしたことをすべて、「Source (ソース)」 > 「Generate toString() (toString() の生成)」の順に選択することで実現できるのです (図 3)。

図 3. toString() 生成機能
toString() 生成機能
toString() 生成機能

Finish (完了)」をクリックすると、新しい toString() メソッドはリスト 5 のようになります。

リスト 5. 自動的に生成された toString() メソッド
...
    @Override
    public String toString() {
        return "Automobile [" + (make != null ? "make=" + make + ", " : "")
                + (model != null ? "model=" + model + ", " : "")
                + (year != null ? "year=" + year : "") + "]";
    }
...

これで Main メソッドを実行すると、出力はリスト 6 のようになります。

リスト 6. 自動的に生成された toString() メソッドの出力
Automobile [make=Toyota, model=Corolla, year=1993]

ストリングのフォーマットを設定する

リスト 6 の出力はリスト 4 に示した元の出力よりもわかりやすい表現になっていますが、少しフォーマットを調整し、さらに読みやすくすると、もっと良くなるかもしれません (例えば「1993 Toyota Corolla (Automobile)」など)。カスタムのテンプレートを使用すると、toString() メソッド用に生成された出力を調整することができます。

toString() メソッドを削除し、「Source (ソース)」 > 「Generate toString() (toString() の生成)」の順に再度クリックします。そして今度は、

  1. String format (文字列の書式)」ドロップダウン・リストの隣にある「Edit (編集)」をクリックします。
  2. 表示された画面で「New (新規)」をクリックします。
    図 4. 新しいフォーマットを追加する
    新しいフォーマットを追加する
    新しいフォーマットを追加する
  3. Pattern (パターン)」の中に ${member.value} ${otherMembers} (${object.className}) のように入力し、そのパターンに名前を付け、「OK」をクリックします。

この新しいパターンが選択された状態で、「Generate toString() (toString() の生成)」画面で「OK」をクリックします。新しいコードはリスト 7 のようになります。

リスト 7. 更新された toString() メソッド
...
    @Override
    public String toString() {
        return (make != null ? make + " " : "")
                + (model != null ? model + " " : "")
                + (year != null ? year : "") + " (Automobile)";
    }
...

これで Main メソッドを実行すると、Automobile オブジェクトの toString() の出力はリスト 8 のようになります。

リスト 8. Automobile オブジェクトの toString() メソッドの出力
Toyota Corolla 1993 (Automobile)

配列を扱う

toString() 生成プログラムを使うと、配列も処理することができます。リスト 9 を考えてみてください。このリストは、新しい、options という名前のストリングの配列を示しています。

リスト 9. options という名前のストリングの配列
        Automobile auto = new Automobile("Toyota", "Corolla", "1993");
        String[] options = new String[] {
                "Automatic Transmission",
                "Power Brakes",
                "Power Windows"
        };
        // new generated method after adding private String[] options;
        auto.setOptions(options);
        System.out.println(auto.toString());
        // prints this:
        // Toyota Corolla [Ljava.lang.String;@defb836 1993 (Automobile)

通常、ネイティブの toString() メソッドは配列の表現を出力します。この表現はそのオブジェクトの元の表現とまったく同じですが、実際に配列の内容を表示することはありません。しかし、オプションの「List contents of arrays instead of using native toString (ネイティブの toString() を使用する代わりに配列のコンテンツをリスト)」を選択すると、それを変更することができます。このオプションを選択すると、toString() メソッドを再生成することができ、新しい出力はリスト 10 のようになります。

リスト 10. 再生成された toString() メソッドの出力
Toyota Corolla [Automatic Transmission, Power Brakes, Power Windows] 1993 (Automobile)

出力を制限する

配列の一部が非常に大きい場合には、出力される内容を制限することができます。そのためには「Limit number of items in arrays/collections/maps (配列/コレクション/マップ内の項目の数を次に制限)」を選択し、制限数を設定します (図 5)。こうすることによって、toString() メソッドによる大量の出力を制限することができます。

図 5. 配列の内容を出力し、ただし出力数を制限する
配列の内容を出力し、ただし出力数を制限する
配列の内容を出力し、ただし出力数を制限する

リスト 11 は制限の設定を 2 にする場合の例を示しています。

リスト 11. 配列の内容の項目数を 2 に制限する
Toyota Corolla [Automatic Transmission, Power Brakes] 1993 (Automobile)

hashCode()equals() を使う

Eclipse Galileo の生成機能、hashCode()equals() は、フィールドの実際の値に基づいてオブジェクト同士を等しくするためのルールを作成したい場合に非常に便利です。これはデフォルトの equals() の動作とは異なります。デフォルトで同じ値を持つオブジェクト同士でさえ、等しいとは限らないからです。リスト 12 のコードを考えてみてください。

リスト 12. equals() メソッドのデフォルトの動作
public class Main {
    public static void main(String[] args) {
        Automobile auto = new Automobile("Toyota", "Corolla", "1993");
        String[] options = new String[] {
                "Automatic Transmission",
                "Power Brakes",
                "Power Windows"
        };
        auto.setOptions(options);
        
        Automobile auto2 = new Automobile("Toyota", "Corolla", "1993");
        String[] options2 = new String[] {
                "Automatic Transmission",
                "Power Brakes",
                "Power Windows"
        };
        auto2.setOptions(options2);
        
        System.out.println("Autos 1 and 2 are equal():  " + auto.equals(auto2));
        
    }
}

すべてのプロパティーは同じ値に設定されているにもかかわらず、このコードを実行すると「Auto 1 and 2 are equal(): false」という内容が出力されます。

この動作を変更するためには、「Source (ソース)」 > 「Generate hashCode() and equals() (hashCode() および equals() の生成)」の順にクリックし、すべてのフィールドを比較する新しいバージョンの equals() メソッドを生成します (リスト 13)。

リスト 13. 新しい equals() メソッドですべてのフィールドを比較する
    @Override
    public int hashCode() {
        // snipped...
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Automobile other = (Automobile) obj;
        if (make == null) {
            if (other.make != null)
                return false;
        } else if (!make.equals(other.make))
            return false;
        if (model == null) {
            if (other.model != null)
                return false;
        } else if (!model.equals(other.model))
            return false;
        if (!Arrays.equals(options, other.options))
            return false;
        if (year == null) {
            if (other.year != null)
                return false;
        } else if (!year.equals(other.year))
            return false;
        return true;
    }

これでこのコードを実行すると、オーバーライドされた equals() メソッドを使って 2 つのオブジェクトが比較され、この 2 つが等しいことがわかります。

Eclipse Galileo での、もう 1 つの新しい機能として、if 文のブロックを生成することができます。「Source (ソース)」 > 「Clean Up (クリーンアップ)」の順に選択することによって、1 行の if 文をブロックに変更する作業をまだ行っていない場合には、この新機能が便利です。通常のベスト・プラクティスとしては、1 行の if 文を避ける必要があると言われています。そのため大抵の人は、確実にそれを守ったコードを作成したいものです。

まとめ

Galileo には toString() メソッドを生成する新機能があり、これを利用することで大量の Java コードを生成する機能が既存の Eclipse の機能に追加されます。実際に使ってみることで、どのコードを型付けする必要があるのか、どのコードを生成できるのかを理解できるようになり、作業の量を減らせるようになります。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source
ArticleID=428114
ArticleTitle=Eclipse Galileo でJava コーディングを迅速に行う
publish-date=08182009