AnnotationとReflection

3407 ワード

重要なコメント
  • @Redunsion:プレゼンテーションはいつまで続きますか.ソース、クラス、ランタイム
  • @Inherita:Annotationをサブクラスに渡しますか?
  • @Target:どこで使用できますか?
  • サンプルコード
    public @interface MyAnnotation {
    }
    
    @MyAnnotation
    public class Book {
    
        private static String B = "Book";
        private static final String C = "Book";
    
        private String a = "a";
    
        public String d = "d";
    
        protected String e = "e";
    
        public Book() {
    
        }
    
        public Book(String a, String d, String e) {
            this.a = a;
            this.d = d;
            this.e = e;
        }
    
        private void f() {
            System.out.println("F");
        }
    
        public void g() {
            System.out.println("G");
        }
    
        public int h() {
            return 1000;
        }
    }
    
    public class App {
    
        public static void main(String[] args) {
            Arrays.stream(Book.class.getAnnotations()).forEach(System.out::println);
        }
    }
    前述したように、Book ClassのAnnotationをクエリーする場合は、クエリーは行われません.Annotationの動作はコメントと似ているため、情報はソースコード、クラスに保持されますが、バイトコードのロード時に保持されません.つまり、実行時には動作しません.
    @Retention
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
    }
    したがって、実行時まで維持したい場合は、上記の@Redunsionの説明を貼り付けることができます.
    実行結果

    @Target
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.FIELD})
    public @interface MyAnnotation {
    }
    @Targetアニメーションを使用してAnnotationの場所を指定できます.
    Annotation値を持つ
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.FIELD})
    public @interface MyAnnotation {
    
        String value();
    
        String name() default "hyun6ik";
    
        int number() default 100;
    
    }
    
    デフォルト値をdefaultで指定することもできます.
    またvalueを指定すると、
    @MyAnnotation("hello")
    public class Book {
    上記の明記を必要とせずに使用できます.(パラメータが2より大きい場合はvalue=を指定する必要があります.)
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.FIELD})
    @Inherited
    public @interface MyAnnotation {
    
        String value();
    
        String name() default "hyun6ik";
    
        int number() default 100;
    
    }
    前述したように@Inheritedコメントを指定すると、MyAnnotationを適用するクラスのサブクラスにもコメントが適用されます.
    public class MyBook extends Book implements MyInterface{
    }
    
    public class App {
    
        public static void main(String[] args) {
            Arrays.stream(MyBook.class.getAnnotations()).forEach(System.out::println);
        }
    }
    実行結果

    Reflection
  • getAnnotation():
  • から継承(@Inherital)宣言へのクエリー
  • getDeclaredAnnotations:
  • 現場Annotation
    FieldのAnnotationは、Annotationの情報を抽出することで参照できます.
            Arrays.stream(Book.class.getDeclaredFields()).forEach(f -> {
                Arrays.stream(f.getAnnotations()).forEach(a -> {
                    if (a instanceof AnotherAnnotation) {
                        final AnotherAnnotation anotherAnnotation = (AnotherAnnotation) a;
                        System.out.println(anotherAnnotation.number());
                        System.out.println(anotherAnnotation.name());
                    }
                });
            });