LoginSignup
6
3

Javaにおけるアノテーションについて学ぶ

Last updated at Posted at 2023-11-29

Javaにおけるアノテーションについて学習ついでにまとめてみました。
アノテーションの基本的な構文や使い方について説明する記事です。
割とchatGTPくんに質問しながら理解していった節があるので、サンプルなどはGPTが生成したものが多いです。

基本的なアノテーションの使用法と概要

そもそもアノテーションとは

直訳すると「注釈」という意味。
注釈とは「語句や文章をわかりやすく解説したもの」である。

Javaにおけるアノテーションとは

アプリケーションのロジックに直接関係しない付随情報(メタデータ)をコードに追加することできる。
Javaには最初から用意されている「標準アノテーション」や、自作のオリジナルアノテーションを作成することもできる。

Spring Frameworkにおいて提供されるアノテーションも存在する。
これはフレームワーク自体の拡張機能に対して、特定の振る舞いや動作をさせたい場合にアノテーションを利用することもある。

使い方

基本的なアノテーションの構文は @ から始まり、その後にアノテーションの名前が続く。
アノテーションを追加する際は、クラスやインターフェース、メソッドなど要素の先頭に記載する。
具体的な記述例は後述する。

アノテーションを使うことによるメリット

コードの意味を明示化できる

@overrideなどはメソッドが親クラスでオーバーライドしていることを明示し、
コードの読み手にコードの意味を提供する。

静的解析を使った問題の早期解決

静的解析ツールやIDEを活用して、エラーや問題の警告を早期に発見することが出来る。
これにより開発の効率を上げることが出来る。

標準アノテーションについて

ライブラリに標準で組み込まれているアノテーションのことを標準ライブラリという。
全てを挙げていくとキリがないので、代表的なアノテーションを紹介する。

@override

メソッドが親クラスでオーバーライドしていることを示す

class MyBaseClass {
    public void myMethod() {
        // メソッドの実装
    }
}

class MyDerivedClass extends MyBaseClass {
    @Override
    public void myMethod() {
        // オーバーライドしたメソッドの実装
    }
}

@Deprecated

メソッドやクラスが非推奨であることを示す

class DeprecatedExample {
    @Deprecated
    public void oldMethod() {
        // 古いメソッドの実装
    }
}

@SuppressWarnings

特定の警告を抑制するためのアノテーション
以下の例だとdeprecationの警告がコンパイル時に発生しないように抑制している。
アノテーションのパラメータは「()」内に記載することで指定することが出来る。

class SuppressWarningExample {
    @SuppressWarnings("deprecation")
    public void useDeprecatedMethod() {
        // 非推奨のメソッドを使用するが、警告を抑制
        DeprecatedExample deprecatedExample = new DeprecatedExample();
        deprecatedExample.oldMethod();
    }
}

カスタムアノテーションの利用

独自のアノテーションを作成することが出来る。
ただし、乱用するとコードが読みにくくなり可読性が下がってしまうこともあるので注意。

カスタムアノテーションの作成

アノテーションを自作するには、以下の「メタアノテーション」を使う必要がある。

@Retention :アノテーションが保持される期間を指定する

Javaには以下の3つのポリシーが存在している

  • RetentionPolicy.SOURCE(ソースレベル)
    ソースコード内でのみ有効であり、コンパイル時に取り除かれる。実行時には利用できない。
    主にコード生成などのツールが使用する場合に適しているらしい。
  • RetentionPolicy.CLASS(クラスレベル)
    コンパイルされたクラスファイルに保持されるが、実行時には利用出来ない。
    リフレクションを使用せずにアノテーションプロセッサがクラスファイルを処理する際に利用するらしい。
  • RetentionPolicy.RUNTIME(実行時)
    コンパイルされたクラスファイルに保持され、実行時にも利用出来る。
    リフレクションを使用して実行時にアノテーションを取得する場合、このリテンションポリシーが必要らしい。

