Java 1.5 新機能! その1

更新日: 2004年 5月 22日(土)

Java 1.5 β

つい、先日( 2月6日)に Java の 1.5βが登場しました。そろそろ、Javaも仕様を固めないといけなさそうな感じがしますが、まだ追加したりなかったようですね・・・。では、新しい言語仕様を早速試してみます。

と、その前に Java 1.5 の最新の情報のリンクは下の通りです。

Java 2 Platform, Standard Edition v 1.5.0 概要
http://java.sun.com/j2se/1.5.0/ja/

ダウンロードのところで Java 1.5 SDK をダウンロードも出来ます。

インストールの方法は、ダウンロードしたexe ファイルを展開して、PATH を通せばOKです。1.5になって変わったといえば、デフォルトのインストール先が C:\ のルートから "C:\Program Files" に移動したってことですかね。

環境設定の例)

PATH %PATH%;"C:\Program Files\Java\j2sdk1.5.0\bin"

javac コマンドを打ち込む前に1度だけ入力すればOkです。ただし、開発環境で本当に 1.4 を使っている方はそのPCに1.5は入れない方がよろしいかと思います(^^ゞ

新しい言語仕様

Java 1.5 の目玉(と、勝手に思いこんでる)の Java 版 テンプレートクラスのGenericsでしょうか。このテンプレートクラスで、C++ の Standard Template Class ( 以下 STL と略す)  に近い Collection クラスが利用できるようになります。

たとえば、1.4以前 までは、List#add(); で、追加する要素の型は、 Object を派生したクラスなら何でもOKでした。 確かに型に捕らわれず、リストに追加していけるので便利ですが、String だけのリストというのを作っても、意図的に Integer などを入れてもコンパイルエラーしないし、get() での戻り値も好きなクラスにキャスト出来たりと、型がとても曖昧でした。

今度からは新しく追加された Generics を使用するとその型の曖昧さを厳密なものに変えることが出来ます。ただ、親が異なる複数の種類のクラスをリストに追加する場合は、今まで通り テンプレートクラスを使わないようにするか、リストの中身をまとめられるように共通のインタフェースを継承させる必要はあります。

では、実際コードを見てみましょう。1.5の新言語機能を使用したコレクションフレームワークのサンプルを下に示します。

import java.util.*;

public class Foo 
{
public static void main(String[] args) {
	// String のリストを生成する。
	List<String> stringList = new LinkedList<String>();
	
	stringList.add("テンプレートクラスって");
	stringList.add("オブジェクト指向じゃないんだよ♪");
	// stringList.add( new Integer(100);  // コンパイルエラー

	for( String i : stringList ) {		// 新しい for 文
		System.out.println(i);
	}
}

List<String> の<> の中にはクラスを入れます。ここでは String  と指定します。ここで、String を指定すると他のクラスで add しようとした時にコンパイルエラーになります。この"<>"のクラス宣言も気になりますよね? クラス宣言は次の通りなります。(見やすいように使っているメソッドの宣言しか書いてません)

interface List<E> {
 void add(E obj);
 E get(int i);
} 

interfaceの宣言の List の隣に <E> があります。 <E> には参照クラスが入り、プリミティブ型は入れてはいけないようです。

上のサンプルコードではEに String を指定したため、add の引数 E は "String" になります。その結果、引数に Integer を入れようとしてコンパイルエラーとなります。

要するに今まで Object クラスだったところを限定したクラスだけ使用可能にするように制限することが出来ます。また、E は適当な参照クラスとして、

class TemplateList<E> {
  E i_e:
}

と、フィールドに宣言することも可能です。構文チェックより前に E の部分が <> の中で指定したクラスに置き換わってコンパイルされたクラスになるような感じになります。

あと、テンプレートクラスを使ってコンパイルする時は、javac のオプションに -source 1.5 をつけます。(下の図の">" はプロンプトの表示のつもりなので、一緒にコピペしないでください(^^ゞ)

 > javac -source 1.5 Foo.java

それと、for 文も変わってますよね?? perl, C# で foreach というコレクションや配列を単純に読み込ませるループ文の一種なのですが、Java では for で出来るようになりました。

for( 一時的なコレクションの中の要素の変数 : コレクションクラス )

と、いう感じでコレクションの中を最初から最後まで走査して、i に次々に入れていってくれます。要するに Iterator を使用せずに 中身を取り出すことが出来ます。

C++ のテンプレートクラスの違いは?

Java の Generics は、コレクションフレームワークで"型"を特定出来るようにするもので、C++のテンプレートクラスとは毛色が違う感じですね。

まだ、C++ が有利だと思う点は、

逆に Java の方が頭がよいなぁと思う点は

まとめ

タイトル通り "Java 1.5 新機能! その1" のその1です。 Java 1.5 にはもっと追加された部分があるので、それを次回(予定?)。