Java の Class クラスに定義されているメソッドを見ていくシリーズ(目次)。 今回は Class クラスに定義されているメソッドのうち、クラスの宣言に関するメソッドを見ていきます。
クラス宣言に関するメソッド
クラス宣言に関するメソッド*1は、ここでは以下のような Java コードに含まれている要素とします:package org.sample; @MyAnnotation public class MyClass<N extends Number>{ // ... }
つまり、以下の要素とします:
クラス階層(継承や実装など)に関連するメソッドは今回は扱いません(おそらく次回)。 今回扱うメソッドを列挙すると
メソッド名 | |
---|---|
パッケージ | getPackage() |
アノテーション | isAnnotationPresent(Class<? extends Annotation> aType) getAnnotations() <A extends Annotation> getAnnotation(Class<A> aType) getDeclaredAnnotations() |
修飾子 | getModifiers() |
型パラメータ | getTypeParameters() |
です。
パッケージ Package
パッケージ関連のメソッドは下表の通り:メソッド名 | 返り値 |
---|---|
getPackage() | Package |
Package クラスの完全修飾名は java.lang.Package です。 使い方は上記の MyClass クラスに対して
Class<?> type = MyClass.class Package pack = type.getPackage(); System.out.println(pack.getName()); // "org.sample" と表示
といった感じです。 Package クラスの詳細は JavaDoc 参照。
アノテーション Annotation
アノテーション関連のメソッドは以下の通り:メソッド名 | 返り値 | スコープ |
---|---|---|
getAnnotations() isAnnotationPresent(Class<? extends Annotation> aType) <A extends Annotation> getAnnotation(Class<A> aType) |
Annotation[] boolean A |
親クラス、 実装インターフェースを含む |
getDeclaredAnnotations() | Annotation[] | 対象とする型のみ |
Annotation インターフェースの完全修飾名は java.lang.annotation.Annotation です。 また、これらのメソッドは java.lang.reflect.AnnotatedElement に定義されています。
アノテーションを取得できる条件
上記のメソッドを使ってプログラム中からアノテーションを取得できるためには、アノテーションのリテンション・ポリシーが RUNTIME でなければなりません:@Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation{}
また、親クラスや実装インターフェースに付加してあるアノテーションが取得できるためには、さらに @Inherited が付加されている必要があります:
@Inherited @Retention(RetentionPolicy.RUNTIME) public @interface SuperAnnotation{}
アノテーションの取得方法
ここではアノテーションの取得方法を見ていきます。 扱うアノテーションはすべて先ほどの「アノテーションを取得できる条件」を満たしているとします。getDeclaredAnnotations() メソッドとその他のメソッドでは、対象とするアノテーションが少し違います。getDeclaredAnnotations() メソッドは親クラス・実装インターフェースにさかのぼらずに、対象としている型に付加されているアノテーションのみを返します。 一方、getDeclaredAnnotations() メソッド以外は、親クラス・実装インターフェースにさかのぼってアノテーションを検索します。
例えば以下のように SuperClass クラスと MyClass クラスが定義されているとします:
@SuperAnnotation public class SuperClass{...} @MyAnnotation public class MyClass extends SuperClass{...}
@MyAnnotation, @SuperAnnotation アノテーションは先ほどのように定義されているとします。 このとき
Class<?> type = MyClass.class; type.getAnnotations(); // 配列 [@MyAnnotation, @SuperAnnoation] が返される assert type.isAnnotationPresent(@MyAnnotation.class) == true; assert type.isAnnoationPresent(@SuperAnnotation.class) = true; assert type.getAnnotation(@MyAnnotation.class) != null; assert type.getAnnotation(@SuperAnnotation.class) != null; type.getDeclaredAnnotations(); // 配列 [@MyAnnotation] が返される
となります。
アノテーション関連メソッドのまとめ
結果をまとめると対象クラスのアノテーション | 親クラス・実装インターフェース のアノテーション |
|
---|---|---|
getAnnotations() isAnnotationPresent() getAnnotation() |
○ (RetentionPolicy:RUNTIME) |
○ (RetentionPolicy:RUNTIME, Inherited) |
getDeclaredAnnotations() | ○ (RetentionPolicy:RUNTIME) |
× |
○:取得可能 ×:取得不可能
となります。
修飾子 Modifier
修飾子関連のメソッドは下表の通り:メソッド名 | 返り値 |
---|---|
getModifiers() | int |
修飾子を判定するには java.lang.reflect.Modifier クラスに定義されている static メソッドを用います:
Class<?> type = MyClass.class; int mod = type.getModifiers(); System.out.println(Modifier.isPublic(mod)); // "true" と表示
型パラメータ Type Parameter
型パラメータに関連するメソッドは下表の通り(Class<T> に対するメソッド):メソッド名 | 返り値 |
---|---|
getTypeParameters() | TypeVariable<Class<T>>[] |
このメソッドは java.lang.reflect.GenericDeclaration に定義されているメソッドです。 使い方は、記事最初の MyClass クラスに対して
Class<?> type = MyClass.class; TypeVariable<?> tv = type.getTypeParameters()[0]; System.out.println(tv.getGenericDeclaration()); // "class org.sample.MyClass" と表示 (MyClass.class.toString()) System.out.println(tv.getName()); // "N" と表示 System.out.println(tv.getBounds()[0]); // "class java.lang.Number" と表示 (Number.class.toString())
といった感じです。 TypeVariable インターフェース(完全修飾名 java.lang.reflect.TypeVariable)の詳細については JavaDoc 参照。
追記
id:irof 氏にご指摘いただきましたが、アノテーションを取得するメソッドは @Inherited アノテーションが付いているアノテーションを、“親クラス”だけをさかのぼって探し、“実装インターフェース”は参照しないようです。Effective Java 第2版 (The Java Series)
- 作者: Joshua Bloch,柴田芳樹
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2008/11/27
- メディア: 単行本(ソフトカバー)
- 購入: 77人 クリック: 936回
- この商品を含むブログ (266件) を見る
*1:一般に使われている言葉ではありませんが。