Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 976
Anupam Gupta Avatar asked Apr 16 '11 10:04

Anupam Gupta


People also ask

What is annotation in Java with example?

In the Java computer programming language, an annotation is a form of syntactic metadata that can be added to Java source code. Classes, methods, variables, parameters and Java packages may be annotated. Like Javadoc tags, Java annotations can be read from source files.

What does annotate mean in Java?

Java annotations are metadata (data about data) for our program source code. They provide additional information about the program to the compiler but are not part of the program itself. These annotations do not affect the execution of the compiled program. Annotations start with @ .

What is @retention annotation in spring boot?

@Retention : Specifies whether the annotation metadata can be accessed at runtime by the application (will determine whether the compiled bytecode is affected).


3 Answers

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 !
like image 66
Luke Woodward Avatar answered Oct 04 '22 04:10

Luke Woodward


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.)

like image 37
Paŭlo Ebermann Avatar answered Oct 04 '22 04:10

Paŭlo Ebermann


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 !

like image 32
fzonin Avatar answered Oct 04 '22 03:10

fzonin