定义 -> @interface

  1. publiC @interface TestAnnotation{
  2. }

应用

  1. @TestAnnotation
  2. public class Test{
  3. }

元注解


基本注解,而且可以注解到注解上.
@Retention、@Documented、@Target、@Inherited、@Repeatable

  • Retention -> 解释注解的存活时间

    • 取值:
      • RetentionPolicy.SOURCE : 编译时忽略它
      • RetentionPolicy.CLASS : 编译时保留,但不加载到 jvm
      • RetentionPolicy.RUNTIME: 加载进 JVM , 程序运行时还在
        1. @Retention(RetentionPolicy.RUNTIME)
        2. public @interface TestAnnotation {
        3. }
  • Document -> 将注解中的元素加到 Javadoc

  • Target -> 指定了注解运用的地方
    • ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
    • ElementType.CONSTRUCTOR 可以给构造方法进行注解
    • ElementType.FIELD 可以给属性进行注解
    • ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
    • ElementType.METHOD 可以给方法进行注解
    • ElementType.PACKAGE 可以给一个包进行注解
    • ElementType.PARAMETER 可以给一个方法内的参数进行注解
    • ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
  • Inherited -> 说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果 它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。
  • Repeatable -> 让注解可以在同一地方出现多次
    1. @interface Persons {
    2. Person[] value();
    3. }
    4. @Repeatable(Persons.class)
    5. @interface Person{
    6. String role default "";
    7. }
    Repeatable 注解了 Person , Persons.class 是容器注解(存放容器的地方), 它里面必须有一个叫 value 的属性,类型是一个数组, 放的是被@Repeatable注解过的注解…
    然后就可以让注解可以在同一地方出现多次了
    1. @Person(role="artist")
    2. @Person(role="coder")
    3. @Person(role="PM")
    4. public class SuperMan{
    5. }

    注解的属性


注解只有属性没有方法

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface TestAnnotation {
  4. int id() default -1;
  5. String msg() default "Hi";
  6. }

可以以 实例.id() 的格式调用
赋值:(不赋值就是 default )

  1. @TestAnnotation(id=3,msg="hello annotation")
  2. public class Test {
  3. }

只有一个属性的话就不用了写 value = xx 了, 直接写 xx 就行了

  1. @Check("hi")
  2. int a;

最后,还需要注意的一种情况是一个注解没有任何属性。比如

  1. public @interface Perform {}

那么在应用这个注解的时候,括号都可以省略。

@Perform
public void testMethod(){}

预置注解


  • Deprecated -> 标记过时的元素,编译器识别后会产生”划掉”效果
  • Override -> 提示子类要重写父类中被 @Override 修饰的方法
  • SupperWarnings -> 忽略警告, 比如”忽略方法过时的警告”:

    @SuppressWarnings("deprecation")
    
  • Functionalinterface -> 函数式接口

    提取注解


如果一个注解要在运行时被成功提取,那么@Retention(RetentionPolicy.RUNTIME) 是必须的
注解通过反射获取。首先可以通过 Class 对象的 isAnnotationPresent() 方法判断它是否应用了某个注解

public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}

然后通过 getAnnotation() 方法来获取 Annotation 对象。

public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}

或者是 getAnnotations() 方法。

public Annotation[] getAnnotations() {}

前一种方法返回指定类型的注解,后一种方法返回注解到这个元素上的所有注解。
例子:

@TestAnnotation()
public class Test {
    public static void main(String[] args) {
        boolean hasAnnotation = Test.class.isAnnotationPresent(TestAnnotation.class);
        if ( hasAnnotation ) {
            TestAnnotation testAnnotation = Test.class.getAnnotation(TestAnnotation.class);
            System.out.println("id:"+testAnnotation.id());
            System.out.println("msg:"+testAnnotation.msg());
        }
    }
}

属性/方法上的注解

@TestAnnotation(msg="hello")
public class Test {
    @Check(value="hi")
    int a;
    @Perform
    public void testMethod(){}
    @SuppressWarnings("deprecation")
    public void test1(){
        Hero hero = new Hero();
        hero.say();
        hero.speak();
    }
    public static void main(String[] args) {
        boolean hasAnnotation = Test.class.isAnnotationPresent(TestAnnotation.class);
        if ( hasAnnotation ) {
            TestAnnotation testAnnotation = Test.class.getAnnotation(TestAnnotation.class);
            //获取类的注解
            System.out.println("id:"+testAnnotation.id());
            System.out.println("msg:"+testAnnotation.msg());
        }
        try {
            Field a = Test.class.getDeclaredField("a");
            a.setAccessible(true);
            //获取一个成员变量上的注解
            Check check = a.getAnnotation(Check.class);
            if ( check != null ) {
                System.out.println("check value:"+check.value());
            }
            Method testMethod = Test.class.getDeclaredMethod("testMethod");
            if ( testMethod != null ) {
                // 获取方法中的注解
                Annotation[] ans = testMethod.getAnnotations();
                for( int i = 0;i < ans.length;i++) {
                    System.out.println("method testMethod annotation:"+ans[i].annotationType().getSimpleName());
                }
            }
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e.getMessage());
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e.getMessage());
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }
}