>> EclipseによるJavaアプリケーションのデバッグへ
>> EclipseによるWebアプリケーションのデバッグへ
Eclipse3.1が2005/06/28についに正式リリースされました。Eclipse3.0.xではJ2SE5.0をサポートしていませんでしたが、この3.1はJ2SE5.0をフルサポートしています。またJ2SE5.0対応だけでなく、いろいろと改善がなされているようです。
まだ私自身あまり触っていませんが、Eclipseのマニュアルを見ながら"これは"と思った新機能を中心に、簡単に紹介していこうと思います。
個人的には以下の2つが目玉かなと思ってます。
J2SE5.0対応、パフォーマンスの改善以外にも様々な改善や機能追加がされているようです。ここではその中でも個人的にいいなと思ったものを紹介します。3.1の更新一覧はEclipse 3.1 - New and NoteworthyやEclipseのメニューからHelp>Welcomeで見ることができます。
現在開いているエディタやバッファに含まれている単語を補完する機能です。テキストエディタ上で補完したい単語の先頭何文字か入力して Alt + / とすると、残りの文字が補完されます。例えば、

ここで Alt + / とすると、

このように補完してくれます。この機能はすべてのテキストエディタで有効です。Javaソースを編集するためのJavaエディタはテキストエディタを継承しているので、Javaエディタにおいてもこの機能は使えます。
build.xmlを開き、antタスク名にカーソルを合わせて Shift + F2 とすると、選択したタスクのマニュアルが表示されます。例えば、

ここで Shift + F2とすると、

Eclipse内にブラウザが開かれます。尚、このマニュアルは Apache AntのWebサイトのコンテンツを取得したものですので、インターネットに接続可能な環境でなければ使えないと思います。
J2SE5.0で導入されたGenericsを使用していないコードをGenericsを使うようにリファクタリングすることができます。例えば以下のコードに対して、

右クリック>Refactor>Infer Generic Type Arguments...を選択してOKとすると、

List→List<String>, Iterator→Iterator<String>のようにGenericsを使ったコードにリファクタリングしてくれました。iter.next()で取得したオブジェクトのキャストも無くなっていますね。
J2SE5.0対応に伴って、拡張for文に対応したテンプレートforeachが追加されました。繰り返し処理をさせたい箇所でforeachと入力し、Ctrl + Spaceで表示される"foreach"を選択することにより、拡張for文のテンプレートが生成されます。


ちなみにテンプレートの名前はforeachですが、実際のコードはforキーワードが使われます。
Serializableインタフェースを直接または間接的に実装しているクラスのクラス名をエディタ上で選択し、Ctrl + 1 とすることで、Serial Version UIDを生成するためのHot fixが表示されます。ここでAdd generated serial version IDを選択すると、UIDが生成されます。(尚、Serializableを実装したクラスでUIDを宣言していないと、警告を出すようになりました。この辺りが気に入らなければ設定で警告を出さないようにもできます。


非推奨メソッドを呼び出しているコードがハイライト表示(取り消し線)されるようになり、非推奨メソッドを使っていることを判別しやすくなりました。尚、この設定も変更可能です。

Eclipse3.0.xまではインデントサイズ=タブ幅に設定されていました。そのためJDKのソースコードのように、インデントサイズ4,
タブ幅8といったソースコードを簡単に作ることは出来なかったわけですが、インデントサイズとタブ幅をそれぞれ独立に設定できるようになりました。これでSUNのCode
Conventionに従ったソースコードを作成することができます。
この設定はJava>Code Style>Formatter>Edit>Indentationタブで行います。
Emacs使いからみれば致命的?に思われていたこの機能が追加されました。対象のソースを開いている状態で、Window>New Windowで同じファイルを編集可能なウィンドウが一つ追加されます。あとは追加されたウィンドウを左右または上下にドラッグすれば同じソースのある箇所を見ながら別の箇所を修正するといったことができるようになります。

コードフォーマッタの設定項目が増えました。例えばEclipse3.0.xではメソッドの中身が空の場合に閉じ括弧(})を改行させないようにすることができませんでしたが(つまり、 void foo() {} とはできなかった)、3.1ではこれが設定できるようになっています。
Eclipse3.0.xではすべてのプロジェクトに対して設定していたこれらの項目をプロジェクト毎に設定できるようになりました。一部のプロジェクトはJ2SE5.0対応が必要だが、一方でJ2SE1.4のプロジェクトも存在するようなケースで、それぞれのプロジェクトを触る前にわざわざCompiler準拠レベルを変更する必要が無いということですね。コードフォーマッタもプロジェクト毎に設定できるので、プロジェクトによってコーディングガイドラインが異なるケースもOKです。
これは自分の覚書として・・・詳細はJ2SE 5.0 虎の穴で詳しく解説されているのでそちらを参考に。
C++のテンプレート機能のようなもの・・・らしい。C++はよく知らないが、とにかくListやMapといったコレクションライブラリからオブジェクトを取得する時の煩わしいキャストが不要になる。型を指定しているので間違った型を格納しようとした場合、コンパイラが警告してくれるという利点も大きい。
public class GenericsTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("hogehoge");
list.add("foo");
list.add("bar");
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
String item = iter.next();
System.out.println(item);
}
}
}
メソッドやクラスに付ける注釈のようなもの。何でこんなものを付けるかというと、人間にとって煩わしい作業をツールに肩代わりさせるためには、ツールに対して何か情報を与える必要があって、そのために付ける付加情報・・・だと思う。
つまり、Metadataだけでは意味がなく、それを解釈するツールがあって初めて役立つもの。特にEJB3.0において、このMetadataが重要な位置を占める模様(POJO関連)。他にもMetadataを利用するフレームワークも色々あるみたいなので、Eclipse3.1というJ2SE5.0対応エディタがリリースされたことによって更に浸透していくんでないかなと思います。
C#のforeachと使い方は同じだと思います。配列だろうがコレクションだろうが同じように扱えるんですね。とても便利。もうIteratorを使う日はなくなるのか・・・。
ちなみに下の例ではGenericsのおかげでList#toArrayの戻り値のキャストが不要になってます。これもいいですね。toArrayを使うと1行が長くなりがちなので、キャストが無くなったのは個人的にかなりうれしいです。
import java.util.ArrayList;
import java.util.List;
public class ExtendedForTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
list.add("hoge");
String[] array = list.toArray(new String[list.size()]);
for (String item : list) {
System.out.println(item);
}
for (String item : array) {
System.out.println(item);
}
}
}
今までは一つの定数ごとにstatic final int ... といったように宣言していたわけですが、それがTypesafe
Enumを使うことで簡単に宣言できるようになります。定数を区別するために意味のない0や1といった値を代入する必要もありません。
public class TypesafeEnumTest {
public enum Color {BLACK, WHITE, RED}
public static void main(String[] args) {
Color color = Color.BLACK;
switch (color) {
case BLACK:
System.out.println("黒");
break;
case WHITE:
System.out.println("白");
break;
case RED:
System.out.println("赤");
default:
break;
}
}
}
リストに整数を格納する時にIntegerを生成して格納し、取り出すときはその逆をする・・・そんな作業からついに解放されます。
public class AutoBoxingTest {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
numbers.add(i);
}
int total = 0;
for (int number : numbers) {
total += number;
}
System.out.println("total:" + total);
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "foo");
map.put(2, "bar");
String token = map.get(1);
System.out.println("token:" + token);
}
}