【コラム】

Java API、使ってますか?

15 アノテーションをさらに広い範囲で利用可能にするJSR 308

15/60

JSR 308: Annotations on Java Types

J2SE 5.0から導入されたアノテーション(JSR 175: A Metadata Facility for the Java Programming Language)はJavaによるプログラミングスタイルを大きく変化させ、とくにJava EEアプリケーション開発の分野ではすでに不可欠なものになりつつある。その後も「JSR 250: Common Annotations for the Java Platform」などによって利用できるアノテーションの種類が充実してきたほか、「JSR 269: Pluggable Annotation Processing API」のJava SE 6への導入によってアノテーションの処理を比較的容易に行えるようになった。

Java SE 7ではそのアノテーションの機能をさらに拡張する「JSR 308: Annotations on Java Types」の導入が検討されている。現在のアノテーションはクラス、メソッド、フィールドそして変数の宣言に対して指定することができる。JSR 308はその範囲をさらに拡大し、配列やメソッドレシーバ、ジェネリックの型引数などにも指定できるようにする。

JSR 308の仕様は現在議論されている最中だが、最新のProposalがこのページで公開されている。それによれば、JSR 308ではとくに型に対するアノテーションの適用を可能にすることが主題となっており、その他の検討事項としてはローカル変数や配列、文に対する適用が挙げられている。一方、式やブロック、ループ、部分構造などに対しては適用しないという。

また、ProposalではJSR 308を適用できる場面としてリスト1に示すような例が挙げられている。

リスト1 JSR 308によるアノテーションの適用例

// ジェネリックにおける型引数
Map<@NonNull String, @NonEmpty List<@Readonly Document>> files;

// ジェネリックにおけるメソッドやコンストラクタ呼び出しの引数
o.<@NonNull String>m("...");

// 型引数の境界指定
class Folder { ... }
Collection

// クラスの継承
class UnmodifiableList implements @Readonly List<@Readonly T> { ... }

// 例外指定
void monitorTemperature() throws @Critical TemperatureException { ... }

// 型キャスト
myString = (@NonNull String) myObject;

// instanceofによる型チェック
boolean isNonNull = myString instanceof @NonNull String;

// オブジェクト生成
new @NonEmpty @Readonly List(myNonEmptyStringSet)
new  @Interned MyObject()

// メソッドレシーバ
public int size() @Readonly { ... }
public void write() @Writable throws IOException { ... }

// クラスリテラル
Class<@NonNull String> c = @NonNull String.class;

// 配列
Document[@Readonly][] docs4 = new Document[@Readonly 2][12];
Document[][@Readonly] docs5 = new Document[2][@Readonly 12];

たとえば最初のジェネリックスの例ならば、mapに格納するデータは空でないList、キーはnull以外でなければならないことを示している。また、Listの中身は読込専用のDocumentでなければならない。ただし、ここで使われている@NonNullや@NonEmptyなどのアノテーションは架空のもので、実際にこのようなアノテーションがJava SEに用意されるということではない。

JSR 308対応のコンパイラを試す

JSR 308に対応したコンパイラは、開発版をここよりダウンロードすることができる。これはOpenJDKプロジェクトによって公開されているコンパイラを、JSR 308仕様に合わせて改変したものだ。

ファイル「jsr308-compiler.zip」をダウンロードして適当な場所で展開すると、中にはcompilerディレクトリ(以下、これを[COMPILER_DIR]と表記)が納められている。ビルドするにはApache Antを用いてプロンプト1のようにコマンドを実行する。

プロンプト1 JSR 308用コンパイラのビルド

> cd [COMPILER_DIR]
> ant build

あるいは、NetBeansプロジェクト形式になっているのでNetBeansを用いてビルドしてもよい。ビルドに成功するとdistディレクトリにbinとlibという2つのディレクトリが生成される。libディレクトリにはコンパイラの本体となるjavac.jarが、binディレクトリにはjavac.jarを"java"コマンドとして使用するためのjava.shが配置される。

