LoginSignup
70
75

More than 5 years have passed since last update.

いまさらJavaのアノテーションを復習する

Last updated at Posted at 2018-11-26

概要

業務でSpring Bootを使うことになり、はるか昔の新卒のJava研修の内容しかなかった頭にアノテーションの概念をインプットする必要に迫られた。

参考にしたサイト

ものすごいわかりやすかったです
http://www.atmarkit.co.jp/ait/articles/1105/19/news127.html

特にこの例でスッと入ってきました

アノテーションとは、「注釈」という意味です。Javadocコメントは開発者に対してプログラムがどういうものかを説明するために使いましたが、これと同様に、コンパイラや実行環境に対してプログラムがどういうものかを伝えたいことがあります。

後述する具体的な例を見れば分かりますが、Javaではアノテーションをプログラムに記述することにより、コンパイラで出力される警告メッセージを抑制したり、実行環境によってプログラムの動作を変更したりできます。

実行時の利用についてはこちらを参考にさせていただきました。
https://www.qoosky.io/techs/390aad36f8

やってみる

java version 1.8.0_181
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

src
└test
  └java
    └annotation
      ├ Main.java
      └ MethodInformation.java

内容

ただのマーカーとしてのアノテーション型を作って設定してみます。

MethodInformation.java
package test.java.annotation;

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

// Targetアノテーションを付けることで「何につけられるアノテーションなのか?」を指定できる
@Target(ElementType.TYPE)
public @interface MethodInformation {
}

Main.java
package test.java.annotation;

@MethodInformation
public class Main {

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

WS000060.JPG
WS000059.JPG

ElementType の種類って?

こちらをどうぞ

java.lang.annotation.ElementType.java
public enum ElementType {
   /** Class, interface (including annotation type), or enum declaration */
   TYPE,

   /** Field declaration (includes enum constants) */
   FIELD,

   /** Method declaration */
   METHOD,

   /** Formal parameter declaration */
   PARAMETER,

   /** Constructor declaration */
   CONSTRUCTOR,

   /** Local variable declaration */
   LOCAL_VARIABLE,

   /** Annotation type declaration */
   ANNOTATION_TYPE,

   /** Package declaration */
   PACKAGE,

   /**
    * Type parameter declaration
    *
    * @since 1.8
    */
   TYPE_PARAMETER,

   /**
    * Use of a type
    *
    * @since 1.8
    */
   TYPE_USE
}

実行

何の問題もなく出力されています。特に何もしないアノテーションなので出力内容に変更はありません。
WS000061.JPG
WS000062.JPG

メソッドにしか付けられないアノテーションにしてみる

MethodInformation.java
package test.java.annotation;

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

@Target(ElementType.METHOD) // メソッドにしか付けられません
public @interface MethodInformation {
}

不穏な空気です
WS000065.JPG

実行

無事失敗します
WS000066.JPG
WS000067.JPG

クラス内部からアノテーションの情報を取得する

MethodInformation.java
package test.java.annotation;

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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) // コンパイル→実行時にもアノテーションの情報を保持しておく必要がある
public @interface MethodInformation {
}

Main.java
package test.java.annotation;

@MethodInformation
public class Main {

    public static void main(String[] args) {
        Main mainInstance = new Main();
        Class clazz = mainInstance.getClass();

        // Mainクラスに設定されているアノテーションの種類を得る
        System.out.println(clazz.getAnnotation(MethodInformation.class));
        System.out.println("Hello World!");
    }
}

WS000000.JPG
WS000002.JPG

RetentionPolicyの種類って?

こちらをどうぞ

java.lang.annotation.RetentionPolicy.java
public enum RetentionPolicy {
   /**
    * Annotations are to be discarded by the compiler.
    */
   SOURCE,

   /**
    * Annotations are to be recorded in the class file by the compiler
    * but need not be retained by the VM at run time.  This is the default
    * behavior.
    */
   CLASS,

   /**
    * Annotations are to be recorded in the class file by the compiler and
    * retained by the VM at run time, so they may be read reflectively.
    *
    * @see java.lang.reflect.AnnotatedElement
    */
   RUNTIME
}

実行結果

@test.java.annotation.MethodInformation() が出力されてるのがわかります
WS000001.JPG

値が設定されたアノテーションの値を取得

アノテーション要素と呼ばれるものを作って、その値を取得してみる

MethodInformation.java
package test.java.annotation;

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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodInformation {
    String testString();
    int testInt();
}


Main.java
package test.java.annotation;

@MethodInformation(testString = "this is test", testInt = 12345)
public class Main {

    public static void main(String[] args) {
        Main mainInstance = new Main();
        Class clazz = mainInstance.getClass();

        MethodInformation methodInformation = (MethodInformation)clazz.getAnnotation(MethodInformation.class);

        // アノテーション型内ではメソッドで定義されている
        System.out.println(methodInformation.testString());
        System.out.println(methodInformation.testInt());
        System.out.println("Hello World!");
    }
}


WS000003.JPG
WS000005.JPG

実行結果

無事設定された値が見れました
WS000006.JPG

自分自身をアノテーションしても大丈夫

MethodInformation.java
package test.java.annotation;

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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@MethodInformation(testString = "this is test double", testInt = 1234512345) // 自分自身をアノテーション
public @interface MethodInformation {
    String testString() default "test";
    int testInt() default 1234;
}
Main.java
package test.java.annotation;

@MethodInformation
public class Main {

    public static void main(String[] args) {
        Main mainInstance = new Main();
        Class clazz = mainInstance.getClass();

        MethodInformation methodInformation = (MethodInformation)clazz.getAnnotation(MethodInformation.class);

        System.out.println(methodInformation.testString());
        System.out.println(methodInformation.testInt());
        System.out.println("Hello World!");
    }
}

annotation_5.JPG
main_11.JPG

実行結果

上書きはされてない(アノテーションのデフォルト値が入っている)のが確認できる。少し不思議な気もします。
WS000000.JPG

70
75
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
70
75