Custom Annotations in Java

Himani Prasad
4 min readApr 1, 2023
Photo by mauRÍCIO SANTOS on Unsplash

Annotations have become an essential part of modern programming, allowing developers to add metadata to their code that can be used for a variety of purposes, such as generating documentation, configuring frameworks, and enforcing constraints.

Annotations are a powerful tool for developers, but what happens when you need to create your own custom annotations? While there are plenty of built-in annotations available in Java, there are situations where you may need to define your own custom annotations to meet specific requirements or to add extra functionality to your code.

Creating custom annotations may seem like a daunting task, but once you understand the basics, you’ll be amazed at the power and flexibility they can bring to your code. So let’s dive in and explore the world of custom annotations, from the basics of creating them to the advanced concepts of using annotation processors. By the end of this article, you’ll have a solid understanding of custom annotations and how they can benefit your development process.

Definition of custom annotations

Annotations are like little sticky notes that you can attach to different parts of your Java code, such as classes, methods, and fields. They contain metadata that provides additional information about these elements. Now, imagine that you could create your own sticky notes with custom messages that fit your needs. That’s exactly what a custom annotation is!

Custom annotations are a powerful way to add your own metadata to your code. They allow you to clearly express your intent and make your code more self-documenting. By adding custom annotations to your code, you can provide important information to other developers who might work on your code in the future. For example, you might create a custom annotation that marks a method as being deprecated, defines a specific behavior for a class.

Creating a custom annotation

To create a custom annotation, you need to define a new annotation type.

Syntax of creating an annotation

The syntax for creating an annotation is similar to that of creating an interface, with the @interface keyword followed by the name of the annotation type. In the example above, the annotation type is named MyAnnotation.

import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String value();
}

How to specify properties for the annotation

You can add properties to your custom annotation type by defining methods in the annotation interface. Properties are defined using the same syntax as methods in a Java interface, but without any parameters or a return type. In the example above, the property is named value().

Restrictions on properties

There are some restrictions on the types of properties that you can define in an annotation type. For example, properties cannot be arrays or generic types. Additionally, the types of properties must be one of the following: byte, char, short, int, long, float, double, boolean, String, Class, enum, or another annotation type.

Annotation Retention Policies

Retention policies specify how long an annotation is retained. Java supports three different retention policies: RUNTIME, CLASS, and SOURCE.

Definition of retention policies

The @Retention annotation is used to specify the retention policy for a custom annotation. The @Retention annotation takes a single argument, which is one of the three retention policies.

Types of retention policies (RUNTIME, CLASS, SOURCE)

  • RUNTIME: retained at runtime and can be queried via reflection. This means that the annotation information is available at runtime when the code is executed.
  • CLASS: retained in the class file, but are not available at runtime. This means that the annotation information is not available at runtime, but it can be used by other tools or libraries that analyze the code.
  • SOURCE: only retained in the source code and are discarded during compilation. This means that the annotation information is only used during the compilation process, but it is not included in the compiled code.

Annotation Target Types

Target types specify where an annotation can be used in your code. Java supports eight different target types: TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, and PACKAGE.

Annotation Processors

Annotation processors are tools that can process annotations and generate code based on them. Annotation processors can be used to automate repetitive tasks, such as generating boilerplate code.

To create an annotation processor, we need to implement the javax.annotation.processing.Processor interface. The Processor interface has several methods that we must implement, including process(), which is called for each annotation that we want to process.

Here is an example of an annotation processor:

public class CustomAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element element : roundEnv.getElementsAnnotatedWith(CustomAnnotation.class)) {
// process the annotated element
}
return true;
}
}

In the above example, we have created an annotation processor called CustomAnnotationProcessor. The processor extends the javax.annotation.processing.AbstractProcessor class, which provides a default implementation for some of the Processor interface methods.

--

--