なお、jsr308-compiler.zipはコンパイラのみなので新しいアノテーションは含まれていない。現在のところ、同じサイトで公開されている「Type-checking Plug-ins(jsr308-checkers.zip)」によってテスト用の@NonNullアノテーションのみ利用可能となっている。@NonNullは、型変数に対してnullの代入を許容しないようにするアノテーションである。Type-checking Plug-insはJSR 308のコンパイラをテストするためのプログラム群で、@NonNullアノテーションはそのサンプルとして公開されているのだが、今後使用できるアノテーションの種類を増やしていくとのことである。

jsr308-checkers.zipを適当な場所で展開すると、中にはcheckersディレクトリ(以下、これを[CHECKERS_DIR]と表記)が納められている。ビルドするにはApache Antを用いてプロンプト2のようにコマンドを実行する。

プロンプト2 Type-checking Plug-insのビルド

> cd [CHECKERS_DIR]
> ant dist

ビルドに成功するとcheckers.jarというファイルが生成される。このJARファイルに、@NonNullアノテーションを処理するためのアノテーションプロセッサが含まれている。

続いて、@NonNullアノテーションを用いたプログラムの例をリスト2に示す。ここでは文字列strおよびジェネリックスを用いたMapの型引数に@NonNullを指定している。

リスト2 @NonNullアノテーションを使用したプログラム例

import checkers.quals.NonNull;
import java.util.HashMap;
import java.util.Map;

class NonNullTest {
    public static void main(String[] args) {
        @NonNull String str = "Hello";

        Map<@NonNull String, String> map = new HashMap<@NonNull String, String>();
        map.put(str, "World");
    }
}

このプログラムをコンパイルするわけだが、JSR 308のコンパイラには新たに-typeprocessorというオプションが追加されている。これは-processorオプションに似たもので、JSR 308のアノテーション処理を行うプロセッサを指定するために使用する。たとえばリスト2のコンパイルはプロンプト3のように行う。現時点でJSR 308対応のコンパイラ自体がjavac.jarとして提供されているため、javaコマンドでjavac.jarを実行する形式となっている。シェルが利用可能な環境では、コンパイラのbinディレクトリにあるjava.shを用いればこれを疑似的にjavaコマンドとして実行できるようになる。

プロンプト3 -typeprocessorオプションを指定してコンパイル

> java -jar javac.jar -classpath [CHECKERS_JAR_PATH] -typeprocessor checkers.nonnull.NonnullChecker NonNullTest.java

リスト2は正常にコンパイルできるが、これをリスト3やリスト4のように、@NonNullを指定した部分にnullを代入しようとすると、アノテーションを処理する際にエラーが発生するようになる(ただし、現時点ではType-checking Plug-insのバグにより通常のエラーではなく例外は発生してしまう)。

リスト3 @NonNullによってエラーが発生するケース

        @NonNull String str = null;

リスト4 @NonNullによってエラーが発生するケース その2

        String str = null;
        Map<@NonNull String, String> map = new HashMap<@NonNull String, String>();
        map.put(str, "World");

JSR 308のproposalは日々の議論に応じて逐次更新されており、コンパイラもそれに対応する形で修正されている。前述したようにType-checking Plug-insにも今後テストできるアノテーションが追加される予定である。また、興味のある人は自分でJSR 308に対応したアノテーションを自作してみるのもいいだろう。その際には@NonNullの実装が参考になるはずだ。

15/60

インデックス

