开发者

Understanding annotation in Java

I was trying to go through some online material to learn annotation in java.

In the following code, what happened to my dear "Hello world" string which I passed in this line: @Test_Target(doTestTarget="Hello World !")?

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

above is the annotation defined and below is its usage

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");
   }
}

When I run this code it is only printing Testing Target annotation

Please help me out, I am completely new to annotation.


Annotations are basically bits of data you can attach to fields, methods, classes, etc.

The syntax for declaring annotations in Java is a little awkward. They look a bit like interfaces (they are, after all, declared with @interface), but they aren't really interfaces. I think you might have put the doTestTarget() method in your TestAnnotations class because you thought your annotation was an interface and you needed to implement it. This isn't true - you can delete this method and the call to it from your code if you wish and doing so won't cause you any problems.

Also, you might not have intended to put the annotation on the field str. Annotations apply only to what immediately follows them. As a result, your code doesn't compile, because you've applied your annotation to a field but declared that your annotation can only be applied to methods. Change @Target(ElementType.METHOD) to @Target(ElementType.FIELD) and your code should then compile.

As for what happens to the string Hello World !, it gets written to the .class file and is available to any tool that reads in Java classes. However, it wouldn't necessarily be available in the JVM at runtime. This happens because you didn't specify a @Retention for your @Test_Target annotation. The default value for @Retention is RetentionPolicy.CLASS, which means that the JVM might not bother to load them out of the class file. (See the Javadoc for the RetentionPolicy enum.)

I imagine you want to see some way of reading the value out of this annotation at runtime. If so, I'd recommend adding @Retention(RetentionPolicy.RUNTIME) to your annotation to make sure it will be available at runtime.

To access your annotation and the value contained within it at runtime, you need to use reflection. I've rewritten your TestAnnotations class as follows to give a quick demonstration:

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

When I run this code, it gives me the following output:

Hello World !


In principle, adding an annotation by itself does not fundamentally alter the programs behaviour.

In your case, you created a new annotation type @Test_Target, which can by used on any method (as indicated by its @Target annotation).

Then you applied this not to a method, but to the str field (which should give a compiler error, I think).

Independently of this, you are creating an object with a doTestTarget method, and invoke it, and get the expected result (i.e. the method is executed).

If you want your annotation to do something more than simply be there and provide some information for the reader of the source, you have to use it - either with an annotation processor at compile time, or using reflection on run time (then you would need also @Retention(RUNTIME) as an annotation on Test_Target.)


In the spirit of learning, another way is to use the annotated class without targeting a method or field. First declare your interface with the method you need and Retention Policy to Runtime

import java.lang.annotation.*;

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

then annotate the interface created to your class. From your class find the annotated class and then call the method with it.

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

}

the result is: Hello World !

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