Java 注解

Java教程 - Java注解


注解将补充信息嵌入源文件中。注解不会更改程序的语义。

通过基于接口的机制创建注解。

以下代码声明了一个名为 MyAnno 的注解:

// A simple annotation type. 
@interface MyAnno {
  String str();

  int val();
}

@ 在关键字接口之前。所有注解仅具有方法声明。注解不能包含extends子句。


注意

所有注解类型自动扩展注解接口。注解接口是所有注解的超级接口。注解接口在java.lang.annotation包中声明。

任何类型的声明都可以具有与其相关联的注解。例如,可以注解类,方法,字段,参数和枚举常量。注解也可以注解。在所有情况下,注解在声明的其余部分之前。

应用注解时,您可以向其成员提供值。例如,下面是一个应用于类的 MyAnno 示例:

// Annotate a method. 
@MyAnno(str = "Annotation Example", val = 100) 
public class Main{}

此注解与类Main链接。


Java注解保留策略

保留策略确定在什么时候丢弃注解。

Java定义了三个这样的策略:SOURCE,CLASS和RUNTIME。

  • SOURCE仅保留在源文件中,并在编译期间被丢弃。
  • CLASS在编译期间存储在.class文件中。 它在运行时不能通过JVM。
  • RUNTIME存储在.class文件中,并可在运行时通过JVM使用。

通过使用Java的内置注解之一为注解指定保留策略:

@Retention

其一般形式如下所示:

@Retention(retention-policy)

retention-policy必须是 SOURCE CLASS RUNTIME 之一。

默认策略为 CLASS

以下代码将保留策略指定为RUNTIME。

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

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno {
  String str();

  int val();
}

如何通过使用反射在运行时获取注解。

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

// An annotation type declaration. 
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno {
  String str();

  int val();
}

public class Main {
  @MyAnno(str = "Annotation Example", val = 100)
  public static void myMeth() {
    Main ob = new Main();
    try {
      Class c = ob.getClass();
      Method m = c.getMethod("myMeth");
      MyAnno anno = m.getAnnotation(MyAnno.class);
      System.out.println(anno.str() + " " + anno.val());
    } catch (NoSuchMethodException exc) {
      System.out.println("Method Not Found.");
    }
  }
  public static void main(String args[]) {
    myMeth();
  }
}

上面的代码生成以下结果。

Java注解反射

您可以获取具有与某个关联的RUNTIME保留的所有注解项目,通过调用该项目的getAnnotations()。

它有这种一般形式:

Annotation[ ] getAnnotations( )

以下代码显示了如何从类中获取注解。

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno {
  String str();

  int val();
}

@Retention(RetentionPolicy.RUNTIME)
@interface What {
  String description();
}

@What(description = "An annotation")
@MyAnno(str = "Meta2", val = 99)
public class Main {
  @What(description = "test method")
  @MyAnno(str = "Testing", val = 100)
  public static void myMeth() throws Exception {
    Main ob = new Main();
    Annotation annos[] = ob.getClass().getAnnotations();
    System.out.println("All annotations for Meta2:");
    for (Annotation a : annos) {
      System.out.println(a);
    }
    Method m = ob.getClass().getMethod("myMeth");
    annos = m.getAnnotations();
    for (Annotation a : annos) {
      System.out.println(a);
    }

  }

  public static void main(String args[]) throws Exception {
    myMeth();
  }
}

上面的代码生成以下结果。

Java注解默认值

您可以给注解成员默认值。如果在应用注解时未指定值,那么将使用这些默认值。

通过向成员声明添加默认子句来指定默认值。

它有这种一般形式:

type member( ) default value;

这里是 @MyAnno 重写为包括默认值:

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno {
  String str() default "Testing";

  int val() default 9000;
}

如果需要,可以给出任一值或两者。因此,以下是可以使用@MyAnno的四种方式:

@MyAnno() // both str and val default 
@MyAnno(str = "string") // val defaults 
@MyAnno(val = 100) // str defaults 
@MyAnno(str = "Testing", val = 100) // no defaults

以下程序演示了在注解中使用默认值。

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;


@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno {
  String str() default "Testing";

  int val() default 1;
}

public class Main {
  @MyAnno()
  public static void myMeth() throws Exception{
    Main ob = new Main();
      Class c = ob.getClass();
      Method m = c.getMethod("myMeth");
      MyAnno anno = m.getAnnotation(MyAnno.class);
      System.out.println(anno.str() + " " + anno.val());
  }

  public static void main(String args[]) throws Exception{
    myMeth();
  }
}

上面的代码生成以下结果。