2004年02月10日 火曜日

Java 2 Platform, Standard Edition (J2SE) 1.5.0 Beta1

2月4日にSun MicrosystemsからJ2SE(Java 2 Platform, Standard Edition)の次期バージョンであるJ2SE 1.5.0 Beta1が公開された。JavaはまだJDK1.0のα版とかβ版とか言っていた頃の熱い時代に熱狂的に遊んでいたが、いろいろ熱が冷めるような事件があって、さらに諸般の理由があって_使わない/使えない言語_であった。いままでわりと保守的な更新を続けてきたJavaであるが、J2SE 1.5.0(コード名「Tiger」)では、Java2になったときと同じ程度、もしくはかつて例のない大きな改良が加えられることとなった。言語仕様に関わりそうなものは、ざっくり…

  • JSR-014: Add Generic Types To The Java Programming Language
    Generic Types
    C++のtemplateに相当する機能。Collectionを使う時に値を取り出すのに_キャストの嵐_だったが、これのおかげでソースが保守しやすくなって嬉しい機能だ。無用な機能が多いC++の中で個人的には非常に重要で便利な機能だと思うのだが、Javaに無くて困っていたんだねぇ。
  • JSR-201: Extending the Java Programming Language with Enumerations, Autoboxing, Enhanced for loops and Static Import
    Enumerations
    C/C++で言うところのenum型の追加。具体的な内容はEffective Javaの中に書かれているTypesafe-Enumと同じもので、定数を表すためのクラスを使って、各定数はそのオブジェクトにしてしまうというもの。自分で完璧なクラスを書くのは大変(できないか…)なので、言語仕様で提供してくれるのは嬉しいかも。
    Autoboxing/Unboxing
    PrimitiveとPrimitiveのwrapper class間の代入を=でできるようになる。(要は自動変換できるようになった。)
    Enhanced for loops
    for-eachのようなfor文が書けるようになる。Collectionを使う時にいちいちIteratorを使うのはめんどくさい。
    Static Import
    static な定数を import 文でインポートできるようになった。
    Variable length argument
    これでようやくprintfのような関数が書ける。(僕は書かないが…)
  • JSR-175: A Metadata Facility for the Java Programming Language
    と言うところ。これらの変更に伴ってざっくりライブラリが変わっているようだ。(まぁGenericなCollectionになっているはずだし…) まぁ待望の機能は付け加わったので、Javaで遊んで良いお年頃になりました。

Java Generics

と言うことで、早速Genericを試してみよう。J2SE 1.4ではCollection使う時にはこんな感じにしていた記憶がある。

// OldNumberList.java for JDK1.4
import java.util.Vector;
public class OldNumberList{
  public static void main(String args[]){
    int num=Integer.parseInt(args[0]);
    Vector vector=new Vector();
    for(int i=0;i<num;i++){
      vector.add(new Integer(i).toString());
    }
    for(int i=0;i<vector.size();i++){
      // Vectorの要素はObject型なので、キャストが必要!!!
      String text=(String)vector.get(i);
      System.out.println(text);
    }
  }
}

実行するにはバイトコンパイルしてVMで実行だから、
javac OldNumberList.java
java OldNumberList 12
でOK。画面に0から11まで表示される。(そういうプログラムなのね。) これをGenericsを使って書き換えみよう。

// NewNumberList.java for JDK1.5
import java.util.Vector;
public class NewNumberList{
  public static void main(String args[]){
    int num=Integer.parseInt(args[0]);
    // Collection生成時に<>で型を指定
    Vector<Integer> vector=new Vector<Integer>();
    for(int i=0;i<num;i++){
      // autoboxingのおかげでwrapper classを意識しなくて良い。
      vector.add(i);
    }
    for(int i=0;i<vector.size();i++){
      // ここでキャストは不要
      Integer number = vector.get(i);
      System.out.println(number);
    }
  }
}

こっちはJDK1.5での言語仕様拡張を有効にしてコンパイルなので
javac -source 1.5 NewNumberList.java
java NewNumberList 12
でOK。バイトコンパイルされた物の実行はJRE1.4とかでもできそう。(もう環境無いので試せません。) と言うことで、今までObject → Integer というキャストが必要だったようなところはすべて不要となった。ダウンキャストできるかどうかは実行時にしか分からないのでコンパイルでエラーが拾えるのはだいぶん嬉しい。試しに、

// OldNumberList.java for JDK1.4
import java.util.Vector;
public class OldNumberList{
  public static void main(String args[]){
    int num=Integer.parseInt(args[0]);
    Vector vector=new Vector();
    for(int i=0;i<num;i++){
      vector.add(new Integer(i)); // 整数の要素を追加
    }
    for(int i=0;i<vector.size();i++){
      // Vectorの要素はObject型なので、キャストが必要!!!
      String text=(String)vector.get(i); // 実行時にClassCastExceptionが発生する
      System.out.println(text);
    }
  }
}
のようなソースをコンパイル実行してみれば分かるような気がする。(No Errorでコンパイルが通って、Class Cast Exceptionが発生するでしょ。)
## 今日もダウン...
全く持ってだめだめな状態。今日、家に帰ってソファーに座った時点で、気を失っていました。風邪とかではないので、完全に気力がないだけなのかも。