Java 11 Gold 取得に向けた学習記録
アノテーションとは
Annotation = 注釈
メタデータとしてコードに付加される情報をアノテーションと言う。メタデータとは、情報自体に対する付随的な情報のことを指す。
@アノテーション名(属性名=値)
@Deprecated
/ @SuppressWarnings
特定の要素(クラス、メソッド、フィールド、コンストラクタなど)が非推奨であることを示すために使用されるアノテーションとしてjava.lang.Deprecated
がある。
また@Deprecated
アノテーションは、forRemoval
とsince
と言う属性を持つ。
属性 | |
---|---|
bool forRemoval() |
将来のリリースで削除される予定であることを示す |
String since() |
非推奨となったバージョンを示す |
public class MyClass {
@Deprecated(since = "1.5", forRemoval = true)
public void oldMethod() {
// 古い実装
}
public void newMethod() {
// 新しい実装
}
}
@Deprecated
アノテーションが付与された要素を使用した場合、コンパイル時に警告が表示されるため開発時に使用を回避することができる。
一方で、警告内容を理解した上でなお使用しなければならない場合、「警告が表示されていることがわかっていて使用しているもの」と「意図せず警告が表示されているもの」の区別がつかなくならないように、特定の警告を非表示にしたい場面がある。
そのような場合、@SuppressWarnings
アノテーションを使用することで警告を非表示にすることができる。
@SuppressWarnings
アノテーションにはString[]
型のvalue
属性(value
と言う名前で定義された属性)が定義されていて、非表示にする警告の種類を渡す必要がある。
value 属性の引数 |
|
---|---|
"deprecation" |
@Deprecated による警告に対して使用する |
"removal" |
@Deprecated(forRemoval = true) による警告に対して使用する |
"unchecked" |
未チェックのキャストや未チェックのジェネリクス操作に関する警告に対して使用する |
"serial" |
Serializable インターフェースの実装クラスに対して、serialVersionUID フィールドが定義されていないことに関する警告に対して使用する |
"unused" |
使用されていない変数やメソッドに関する警告に対して使用する |
public class MyClass {
@Deprecated()
public void oldMethod() {
}
}
public class Main {
@SuppressWarnings("deprecation")
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.oldMethod();
}
}
カスタムアノテーション
アノテーションはclass
、interface
、enum
と同様に型の一種であり、@interface
を使用して定義することができる。
public @interface MyAnnotation {}
開発者が自前で定義したカスタムアノテーションは、暗黙的にjava.lang.annotation.Annotation
インターフェースを継承したことになる。具体的には、カスタムアノテーションはコンパイルされるとjava.lang.annotation.Annotation
インターフェースを継承したインターフェースに置き換わる。
暗黙的な継承は、javap
コマンドによって確認することができる。
$ cd <MyAnnotationのディレクトリ>
$ javac MyAnnotation.java
$ javap MyAnnotation.class
Compiled from "MyAnnotation.java"
public interface MyAnnotation extends java.lang.annotation.Annotation {}
public interface MyAnnotation extends java.lang.annotation.Annotation {}
ただし@MyAnnotation
を付与したクラスが、MyAnnotation
を継承(extends
)したり実装(implements
)したクラスになるわけではない。
アノテーションは型の一種。
パラメータ
定義
アノテーションには属性を定義することができ、この属性を注釈パラメータと言う。
public @interface MyAnnotation {
// 属性を定義
String attribute();
}
パラメータに使用できる型は以下のみ。
- プリミティブ型
-
int
、long
、short
、float
、double
、byte
、char
、boolean
-
-
String
型 -
Class
型 - Enum型
- アノテーション型
- 上記を要素にもつ配列
使い方
定義したパラメータには、次のような形で渡すことができる。
@MyAnnotation(attribute = "hello")
public class MyClass {}
属性名の省略
- パラメータが一つ
- パラメータ名が
value
の条件を満たす場合、アノテーション付与時にパラメータ名を省略することができる。
public @interface MyAnnotation {
String value();
}
@MyAnnotation("hello")
public class MyClass {}
()
の省略
パラメータがない場合、アノテーションの()
は省略することができる。
パラメータを持たないアノテーションのように、付与されていること自体に意味を持つようなものをマーカーアノテーションと言う。
public @interface MyAnnotation {}
@MyAnnotation
public class MyClass {
}
デフォルト値
パラメータは、デフォルト値をあらかじめ定義しておくことができる。
public @interface MyAnnotation {
String value() default "hello";
}
デフォルト値が定義されたアノテーションには、パラメータを渡す必要がない。
// デフォルト値 "hello" が使用される
@MyAnnotation
public class MyClass {
}
配列のパラメータ
注釈パラメータが配列の場合、以下のような使い方になる。
public @interface MyAnnotation {
String[] array() ;
}
@MyAnnotation(array = {"hello", "world", "!"})
public class MyClass {
}
このとき、もし渡す配列の要素が1つだけなら配列リテラル{}
を省略することができる。
@MyAnnotation(array = "hello")
public class MyClass {
}
メタアノテーション
アノテーションを定義する際に利用するアノテーションをメタアノテーションと言う。メタアノテーションはアノテーションの構成情報を宣言するために使用される。
@Retention
/ RetentionPolicy
Retention = 保持
アノテーションの保持時間を指定するために利用されるメタアノテーションとして、java.lang.Retention
がある。
メタアノテーションのRetention
は、注釈パラメータvalue
にEnum型のjava.lnag.RetentionPolicy
を保持している。
RetentionPolicy |
説明 |
---|---|
CLASS |
デフォルト値。.class ファイルには保持されるが、実行時にJVMによって保持されない。.class ファイルに対して処理を行うような場合に使用する。リフレクションを利用して読み取ることができない。 |
RUNTIME |
.class ファイルと実行時のJVMで、どちらも保持される。リフレクションを利用して読み取ることができる。 |
SOURCE |
コンパイラによって破棄され、.class ファイルに保持されない(実行時も保持されない)。 |
以下のような形で利用する。
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}
@Target
/ ElementType
アノテーションの対象を指定するために利用されるメタアノテーションとして、java.lang.Target
がある。
Retention
は、注釈パラメータvalue
にEnum型のjava.lnag.ElementType
を保持している。
ElementType |
説明 |
---|---|
ANNOTATION_TYPE |
アノテーションの定義(メタアノテーション) |
CONSTRUCTOR |
コンストラクタ |
FIELD |
フィールド |
LOCAL_VARIABLE |
ローカル変数 |
METHOD |
メソッド |
MODULE |
モジュール |
PACKAGE |
パッケージ |
PARAMETER |
パラメータ |
TYPE |
クラス、インターフェース、Enum |
TYPE_PARAMETER |
ジェネリクス(型引数) |
TYPE_USE |
型に対してアノテーションを付与する |
以下のような形で利用する。
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
public @interface MyAnnotation {}
リフレクションからアノテーション情報を取得する
リフレクションを利用してアノテーション情報を取得するためにはClass<T>
クラスのgetAnnotation()
メソッドを使用する。
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
Class<MyClass> myClassCls = MyClass.class;
Class<MyAnnotation> myAnnotationCls = MyAnnotation.class;
MyAnnotation myAnnotation = myClassCls.getAnnotation(myAnnotationCls);