minimize

事業拡大のため、新しい仲間を募集しています。
→詳しくはこちら

J2SE 5.0

J2SEの次期リリース版である5.0。
今までのようなマイナーバージョンアップではなく、大幅な言語仕様修正が入りました。
なんたって(1.5ではなく)5.0ですから。
以下、その主な内容です。

Generics

これが、一番大きな修正点でしょう。
簡単に言うと、コレクションの「型」を指定できるようになりました。
以下のようなロジックがあったとします。

List list = new ArrayList();
list.add("abc");
list.add("def");
for (Iterator it = list.iterator() ; it.hasNext()) {
    String s = (String)it.next();
    System.out.println(s);
}

これが Generics を適用すると以下のようになります。

List<String> list = new ArrayList<String>();
list.add("abc");
list.add("def");
for (Iterator<String> it = list.iterator() ; it.hasNext()) {
	  String s = it.next();
	  System.out.println(s);
}

ListやIteratorの後に <String> という記述があります。
これにより、Listに格納するオブジェクトの型を決定できるという訳です。
addメソッドに渡すパラメータは String クラスのインスタンスである必要があります。
Iteratorから値を取り出すときも、面倒なキャストが必要ありません。

C++を知ってる人ならば誰もが判ることですが、
この機能はまさにC++の「テンプレート」そのものです。
テンプレートは高機能ですが、使い方によっては
かなりの可読性が失われる危険性もあります。
使いどころには注意する必要がありそうです。

Enhanced for loop

上の例は、この Enhanced for loop を適用するとさらに簡単にすることが出来ます。
for文の部分を以下のように記述できます。

for (String s : list) {
    System.out.println(s);
}

うーん、便利ですね。ただ、個人的にコロン(:)はどうかと思いますが…

Autoboxing/unboxing

まずは以下のコードを見て下さい。

public static void main(String args[]) {
  Map<String, Integer> m = new TreeMap<String, Integer>();
  for (String word : args)
      m.put(word, m.get(word) + 1);
  System.out.println(m);
}

これは、パラメータargsに指定した英文から
使われた単語の種類と頻度を計測するプログラムです。
注目すべきは、

m.get(word) + 1

という部分です。これは本来なら、

Integer freq = m.get(word);
if (freq == null) {
    m.put(word, new Integer(1));
} else {
    m.put(word, new Integer(freq.intValue() + 1));
}

と記述していたはずです。
先の一文はこれと同等の動きをします。

Typesafe enums

C++ではお馴染みの enum が使えるようになりました。
これは、定数を列挙した型のことで、以下のように使います。

public enum Coin {
    penny, nickel, dime, quarter;
}
...
return Coin.penny;

enum内で定義された変数は全てpublic staticとなります。

Static import

定数クラス(インターフェイス)の扱い方が明確になりました。
以前のJavaでは、

public interface Physics {
    int OK = 0;
    int NG = 1;
}
public class Guacamole implements Physics {
    ..
    int i = OK;
}

のように定数をインターフェイスで宣言して、
定数を使用するクラスでこのインターフェイスを実装するという形が多く取られていました。
しかし、この使い方は antipattern とされているように使用するのは好ましくありません。
インターフェイスとは本来、一連の動作(メソッド)を抽象化するために用いるもので
定数のみを宣言したものをインターフェイスとして使うのは良くないことなのでしょう。

そこで、Static import を適用すると以下のように書けます。

import static org.iso.Physics.*;
...
int i = OK;

import宣言の後に static というキーワードが付いています。
これにより、Physicsインターフェイスで宣言されている定数をimportすることが出来ます。
ちなみに、この場合Physicsはクラスとして宣言する方が良いとされています。

public final class Physics {
    public static final int OK = 0;
    public static final int NG = 1;
}