Javaの新バージョン「J2SE5.0 Tiger」の新機能のメモ。詳しい使い方などは、参考文献や他のサイトをご覧ください。

J2SE5.0 Tiger では、言語構文が大幅に追加されています。GenericsオートボクシングEnum(列挙型)可変長引数アノテーション拡張for ステートメントStatic インポートなど、目を見張る機能がたくさん付け加わっています。

J2SE5.0 Tiger は、EoD (Easy Of Development) を行うための道具です。今後はさらに普及してきて、J2SE1.4 に確実に置き換わると思います。今のうちに概要や変わったところをチェックしておくのがいいと思います。

参考

覚書き一覧

  1. 基本クラス、コレクションクラスの変更点
  2. Generics - ジェネリクス
  3. Enum - 列挙型
  4. ボクシング、アンボクシング
  5. 可変長引数
  6. アノテーション
  7. 拡張 for ステートメント

基本クラス、コレクションクラスの変更点

java.util.Arrays の変更

java.util.Arraysクラスに toString() が付け加わりました。配列をプリントできるようになります。デバッグ時に楽になります。deepToString() は2次元配列以上の配列の中身を再帰的にプリントします。

java.util.Queue インターフェース

java.util.Queueインターフェースが追加されました。キューは FIFO (先入れ、先出し)の性質を持ち、先に挿入した値が最初に取得できるコレクションです。キューでは、offer() と poll()、element()、peek() を利用します。

要素がない場合の挙動に注意
キューのコレクションメソッドである add() や remove() は要素がない場合の挙動が例外をスローするようになっています。

java.util.Queue はインターフェースで、実装クラスは LinkedList や他のList 実装が使えます。

Queue q = new LinkedList();

戻り型のオーバーライド

J2SE5.0 Tiger から戻り型がオーバーライドできるようになりました。今までは、メソッドのオーバーライドはメソッドの戻り型を含めてシグネチャが一致しなければなりませんでしたが、それが変更されています。

[参考]

Unicode4.0 のサポート

Unicode4.0 をサポートするようになりました。これにより、Unicode が16ビットに収まらなくなり、charで表現できない文字が存在することになります。この場合 int を使うことになります。

Unicode4.0 のサポートにより、16bit に収まらない文字を扱うには、char ではなく、int を使います。

StringBuilder クラスを使う

StringBuilder クラスが追加されました。これは StringBuffer の非同期クラスの位置づけになっています。コレクションフレームワークにより、Vector よりも ArrayList を、HashTable より HashMap を使うのが好まれるように、StringBuffer よりも StringBuilder を使うようになります。ただし、非同期処理の場合に限ります。

非同期処理ですむ場合は、StringBuffer の代わりに StringBuilder を使うようにします。

Generics - ジェネリクス

Generics 構文

Generics は C++ 言語のテンプレートと同じ役割をします。主にコレクションを使うときに、型の安全性を保証するのに使います。また、Iterator を使う場合にキャストが不要になるという利点もあります。

List<String> list = new ArrayList<String>();

オートボクシング という機能が J2SE5.0 Tiger から追加されました。これはプリミティブ型とオブジェクト型の変換をコンパイル時に解決してくれると言う機能です。この機能を使うと、Generics を使ってプリミティブ型をコレクションに追加することができるようになっています。その場合、下記のようにします。

List<Integer> list = new ArrayList<Integer>(); 
list.add(8); 
list.add(5); 

型パラメータとして指定できるのは Object型 だけですので注意が必要です。プリミティブ型は指定できません。

java.util.Map は型パラメータを二つとります。 key に指定する型と value に指定する型です。

Iterator の型パラメータに関して

Iterator とコレクションは常にペアで考える必要があります。コレクションに型パラメータが指定されていれば、Iterator にも同じ型パラメータを指定する必要があります。

List<Integer> list = new ArrayList<Integer>(); 
list.add(8); 
list.add(5); 
 
Iterator<Integer> iter = list.iterator(); 
while (iter.hasNext()) { 
    int n = iter.next(); 
} 

J2SE5.0 Tiger を使って開発を行う場合、できる限り Generics を使って、型の安全性を確保するのがよい作法です。

ワイルドカードを使用する

型パラメータには ワイルドカード (?) を使うことができる。これを指定すると、どんな型でも受け入れるという事を示すことになる。ただし、ワイルドカードを使った場合、そのコレクションは読み取り専用になる。つまり、 add()、addAll()、set() などのメソッド呼び出しはコンパイルエラーになる。

List<?> list = new ArrayList<String>(); 
 
/* ワイルドカードを使っているので、読み取り専用になっている */
//list.add("Hey"); 
//list.add("Good"); 
//list.add("Hello"); 
 
for (Iterator<?> iter = list.iterator(); iter.hasNext(); ) { 
System.out.println(iter.next()); 
} 
 

Enum - 列挙型

Enum (列挙型) は、型のチェックが行われる、定数の範囲とでも考えればいいと思います。

