【コラム】

Java API、使ってますか?

35 公開されたJSR 308のEarly Draftを検証する

35/60

JSR 308の概要

本連載第15回で、配列やメソッドレシーバ、ジェネリックの型引数などに対してアノテーションを適用できるようにするための「JSR 308: Annotations on Java Types」を紹介した。そのJSR 308だが、11月9日よりJCPのサイトにおいてEary Draftの公開が開始されている。これによって新しいアノテーション利用方法の詳細が明らかになってきた。

まず、前回も書いたようにJSR 308の主題は"型"に対するアノテーションの適用を可能にすることであり、同時にローカル変数や配列、文に対する適用も検討されている。一方で式やブロック、ループ、部分構造などに対する適用は考えられていない。

Eary DraftではJSR 308によるアノテーションの適用例として、リスト1に示すものが挙げられている。大半は前回紹介したものと同じだが、新たにGenaricであるメソッドレシーバの型パラメータや静的メンバアクセスに対する適用が追加されている。

リスト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 { ... }
// メソッドレシーバがGenaricである場合、そのパラメータにも指定できる [New]
public int size() @Readonly<@Readonly> { ... }
public void requiresNonNullKeys() <@NonNull,> { ... }

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

// 静的メンバへのアクセス [New]
@NonNull Type.field

// 配列
Document[@Readonly][] docs4 = new Document[@Readonly 2][12];
Document[][@Readonly] docs5 = new Document[2][@Readonly 12];
※ ここで使われている@NonNullや@NonEmptyなどのアノテーションは架空のもので、実際にこのようなアノテーションがJava SEに用意されるということではない。

Eary Draftで上記適用例のいくつかに関する詳細な説明が掲載されているので、以下で簡単に紹介したい。

型に対するアノテーションの適用例1 - メソッドレシーバに対するアノテーション

メソッドレシーバは通常暗黙のパラーメータだが、そのレシーバにアノテーションを指定することで明示的な制限などを加えることができるようになる。たとえばリスト2のように宣言されていた場合、size()メソッドの呼び出しがレシーバに変更を加えないことを示す。

リスト2

int size() @Readonly { ... }

メソッドレシーバに対するアノテーションは、メソッドそのものやメソッドの戻り値に対するアノテーションとは異なるので注意が必要だ。たとえばメソッドの戻り値を変更しないように示唆したい場合は、戻り値に対して@Readonlyを指定するような形になる。

型に対するアノテーションの適用例2 - 型キャストに対するアノテーション

Eary Draftには、キャストする型に対してアノテーションを許可する理由が2つ挙げられている。ひとつは、キャスト対象のオブジェクトの型にアノテーションが指定されていた場合、キャスト後の型も同じアノテーションを含む必要があるという理由である。キャスト時にアノテーションが外れてしまったのでは意味がないからだ。

たとえばリスト3のように@NonNullを指定された型のオブジェクトは、@NonNullの型にしかキャストすることはできない。

リスト3

@NonNull Object myObject;
@NonNull String myString = (@NonNull String) myObject;
String myString2 = (String) myObject;   // これはアノテーションの処理時にエラーになる

もうひとつの理由は、コンパイラに型に関する付加的な情報を渡したい場合に利用できるというもの。たとえばリスト4の場合、キャストすることによってオブジェクトxにnullを許容しないという制限を加えている。

リスト4

final Object x = new Object();
@NonNull myObject = (@NonNull Object) x;

型に対するアノテーションの適用例3 - 型チェックに対するアノテーション

instanceof演算子でチェックする型に対してもアノテーションを指定できるようになる。このとき、アノテーションと型が両方一致しなければtrueにはならない。たとえば、リスト5のように"@NonNull Object"な型のオブジェクトは、型が一致したとしても@NonNullでなければtrueにはならない。

リスト5

@NonNull Object myObject = new String("hoge");
... myObject instanceof @NonNull String  // true
... myObject instanceof String            // false

逆も同様で、アノテーションを指定されていない型のオブジェクトは、何らかのアノテーションが指定された型とは一致しない。

リスト6

Object myObject = new String("hoge");
... myObject instanceof @NonNull String  // false
... myObject instanceof String           // true

型に対するアノテーションの適用例4 - オブジェクト生成に対するアノテーション

オブジェクトの生成に対してアノテーションを指定すると、生成されるオブジェクトに対して制約を加えることが可能になる。たとえばリスト7のようにした場合、生成されるListオブジェクトは読み込み専用で、かつ空であってはならないものとなる。

リスト7

List myList = new @NonEmpty @Readonly List(myNonEmptyStringSet);

型に対するアノテーションの適用例5 - 型引数の制約やワイルドカードに対するアノテーション

ジェネリクスを利用する場合、型引数には制約やワイルドカードを指定できる。JSR 208では、この制約やワイルドカードのための型に対してアノテーションを付けることができるようになる。Draftには詳しくは書かれていないが、たとえばリスト8のようなクラス宣言の場合、型Fの値はは存在するファイルへの参照を持つFile(の派生クラスの)インスタンスでなければならないということのようだ。

リスト8

class Folder { 
      ...... 
}

型に対するアノテーションの適用例6 - スーパークラスに対するアノテーション

クラスの継承やインタフェースの実装の際に、スーパークラスに対してアノテーションを指定することで、サブクラス自身にもそのアノテーションが適用される。たとえばリスト9ではスーパークラスが読み込み専用のListになっているため、UnmodifiableListも読み込み専用となる。

リスト9

class UnmodifiableList implements @Readonly List<@Readonly T> {
      ......
}

型に対するアノテーションの適用例7 - 配列に対するアノテーション

JSR 308では配列に対してアノテーションを指定することも可能になる予定だが、そのための構文についてはまだ詳細が定まっていない。Eary Draftではいくつかの候補が提案されている。

基本的な議論としては、まず括弧([])に対するアノテーションが配列自身を対象とするのか(ARRAY)、それとも配列の要素を対象とするのか(ELTS)という点がある。それから、アノテーションがどこに表れるのかといった問題もある。選択肢としては括弧の中(IN)なのか前(PRE)なのか、あるいは後ろ(POST)なのかだ。

たとえばリスト10のような宣言の場合、ARRAY-INという組み合わせならば@Readonlyは配列自身にかかるので、「要素にnullを許容しない読み込み専用の配列」ということになる。ELTS-INならば逆に@Readonlyは要素にかかるので、「読み込み専用の要素を持つnullでない配列」ということになる。

リスト10

@NonNull Document[@Readonly]

いずれにせよ矛盾がなく、かつ理解しやすい構文にしなければならないが、もともとの配列の構文があまり厳密と言えるものではないため、詳細が決定するまでにはまだ時間が必要なようだ。

本連載の第15回ではJSR 308対応コンパイラの開発版を使ってみた。現在は使用できるアノテーションが増えている他、ビルド方法も若干変更されているので、次回はその辺りを紹介したいと思う。

35/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」に登録してください。

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



人気記事

一覧

イチオシ記事

新着記事