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

#概要
業務で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


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

```java:MethodInformation.java
package test.java.annotation;

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

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

```


```java:Main.java
package test.java.annotation;

@MethodInformation
public class Main {

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

```

![WS000060.JPG](https://qiita-image-store.s3.amazonaws.com/0/275553/9822cb1d-2ed6-b428-c295-0a9824ea5813.jpeg)
![WS000059.JPG](https://qiita-image-store.s3.amazonaws.com/0/275553/bc43b1a9-1055-ef78-a3e4-b2ee1b3b18b3.jpeg)


###ElementType の種類って？
こちらをどうぞ
>```java: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](https://qiita-image-store.s3.amazonaws.com/0/275553/41e78129-45de-b69a-a570-27adfc5352c2.jpeg)
![WS000062.JPG](https://qiita-image-store.s3.amazonaws.com/0/275553/89dd90fb-6cfb-b6a7-da38-b6bd348dfcec.jpeg)


##メソッドにしか付けられないアノテーションにしてみる
```java:MethodInformation.java
package test.java.annotation;

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

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

不穏な空気です
![WS000065.JPG](https://qiita-image-store.s3.amazonaws.com/0/275553/c02d2ae1-7915-d664-0517-2c4ee9823c7a.jpeg)


##実行
無事失敗します
![WS000066.JPG](https://qiita-image-store.s3.amazonaws.com/0/275553/07211b0c-85c4-3b33-d290-8d7bf5bb52ff.jpeg)
![WS000067.JPG](https://qiita-image-store.s3.amazonaws.com/0/275553/4ae045fa-12cb-7b02-51b7-5dcbadc734ac.jpeg)


#クラス内部からアノテーションの情報を取得する
```java: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 {
}

```

```java: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](https://qiita-image-store.s3.amazonaws.com/0/275553/5e0e204d-18b1-5e87-83f3-5a4525db4ab5.jpeg)
![WS000002.JPG](https://qiita-image-store.s3.amazonaws.com/0/275553/66231f48-d6ca-2356-000d-6216560539ef.jpeg)



##RetentionPolicyの種類って？
こちらをどうぞ
>```java: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](https://qiita-image-store.s3.amazonaws.com/0/275553/37142aca-2d68-ce3f-1d7b-ca76c97c6a31.jpeg)


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

```java: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();
}


```

```java: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](https://qiita-image-store.s3.amazonaws.com/0/275553/8164696a-b7b3-5655-a643-9baf8a3ad1df.jpeg)
![WS000005.JPG](https://qiita-image-store.s3.amazonaws.com/0/275553/c92f1c4b-75b4-7451-c9a5-7aa4e35f6cac.jpeg)

##実行結果
無事設定された値が見れました
![WS000006.JPG](https://qiita-image-store.s3.amazonaws.com/0/275553/0a9213ac-533c-480e-6342-51af18e2541d.jpeg)


#自分自身をアノテーションしても大丈夫
```java: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;
}
```

```java: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](https://qiita-image-store.s3.amazonaws.com/0/275553/c4a3083f-f73c-75a9-44ec-0af8fcb108cc.jpeg)
![main_11.JPG](https://qiita-image-store.s3.amazonaws.com/0/275553/7f262aba-2be6-80e7-af8b-c187108cd813.jpeg)


##実行結果
上書きはされてない(アノテーションのデフォルト値が入っている)のが確認できる。少し不思議な気もします。
![WS000000.JPG](https://qiita-image-store.s3.amazonaws.com/0/275553/b88813e8-fa5c-8e74-2a3c-e894fb515d64.jpeg)