Creating Custom Annotations

Authors
  • Amit Shekhar
    Name
    Amit Shekhar
    Published on
Creating Custom Annotations

I am Amit Shekhar, a mentor helping developers in getting high-paying tech jobs.

In this blog, we will learn how to create custom annotations in Java.

Annotations are Metadata.

And Metadata is a set of data that gives information about other data.

So in this case, annotations are essentially just information about your code.

@Override
public String toString() {
    return "I am Amit Shekhar";
}

Here, you have @Override annotation over the method toString(). Even if you don’t put the @Override annotation, this code will still work fine.

So, what is the use of @Override annotation here?

@Override tells the compiler that this method is an overridden method (metadata about the method) and whether any such method exists in its parent class. Then it throws a compiler error (the method does not override a method from its super class).

Look at the below code. It will not compile, as there is typo error: "toStrring" instead of "toString".

@Override
public String toStrring() {
    return "I am Amit Shekhar";
}

But it will compile, if there is you don’t add an @Override annotation.

Creating custom annotations

For Example, Let’s create @Status annotation

Create a Status interface like below:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Status {
    public enum Priority {LOW, MEDIUM, HIGH}
    Priority priority() default Priority.LOW;
    String author() default "Amit";
    int completion() default 0;
}

@Target specifies where an annotation can be placed. If you don’t specify this, the annotation can be placed anywhere. Here are some valid targets:

  • ElementType.TYPE (class, interface, enum)
  • ElementType.FIELD (instance variable)
  • ElementType.METHOD
  • ElementType.PARAMETER
  • ElementType.CONSTRUCTOR
  • ElementType.LOCAL_VARIABLE

@Retention defines how long the annotation should be kept around. Here are some valid retention policies:

  • RetentionPolicy.SOURCE — Discard during the compile step. These annotations don’t make any sense after the compilation has completed, so they don’t need to be turned into bytecode. Examples: @Override, @SuppressWarnings
  • RetentionPolicy.CLASS — Discard during the class load. Useful when doing bytecode-level post-processing. Somewhat surprisingly, this is the default.
  • RetentionPolicy.RUNTIME — Don’t discard. This annotation should be available for reflection at runtime.

Using annotations in your Class Foo.java:

@Status(priority = STATUS.Priority.MEDIUM, author = "Amit Shekhar", completion = 0)
public void methodOne() {
    //no code
}
@Status(priority = STATUS.Priority.HIGH, author = "Amit Shekhar", completion = 100)
public void methodTwo() {
    //complete code
}

Now you can print the status of all the methods like below:

Class foo = Foo.class;
for(Method method : foo.getMethods()) {
    Status statusAnnotation = (Status)method.getAnnotation(Status.class);
    if(statusAnnotation != null) {
        System.out.println(" Method Name : " + method.getName());
        System.out.println(" Author : " + statusAnnotation.author());
        System.out.println(" Priority : " + statusAnnotation.priority());
        System.out.println(" Completion Status : " + statusAnnotation.completion());
    }
}

If you have only one attribute inside an annotation, it should be named "value" and can be used without attribute name while using it:

@interface Status{
    int value();
}
@Status(50)
public void someMethod() {
    //few codes
}

And that’s how you create custom annotations.

Master Kotlin Coroutines from here: Mastering Kotlin Coroutines

That's it for now.

Thanks

Amit Shekhar

You can connect with me on:

Read all of my high-quality blogs here.