理解Java中的注释

时间:2011-04-16 10:06:13

标签: java annotations

我试图通过一些在线资料来学习java中的注释。

在下面的代码中,我在这行中传递的亲爱的“Hello world”字符串发生了什么:@Test_Target(doTestTarget="Hello World !")

@Target(ElementType.METHOD)
public @interface Test_Target {
   public String doTestTarget();
}
上面的

是定义的注释,下面是它的用法

public class TestAnnotations {
   @Test_Target(doTestTarget="Hello World !")
   private String str;
   public static void main(String arg[]) {
      new TestAnnotations().doTestTarget();
   }
   public void doTestTarget() {
      System.out.printf("Testing Target annotation");
   }
}

当我运行此代码时,它只打印Testing Target annotation

请帮帮我,我对注释完全不熟悉。

3 个答案:

答案 0 :(得分:22)

注释基本上是可以附加到字段,方法,类等的数据位。

在Java中声明注释的语法有点尴尬。它们看起来有点像接口(毕竟它们是用@interface声明的),但它们并不是真正的接口。我想您可能已将doTestTarget()方法放在TestAnnotations类中,因为您认为注释是一个接口,您需要实现它。事实并非如此 - 如果您愿意,可以删除此方法并从代码中调用它,这样做不会给您带来任何问题。

此外,您可能没有打算将注释放在字段str上。注释仅适用于紧随其后的内容。因此,您的代码无法编译,因为您已将注释应用于字段,但声明您的注释只能应用于方法。将@Target(ElementType.METHOD)更改为@Target(ElementType.FIELD),然后应编译代码。

对于字符串Hello World !会发生什么,它会被写入.class文件,并且可用于读取Java类的任何工具。但是,它不一定在运行时在JVM中可用。这是因为您没有为@Retention注释指定@Test_Target@Retention的默认值为RetentionPolicy.CLASS,这意味着JVM可能无需将它们加载到类文件中。 (参见Javadoc for the RetentionPolicy enum。)

我想你想在运行时看到一些从这个注释中读取值的方法。如果是这样,我建议您在注释中添加@Retention(RetentionPolicy.RUNTIME)以确保它在运行时可用。

要在运行时访问注释及其中包含的值,您需要使用反射。我已按照以下方式重写您的TestAnnotations课程,以便快速演示:

import java.lang.reflect.Field;

public class TestAnnotations {

   @Test_Target(doTestTarget="Hello World !")
   private String str;

   public static void main(String[] args) throws Exception {
      // We need to use getDeclaredField here since the field is private.
      Field field = TestAnnotations.class.getDeclaredField("str");
      Test_Target ann = field.getAnnotation(Test_Target.class);
      if (ann != null) {
         System.out.println(ann.doTestTarget());
      }
   }
}

当我运行此代码时,它给出了以下输出:

Hello World !

答案 1 :(得分:4)

原则上,单独添加注释并不会从根本上改变程序的行为。

在您的情况下,您创建了一个新的注释类型@Test_Target,可以在任何方法上使用(如@Target注释所示)。

然后你不将这个应用到方法,而是应用到str字段(我认为应该给出编译器错误)。

独立于此,您正在使用doTestTarget方法创建一个对象,并调用它,并获得预期结果(即执行该方法)。

如果你希望你的注释能够做更多的事情而不仅仅是为源代码的读者提供一些信息,你必须使用它 - 在编译时使用注释处理器,或者在运行时使用反射(然后您还需要@Retention(RUNTIME)作为Test_Target上的注释。)

答案 2 :(得分:1)

本着学习的精神,另一种方法是使用带注释的类而不是以方法或字段为目标。 首先使用您需要的方法和保留策略到运行时

声明您的接口
import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
public @interface Test_Target {
   public String doTestTarget() default "default string";
}

然后注释为您的类创建的接口。从你的班级找到带注释的类,然后用它调用方法。

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;

@Test_Target(doTestTarget="Hello World !")
public class TestAnnotations {

public static void main(String[] args) throws Exception 
{      
    AnnotatedElement c = TestAnnotations.class;
    if(c.isAnnotationPresent(Test_Target.class))
    {
        Annotation singleAnnotation = c.getAnnotation(Test_Target.class);
        Test_Target tt = (Test_Target) singleAnnotation;
        System.out.println(tt.doTestTarget());
    }       
}

}

结果是: Hello World!