※リフレクションとは
 プログラムが自分自身の構造を調査し、または操作するためのメカニズムを指す。

@Target :アノテーションがどの種類の要素に適用できるかを指定する

  • ElementType.METHOD
    メソッドに対して適用する際に指定する
  • ElementType.TYPE
    クラスに対して適用する際に指定する
  • ElementType.FIELD
    フィールドに対して適用する際に指定する
  • ElementType.CONSTRUCTOR
    コンストラクタに対して適用する際に指定する

「MyCustomAnnotation」というアノテーションを作成する際の例

chatGPTに理解の手助けをしてもらった時の例。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// カスタムアノテーションの定義
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyCustomAnnotation {
    String value() default "Default Value";
    int count() default 1;
}

自作アノテーションを使用する
mainメソッドでは、リフレクションを利用してmyAnnotatedMethodを動作させている。
myAnnotatedMethodに付与された値を動的に出力している。

import java.lang.reflect.Method;

public class MyClass {
    @MyCustomAnnotation(value = "Custom Value", count = 3)
    public void myAnnotatedMethod() {
        System.out.println("Executing myAnnotatedMethod");
    }

    public static void main(String[] args) {
        // リフレクションを使用してアノテーションの情報を取得
        try {
            // myAnnotatedMethodメソッドに付与されたアノテーションを取得
            Method method = MyClass.class.getMethod("myAnnotatedMethod");
            MyCustomAnnotation annotation = method.getAnnotation(MyCustomAnnotation.class);

            // アノテーションの情報を表示
            if (annotation != null) {
                System.out.println("Value: " + annotation.value());
                System.out.println("Count: " + annotation.count());
            }

            // アノテーションの情報を利用して動的な振る舞いを実現
            if (annotation != null && annotation.count() > 1) {
                for (int i = 0; i < annotation.count(); i++) {
                    System.out.println("Executing myAnnotatedMethod iteration " + (i + 1));
                    method.invoke(new MyClass()); // メソッドの実行
                }
            }

        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
    }
}

Spring Frameworkにおけるアノテーションについて

フレームワーク自体の拡張機能に対して、特定の振る舞いや動作をさせたい場合に活用する。
これも全て挙げるとキリがないので、業務でよく見かけるアノテーションを羅列していく。

@Controller

コントローラークラスであることを示す

@Service

サービスクラスであることを示す

@Repository

リポジトリクラスであることを示す

@RequestParam

HTTPリクエストのパラメータを取得するために使用される。

@RequestMapping

HTTPリクエストとコントローラーメソッドをマッピングするために使用される。
これにより、どのURLがどのコントローラーメソッドに対応するかを指定することが出来る。

@GetMapping

HTTP GETリクエストとコントローラーメソッドをマッピングするために使用される。
@RequestMappingの簡略版。@RequestMappingよりも簡潔なコードを実現できる。

@PostMapping

HTTP POSTリクエストとコントローラーメソッドをマッピングするために使用される。
@RequestMappingの簡略版。@RequestMappingよりも簡潔なコードを実現できる。

@Component

Spring Frameworkのコンポーネントスキャン対象のクラスに付与される。
コンポーネントスキャンとは、クラスローダーをスキャンして特定のクラスを自動的にDIコンテナに登録することである。このことをBeanという。
@Componentを記載したクラスが検出されると、Springコンテナに登録される。
その後、他のクラスでこのコンポーネントを利用する場合、DIによって自動的にインスタンスが提供される。

余談)Beanのライフサイクル

こちらの記事が非常にわかりやすかった

@Autowired

Spring FrameworkにおいてDIを実現する際に使い、コンポーネントやBeanへの自動的な依存性の注入を行う。
@Autowiredをフィールド、セッターメソッド、コンストラクタに付与することで、Springは対象のクラスのインスタンスに依存性を注入する。

参考

6
3
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
6
3