0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Java アノテーション

Last updated at Posted at 2024-07-20

Java 11 Gold 取得に向けた学習記録

アノテーションとは

Annotation = 注釈

メタデータとしてコードに付加される情報をアノテーションと言う。メタデータとは、情報自体に対する付随的な情報のことを指す。

アノテーション
@アノテーション名(属性名=)

@Deprecated / @SuppressWarnings

特定の要素(クラス、メソッド、フィールド、コンストラクタなど)が非推奨であることを示すために使用されるアノテーションとしてjava.lang.Deprecatedがある。

また@Deprecatedアノテーションは、forRemovalsinceと言う属性を持つ。

属性
bool forRemoval() 将来のリリースで削除される予定であることを示す
String since() 非推奨となったバージョンを示す
@Deprecated
public class MyClass {
    @Deprecated(since = "1.5", forRemoval = true)
    public void oldMethod() {
        // 古い実装
    }

    public void newMethod() {
        // 新しい実装
    }
}

@Deprecatedアノテーションが付与された要素を使用した場合、コンパイル時に警告が表示されるため開発時に使用を回避することができる。

anotation.png

一方で、警告内容を理解した上でなお使用しなければならない場合、「警告が表示されていることがわかっていて使用しているもの」と「意図せず警告が表示されているもの」の区別がつかなくならないように、特定の警告を非表示にしたい場面がある。

そのような場合、@SuppressWarningsアノテーションを使用することで警告を非表示にすることができる。

@SuppressWarningsアノテーションにはString[]型のvalue属性(valueと言う名前で定義された属性)が定義されていて、非表示にする警告の種類を渡す必要がある。

value属性の引数
"deprecation" @Deprecatedによる警告に対して使用する
"removal" @Deprecated(forRemoval = true)による警告に対して使用する
"unchecked" 未チェックのキャストや未チェックのジェネリクス操作に関する警告に対して使用する
"serial" Serializableインターフェースの実装クラスに対して、serialVersionUIDフィールドが定義されていないことに関する警告に対して使用する
"unused" 使用されていない変数やメソッドに関する警告に対して使用する
public class MyClass {
    @Deprecated()
    public void oldMethod() {
    }
}
@SuppressWarnings
public class Main {
    @SuppressWarnings("deprecation")
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.oldMethod();
    }
}

カスタムアノテーション

アノテーションはclassinterfaceenumと同様に型の一種であり、@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();
}

パラメータに使用できる型は以下のみ。

  • プリミティブ型
    • intlongshortfloatdoublebytecharboolean
  • 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ファイルに保持されない(実行時も保持されない)。

以下のような形で利用する。

@Retention
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 型に対してアノテーションを付与する

以下のような形で利用する。

@Target
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);

参考

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?