Category.java

 
package com.hamasyou; 
 
public enum Category {  
    BOOK,  
    WEB,  
    COMPUTER,  
    SYSTEM 
}; 

慣習では Enum クラス名は 単語の区切りが大文字、列挙の識別子はすべて大文字とされています。

列挙型は == や equals() で比較できます。また、compareTo() を使って比較することができます。デフォルトの順序は、識別子の順番になります。

toString() と valueOf() メソッドが提供されます。

(例: Category.SYSTEM.toString().equals("SYSTEM") )
(例: Category.BOOK == Category.valueOf("BOOK"))
※ toString() をオーバーライドする場合は、 valueOf もオーバーライドしなければならない。常にペアで修正すること。

J2SE5.0 Tiger から、列挙型による switch 文の分岐ができるようになりました。switch 文ではラベルに識別子を使う場合、enum クラス名を付けるとコンパイルエラーになります。

Category c = Category.BOOK; 
switch (c) { 
    case Category.SYSTEM:    // コンパイルエラー 
        System.out.println("BOKE"); 
        break; 
    case WEB: 
        System.out.println("BOKE"); 
        break; 
    case BOOK: 
        System.out.println("OK"); 
        break;                 
} 

[参考]

ボクシング、アンボクシング

プリミティブ型からオブジェクトラッパー型へ、オブジェクトラッパー型からプリミティブ型への変換を、コンパイル時に行ってくれる機能がオートボクシング、アンボクシング です。

Integer obj = 10; 
int n = new Integer(8); 
obj++; 

上のような事ができます。例えばメソッドの引数で、int をとる場合でも、Integer インスタンスを渡すことができるようになります。

プリミティブへの null の代入に注意

オブジェクトラッパー型のインスタンスには null が指定できました。しかし、アンボクシング時に null インスタンスであると、NullPointerException が発生します。

Integer nullObj = null; 
int n = nullObj;    // NullPointerException 

可変長引数

可変長引数の機能により、同じ型の可変の引数を取ることができます。引数の数をコンパイル時または実行時に決定することができます。可変長引数は省略記号(…)を使います。

public Constructor(String name, String... args)

可変長引数は、1メソッドにつき、1つの省略記号しか使えない。また、省略記号は最後の引数として指定しなければならない。

可変長引数には、引数を0個以上指定できる。引数に何も指定しないことも可能です。

可変長引数は、メソッドの中では配列のように使用できる。引数を指定せずに呼び出すことも可能なので、プログラマはこのことを念頭に入れてメソッドを実装しなければなりません。

アノテーション

アノテーションとは

アノテーションとは、実行可能なコードではなく、コードを説明する付加情報のことです。ツールによって分析・解析される情報になります。J2SE5.0 Tiger で採択されたアノテーションは、明確に定義されたメタデータを使って、コードを補足するものと考えられます。

アノテーションは、コンパイラによってチェックされます。アノテーションの綴りが間違っている場合にはコンパイルエラーになります。アノテーションは、意図していることを表すための重要なものなので、使用することをお勧めします

標準アノテーション

@Override

このメソッドが、スーパークラスのメソッドをオーバーライドすることを示します。

public String toString() { 
... 
} 
@Deprecated

このメソッドまたは要素の使用が廃止されたことを示します。このアノテーションは、メソッド宣言と同じ行に宣言します。

@Deprecated public void hoge() { 
... 
} 
@SuppressWarnings

初期化子に対するコンパイラの警告を無効にすることを示します。

@SuppressWarnings("unchecked") 
public void warnMethod() { 
... 
} 

[参考]

メタアノテーション

メタアノテーション、つまりアノテーションのアノテーションには4つの標準のものが用意されています。

@Target

アノテーションを定義できるプログラム要素を指定する。

  • ElementType.TYPE
  • ElementType.FIELD
  • ElementType.METHOD
  • ElementType.PARAMETER
  • ElementType.CONSTRUCTOR
  • ElementType.LOCAL_VARIABLE
  • ElementType.ANNOTATION_TYPE
  • ElementType.PACKAGE
@Retention

アノテーションの定義をどこまで残すかを指定する。コンパイル時に無視することもできるし、クラスファイルに埋め込むこともできる。

@Documented

アノテーションをJavaDocに表示するかどうかを指定する。第三者が書いたコードのトラブルシューティング、アップデート情報、管理を行うための情報を記載するときに使う。

@Inherited

アノテーションを継承先のクラスにも反映させるかどうかを指定する。

拡張 for ステートメント

for (Object element : list) { 
    element.toString(); 
}

この拡張 for ステートメントにより、java.util.Iterator を使う機会がグッと減る。for 文に使えるクラスは、java.lang.Iterable インターフェースを実装している配列またはオブジェクト出なければならない

拡張 for ステートメントでできないことに、「現在の要素位置を特定すること。」、「ループ中で要素を削除する。」、「二つ以上の配列を同一インデックスでアクセスする。」などがあります。

参考

  • J2SEの易しい解説を求める人へ。