連載目次
第60回 どうなる? 今後のJavaプラットフォーム(Java SE編)
第59回 どうなる? 今後のJavaプラットフォーム(Java EE編)
第58回 Java SE 7の要注目機能"クロージャ"はどうなるのか その6
第57回 Java SE 7の要注目機能"クロージャ"はどうなるのか その5
第56回 Java SE 7の要注目機能"クロージャ"はどうなるのか その4
第55回 Java SE 7の要注目機能"クロージャ"はどうなるのか その3
第54回 Java SE 7の要注目機能"クロージャ"はどうなるのか その2
第53回 Java SE 7の要注目機能"クロージャ"はどうなるのか
第52回 Early Draftが公開されたJSF 2.0
第51回 EJBから独立したJava Persistence 2.0
第50回 モバイルJavaの新しい潮流となるか - MSA 2.0のドラフト公開
第49回 やっぱり基本はServlet - Servlet 3.0のEarly Draftを読む
第48回 JOGLで3Dプログラミング その4
第47回 JOGLで3Dプログラミング その3
第46回 JOGLで3Dプログラミング その2
第45回 JOGLで3Dプログラミング
第44回 JARファイルを効率的にネットワーク転送するためのPack200形式
第43回 Early Draftで把握するEJB 3.1の新機能
第42回 次世代の携帯端末向けJava仕様"MIDP 3.0"はどうなるか その2
第41回 次世代の携帯端末向けJava仕様"MIDP 3.0"はどうなるか その1
第40回 リソースアダプタによる接続の仕組み
第39回 JCAを利用したシステム間接続
第38回 Java EEと外部システムの接続性を支えるJCAがバージョンアップ
第37回 Javaのモジュラリティ強化を担う"スーパーパッケージ"とは
第36回 JSR 308対応のコンパイラを試す
第35回 公開されたJSR 308のEarly Draftを検証する
第34回 スクリプト言語とJavaを結びつけるJSR 223
第33回 Java EE環境に統一されたコンポーネントモデルを提供するJSR 299 その2
第32回 Java EE環境に統一されたコンポーネントモデルを提供するJSR 299 その1
第31回 Javaの文法がそのまま使えるスクリプト言語"BeanShell"
第30回 Javaアプリケーションにオブジェクトのキャッシュ機構を提供するJCache API
第29回 Javaアプリケーションからのリソース管理を可能にするJSR 284
第28回 XMLデータソースへの問い合わせはJSR 225で
第27回 Portlet Specification 2.0をもっと手軽に利用する
第26回 次期Javaポートレット仕様となるJSR 286
第25回 JSFとポートレットをつなげるJSR 301
第24回 Webサービス向けのポートレット仕様「WSRP」
第23回 高い相互運用性を実現するポートレットAPI - JSR 168
第22回 Java EE環境でタスクのスケジューリングを可能にするJSR 236
第21回 Java EE環境でのスレッドプログラミングを可能にするJSR 237
第20回 音声認識/合成のためのAPI - Java Speech APIとJSR 113
第19回 JSR 291でJavaプラットフォームにダイナミックコンポーネントモデルを導入
第18回 JAX-RSで簡単RESTful - JSR 311
第17回 待望のServlet 3.0がJSRに登場 - JSR 315
第16回 アノテーションを使ってバグ退治 - JSR 305
第15回 アノテーションをさらに広い範囲で利用可能にするJSR 308
第14回 Webアプリケーション開発の要となるか - JSF 2.0がJSRに登場
第13回 Webサービス経由でのJMX Agentへの接続を可能にするJSR 262
第12回 Javaアプリケーションのモジュール化をサポートするJava Module System
第11回 "NIO.2"がやってきた - JSR 203: More New I/O APIs for the Java Platform
第10回 JSR 295: Beans Bindingの参照実装を試す
第9回 けっこう便利! 単位を扱うAPI -- JSR 275: Units Specification
第8回 アノテーションでバリデーション - JSR 303: Bean Validator
第7回 Swing開発の救世主となるか - Swing Application Framework
第6回 JavaBeansのプロパティを同期させるバインディングAPI
第5回 誰よりも早く"Java SE 7"を睨む
第4回 日時情報の取り扱いを改善する JSR 310: Date and Time API
第3回 古いAPIも進化している!? - JSR 919: JavaMail 1.4
第2回 JSR 1 リアルタイムJava仕様
第1回 JCPによって進められるJava関連技術の標準化

もっと見る

提供:マイナビ

会員登録はこちら

大学・大学院・短大・専門学生向けの就職情報サイト「マイナビ2010」「マイナビ2009」に今すぐ登録しよう!  大手企業からベンチャー企業までの約13,000社の企業情報を公開、エントリーが可能です。2010年卒予定の方は「マイナビ2010」に、2009年卒予定の方は「マイナビ2009」に登録してください。

毎日コミュニケーションズはプライバシーマークを取得しています。



人気記事

一覧

イチオシ記事

新着記事