レベル: 中級 Nathan A. Good, Senior Information Engineer, Freelance Developer
2009年 8月 18日 Eclipse Galileo での新しいコード生成機能、toString() の使い方を学びましょう。また、hashCode()、equals()、セッター/ゲッターの生成機能の使い方も学び、Java™ クラスの基本部分を作成するのに必要な作業量を削減しましょう。
コード生成のヒントを紹介するこの記事では、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 (コード・テンプレート)」の順に選択する
 |
ベスト・プラクティスをコード化する
私はいくつかのプロジェクトのテクニカル・リーダーとして、それらのプロジェクトで使用するためのベスト・プラクティスをいくつか特定しました。私はそれらのベスト・プラクティスを Java コード・テンプレートの中に入れ、チームのメンバーがインポートできるようにしてあります。
|
|
「Preferences (設定)」ウィンドウで「Java」 > 「Editor (エディター)」 > 「Templates (テンプレート)」の順に選択すると、名前順にテンプレートのリストが表示されます (図 2)。Eclipse に同梱されているテンプレートを探します。独自のテンプレートを追加することもでき、さらにはテンプレートをインポートすることもできます。
図 2. 「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
Galileo が登場する前は、toString() メソッドは手動でコーディングしなければなりませんでした。この例のように簡単なクラスの場合にはそれほど大変ではありませんが、もっと多くのフィールドがあるクラスの場合には、作成に長い時間がかかります。また、単純に値を連結する以上のことをしなければならない場合や、ヌルをチェックしたい場合、さらには StringBuilder を使ってパフォーマンスを高めたい場合があるかもしれません。しかし Galileo では、そうしたことをすべて、「Source (ソース)」 > 「Generate toString() (toString() の生成)」の順に選択することで実現できるのです (図 3)。
図 3. 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() の生成)」の順に再度クリックします。そして今度は、
- 「String format (文字列の書式)」ドロップダウン・リストの隣にある「Edit (編集)」をクリックします。
- 表示された画面で「New (新規)」をクリックします。
図 4. 新しいフォーマットを追加する
- 「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 の機能に追加されます。実際に使ってみることで、どのコードを型付けする必要があるのか、どのコードを生成できるのかを理解できるようになり、作業の量を減らせるようになります。
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | 
|  | Nathan A. Good はミネソタ州の Twin Cities エリアに住んでいます。彼はプロとしてソフトウェア開発やソフトウェア・アーキテクチャー、システム管理などを行っています。彼はソフトウェアを書いている時以外は、PC やサーバーを構築したり、新しい技術について資料を読んだり、そうした技術に取り組んだり、彼の友人達をオープソース・ソフトウェアに移行させようとしたりしています。彼は数多くの本や記事を執筆、あるいは共同で執筆しており、その中には『Professional Red Hat Enterprise Linux 3』や『Regular Expression Recipes: A Problem-Solution Approach』、『Foundations of PEAR: Rapid PHP Development』などがあります。 |
記事の評価
|