Tiger (Java2 SE 1.5) のJava 言語仕様の拡張

作成日:2003.5.10

Java 言語は、 SUN の配布する次の Java 2 Platform, Standard Edition 1.5 (以下、J2SE 1.5) から その言語仕様に大きな修正が加えられる予定だ。
その内容を SUN のエンジニア Dr. Joshua Bloch が 紹介するページが公開された (ここ)。

J2SE 1.5 で Java 言語仕様に追加される予定の機能は大きく6点。

  1. Generics
  2. Enhanced for loop
  3. Autoboxing/unboxing
  4. Typesafe enums
  5. Static import
  6. Metadata

ただし、仕様は決定ではないので、まだ変更される可能性がある。

1. Generics

すでに予告されたように C++ の template のような generic type が 言語仕様に追加される。

従来の JDK のライブラリでは、 java.util.Listjava.util.Map などのコンテナクラスは、 すべてのオブジェクトを基底クラス Object として取り扱ってきた。 つまり、 コンテナにはどんな種類のオブジェクトでも格納することが可能だった。

List words = new ArrayList();
words.add( word );
String title = ((String) words.get(i)).toUppercase();

しかし、 ユーザーは String クラスを収めるコンテナ、 自分の作成したクラス収めるコンテナのように、 特定の型に特化したコンテナを必要とすることの方が多い。 従来のコンテナクラスでは、 間違った型の要素を誤ってコンテナに挿入することを防ぐことができなかった。

Generic type を用いると 次のようにコンテナクラスを特化できる。

List<String> words = new ArrayList<String>();
words.add( word );
String title = words.get(i).toUppercase();

この機能を使うと、 特定クラス(この例では Stringクラス) に特化したコンテナが作成できる。

このコンテナへ要素を挿入・取り出す場合には コンパイラによる要素の型チェックが入る。 その結果、 コンテナクラスの意味が明確になり、 型チェックによって安全性が向上し、 実行時のエラーを減少させることができる。

Java の Generic type は C++ の template と違い、 特化したクラス毎の実体は生成しない。 Java のソースコードをコンパイルし終わると、 List<String> は従来の List コンテナに置換された バイトコードとなって出力される。

また、 J2SE1.5 の generic type は、 primitive 型へ特化(List<int> など) はできないようだ。

2. Enhanced for Loop

Java 言語では、 コレクションや配列の内容を全て列挙するために for 構文が利用される。

for (Iterator<Strin>; i = c.iterator(); i.hasNext(); ) {
  String s = i.next();
  // Body
}

このコレクションから要素を取り出すという動作をより明確にするために、 Perl や C# 言語は foreach 構文を持っている。 J2SE 1.5 から、 forforeach のような機能を実現する 構文が追加された。

上の Java プログラムを 新しい構文で書き直すと以下のようになる。

for (String s : c ) {
  // Body
}

generic type のコンテナだけでなく、 従来のコレクションクラスや配列型も、 この新しい構文を使うことが可能だ。

配列の場合は、

int sum = 0;
for( int i=0 ; i<a.length ; i++ ){
  int e = a[i];
  sum += e;
}

上の表現を下のように書き改めることができる。

int sum = 0;
for( int e : a ){
  sum += e;
}

また enum型の仕様が拡張されたのと合わせて、 以下のような表現も可能になった。

enum Day {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };

for (Day d : Day.VALUES){
  // Body ...
}

3. Autoboxing / unboxing

boxing と unboxing が使えるようになった。

ブラボー!!

従来の Java 言語では、 primitive 型の変数をオブジェクトとして扱いたい場合には、 ラッパークラスのインスタンスへ変換を行う必要があった。 例えば、int 型 のラッパークラスは java.lang.Integer クラスである。 int 型を Integer クラスに変換し、 そこから逆変換するためには以下のようなコードを 必要とした。

int     i1 = ... ;
Integer I1 = new Integer( i1 );
int     i2 = I1.intValue();

これと等価な処理が

Integer I1 = (Integer) i1;
int     i2 = (int) I1;

と書けるようになった これは完全に C# の影響だと思われる。

4. Typesafe Enums

enum 型が大幅に拡張された。 かいつまんで紹介する。

5. Static Import

あるクラスの名前空間に、 他のクラスやインターフェイスの static なメソッドやフィールドを 取り込めるようにする static import 機能が追加された。

Java は C/C++ のようなマクロが使えないため、 定数の集合をインクルードした場合、 以下のようなテクニックを使うようになっていた。

public interface Physics {
  public static final double AVOGADROS_NUMBER   = 6.02214199e23;
  public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
  public static final double ELECTRON_MASS      = 9.10938188e-31;
}

public class Guacamole implements Physics {
    public static void main(String[] args) {
        double moles = ...;
        double molecules = AVOGADROS_NUMBER * moles;
        ...
    }
}

この implements は概念的には、インターフェイスを継承したのではなく、 Guacamole クラスの名前空間の中に定数集合を取り込むためのものである。 interface の本来の概念からは外れていて好ましくない。

新たに定義された static import を使うと、 以下のように書けるようになる。

import static org.iso.Physics.*;

class Guacamole {
    public static void main(String[] args) {
        double molecules = AVOGADROS_NUMBER * moles;
        ...
    }
}

また、Math クラスを static import すると、 Math.abs(x)、Math.sqrt(x) と書いていたコードが abs(x)、sqrt(x) と 書けるようになる。

6. Metadata

ドラフトが公開されていないため概念が掴めないが、 ツール類が Java のソースコードをうまく扱えるようにするための 機構のようだ。

例えば、metadata を埋め込まれた以下のようなソースがある場合、

import javax.xml.rpc.*;

public class CoffeeOrder { 
  @Remote public Coffee [] getPriceList() {
      ...
  }
  @Remote public String orderCoffee(String name, int quantity) {
      ...
  }
}

これをツールが解釈して、 以下のようなコードを生成できるように することを狙ったている(らしい)。

public interface CoffeeOrderIF extends java.rmi.Remote { 
    public Coffee [] getPriceList()
        throws java.rmi.RemoteException; 
    public String orderCoffee(String name, int quantity)
        throws java.rmi.RemoteException; 
} 

public class CoffeeOrderImpl implements CoffeeOrderIF { 
    public Coffee [] getPriceList() {
        ...
    } 
    public String orderCoffee(String name, int quantity) {
        ...
   }
}

コメント

コメントを書き込む

TOP    掲示板    戻る
Written by NAKAMURA Minoru, Email: nminoru atmark nminoru dot jp, Twitter:@nminoru_jp