Custom Annotation in Java | Example Program

Creating your own annotation is called custom annotation or user-defined annotation in java.

It is very easy and more interesting to create your own annotation than using core java or third-party annotations.

A custom annotation is declared by using the @interface element. In Java, a type of annotation is an interface, except that we must add @ sign before the interface keyword when declaring it.

The general syntax to declare a custom annotation in java is as follows:

public @interface CustomAnnotation {
}
For example:
public @interface MyAnnotation { }

In the above syntax, MyAnnotation is the name of custom annotation. By default, all annotation types extend java.lang.annotation.Annotation interface implicitly or explicitly.

Rules for Creating Custom Annotation Signature in Java


There are the following few points that must be remembered by the programmer when declaring custom annotation.

1. The method must not have any throws clauses.

2. Method should return one of the following data types:

  • primitive data types
  • String
  • Class
  • enum
  • array

3. Method should not have any parameter in the method definition.

4. We should add @ sign just before the interface keyword to define custom annotation.

5. It may assign a default value to the method.

Declaring, Applying, and Accessing Your Own Custom Annotation


Let’s take a simple example program where we will create, apply, and access custom annotation. In this program, we will display members of annotation associated with a method.

Look at the following source code to understand better.

Program source code 1:

package annotationsProgram;
// Creating custom annotation type called Student.
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Student 
{
  String firstName();
  String lastName();
  int rollNo();
}
package annotationsProgram;
// Applying annotation.
public class Hello 
{
// Importing annotation on a method display().
@Student(firstName = "Ivaan", lastName = "Sagar", rollNo = 20)
public void display()
{
    System.out.println("Hello annotation");	
 }
}
package annotationsProgram;
import java.lang.reflect.Method;
// Acceessing annotation
public class TestCustomAnnotation 
{
public static void main(String[] args) throws NoSuchMethodException, SecurityException 
{
   Hello h = new Hello(); // Creating object of class Hello.
   h.display(); // Calling method of Hello class. 
   Method m = h.getClass().getMethod("display"); 
   Student st = m.getAnnotation(Student.class);
 
   System.out.println("First name: " +st.firstName());
   System.out.println("Last name: " +st.lastName());
   System.out.println("Roll number: " +st.rollNo());
 }
}
Output:
         Hello annotation
         First name: Ivaan
         Last name: Sagar
         Roll number: 20

1. In this program, @Documented annotation has been used to appear annotation in the documentation generated by javadoc tool.

2. Annotation with a retention policy of RUNTIME has been used to specify that annotation instances are retained in the .class file during compilation and will be available for reading at runtime.

3. Every annotation begins with the @interface keyword followed by the name of annotation type that is Student in this program.

4. Within the curly braces, methods like firstName(), lastName(), and rollNo() are declared to define annotation data.

5. We have created a class Hello where we have imported annotation on the display() method.

6. Now, we created another class TestCustomAnnotation where we have created an object of class Hello and accessing display() method.

7. The getClass() method provided by Object class returns the Class object that represents invoking object. The general syntax to declare getClass method is as follows:

final Class getClass;

After obtaining a Class object, we need to use its methods to get information about the various elements declared by the class, including its annotation.

To obtain annotations associated with a particular element (such as method, field, constructor) declared within a class, we must first obtain an object that represents that element.

8. For example, to obtain annotations associated with a method in the above program, we have obtained a Class object that represents the class and then called getMethod() on that Class object, specifying the name of the object.

The general syntax of getMethod is as follows:

Method getMethod(String methodName, Class...parameterTypes)

The name of method is passed in String form in methodName. If the method has parameters as arguments, Class objects representing those types must also be specified by parameterTypes.

Here, parameterTypes is a varargs parameters. It means that we can declare as many parameter types as needed, including zero.

The getMethod() method returns a Method object that represents the method. If the method is not found, an exception NoSuchMethodException is thrown.

Similarly, getField() and getConstructor() methods obtain the information about field and constructor, respectively. These methods return objects of type Field and Constructor.

9. We have used getAnnotation() method to obtain a specific annotation associated with the Method object. The general syntax to define getAnnotation() method is as follows:

Annotation getAnnotation(Class annotationType)

In the above syntax, annotationType is a Class object that represents the annotation in which we are interested. The getAnnotation() method returns a reference to the annotation.

Using this reference, we have obtained values associated with members of annotation. If the annotation is not found, this method returns a null value.

10. Similarly to the Method object, we can also obtain the information about specific annotation associated with a Class, Field, or Constructor object by calling the getAnnotation() method.


2. Let’s take another example program where we will display members of annotation associated with a method.

Program source code 2:

package annotationsProgram;
// Creating custom annotation.
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
 String str();
 int value();
}
package annotationsProgram;
import java.lang.reflect.Method;
public class Hello {
@MyAnnotation(str = "Annotation Example", value = 02)
public static void display() throws NoSuchMethodException, SecurityException
{
    System.out.println("Hello annotation");
    Hello h = new Hello();

// Obtaining annotation for this method and displaying values of members of this annotation. 
// For this, create a Class object that represents this class.
     Class c = h.getClass();

// Now, create a Method object that represents this method. 
     Method m = c.getMethod("display");
   
// Next, get the annotation for the class Hello.
     MyAnnotation myanno = m.getAnnotation(MyAnnotation.class);
   
// Finally, display values of members of annotation. 
     System.out.println(myanno.str()+ " " +myanno.value());
  }
}
package annotationsProgram;
public class TestCustomAnnotation {
public static void main(String[] args) throws NoSuchMethodException, SecurityException
{
 Hello.display();
 }
}
Output:
           Hello annotation
           Annotation Example 2

In both preceding examples, the display() method has no parameters. Thus, when display() method was called, only the name of display() method was passed.


Let’s create a slightly different program where we will create a method that has parameters. In this case, we must specify Class objects representing types of those parameters as arguments to getMethod().

Program source code 3:

package annotationsProgram;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation 
{
   String str();
   int value();
}
package annotationsProgram;
import java.lang.reflect.Method;
public class Hello 
{
// MyAnnotation now has two arguments.  	
@MyAnnotation(str = "Two parameters", value = 20)
public static void display(String str, int i) throws NoSuchMethodException, SecurityException
{
   System.out.println("Hello annotation");
   Hello h = new Hello();
   Class c = h.getClass();
// Here, parameters types are defined. 
     Method m = c.getMethod("display", String.class, int.class);

     MyAnnotation myanno = m.getAnnotation(MyAnnotation.class); 
     System.out.println(myanno.str()+ " " +myanno.value());
 }
}
package annotationsProgram;
public class TestCustomAnnotation {
public static void main(String[] args) throws NoSuchMethodException, SecurityException
{
   Hello.display("test", 10);
 }
}
Output:
         Hello annotation
         Two parameters 20

In this example program, the display() method takes String and int parameters. Therefore, Class objects representing String and int are passed as additional arguments.

Obtaining All Annotations in Java


We can get all annotations that have RUNTIME retention that is associated with an element by invoking getAnnotations() method on that element.

The general syntax to declare getAnnotations() method is as follows:

Annotation[ ] getAnnotations();

The getAnnotations() method returns an array of annotation objects. This method can be called on objects of type Class, Field, Constructor, and Method.


Note: Annotation is the super interface of all annotation interfaces and it overrides toString() method of the Object class. The toString() method is called to produce a string that describes annotation.

Let’s create a program where we will get all annotations associated with a class and a method. In this program, we will use two annotations that will be used to annotate a class and a method.

Program source code 4:

package annotationsProgram;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 
{
   String str();
   int value();
}
package annotationsProgram;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation2 
{
    String description();
}
package annotationsProgram;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@MyAnnotation1(str = "Hello", value = 100)
@MyAnnotation2(description = "An annotation associated with a class")
public class Hello 
{  	
@MyAnnotation1(str = "display", value = 200)
@MyAnnotation2(description = "An annotation associated with a method")
public static void display() throws NoSuchMethodException, SecurityException
{
  System.out.println("Hello all annotations");
  Hello h = new Hello();
  Class c = h.getClass(); 
  Annotation[ ] myannos = c.getAnnotations(); 
  
// Display all annotations for Hello.
     System.out.println("All annotations associated with a class Hello:");
     for(Annotation a : myannos)
	      System.out.println(a);  
     System.out.println();

// Displaying all annotations associated with a method display().
     Method m = h.getClass().getMethod("display");
         myannos = m.getAnnotations();
      System.out.println("All annotations associated with method display: ");
      for(Annotation a : myannos)
	      System.out.println(a);
 }
}
package annotationsProgram;
public class TestCustomAnnotation {
public static void main(String[ ] args) throws NoSuchMethodException, SecurityException
{
    Hello.display();
 }
}
Output:
         Hello all annotations
         All annotations associated with a class Hello:
         @annotationsProgram.MyAnnotation1(str=Hello, value=100)
         @annotationsProgram.MyAnnotation2(description=An annotation associated with a class)

         All annotations associated with method display: 
         @annotationsProgram.MyAnnotation1(str=display, value=200)
         @annotationsProgram.MyAnnotation2(description=An annotation associated with a method)

In this program, we have used getAnnotations() method to get an array of all annotations associated with Hello class and with display() method.


Hope that this tutorial has covered almost all the important points related to how to create custom annotation in java with example programs. I hope that you will have understood the basic concepts of creating custom annotation in java.
Thanks for reading!!!