Java Annotations

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 @. Its syntax is:

@AnnotationName

Let's take an example of @Override annotation.

The @Override annotation specifies that the method that has been marked with this annotation overrides the method of the superclass with the same method name, return type, and parameter list.

It is not mandatory to use @Override when overriding a method. However, if we use it, the compiler gives an error if something is wrong (such as wrong parameter type) while overriding the method.

Example 1: @Override Annotation Example

class Animal {
  public void displayInfo() {
    System.out.println("I am an animal.");
  }
}

class Dog extends Animal {
  @Override
  public void displayInfo() {
    System.out.println("I am a dog.");
  }
}

class Main {
  public static void main(String[] args) {
    Dog d1 = new Dog();
    d1.displayInfo();
  }
}

Output

I am a dog.

In this example, the method displayInfo() is present in both the superclass Animal and subclass Dog. When this method is called, the method of the subclass is called instead of the method in the superclass.


Annotation formats

Annotations may also include elements (members/attributes/parameters).

1. Marker Annotations

Marker annotations do not contain members/elements. It is only used for marking a declaration.

Its syntax is:

@AnnotationName()

Since these annotations do not contain elements, parentheses can be excluded. For example,

@Override

2. Single element Annotations

A single element annotation contains only one element.

Its syntax is:

@AnnotationName(elementName = "elementValue")

If there is only one element, it is a convention to name that element as value.

@AnnotationName(value = "elementValue")

In this case, the element name can be excluded as well. The element name will be value by default.

@AnnotationName("elementValue")

3. Multiple element Annotations

These annotations contain multiple elements separated by commas.

Its syntax is:

@AnnotationName(element1 = "value1", element2 = "value2")

Annotation placement

Any declaration can be marked with annotation by placing it above that declaration. As of Java 8, annotations can also be placed before a type.

1. Above declarations

As mentioned above, Java annotations can be placed above class, method, interface, field, and other program element declarations.

Example 2: @SuppressWarnings Annotation Example

import java.util.*;

class Main {
  @SuppressWarnings("unchecked")
  static void wordsList() {
    ArrayList wordList = new ArrayList<>();

// This causes an unchecked warning
    wordList.add("programiz"); 

    System.out.println("Word list => " + wordList);
  }

  public static void main(String args[]) {
    wordsList();
  }
}

Output

Word list => [programiz]

If the above program is compiled without using the @SuppressWarnings("unchecked") annotation, the compiler will still compile the program but it will give warnings like:

Main.java uses unchecked or unsafe operations.
Word list => [programiz]

We are getting the warning

Main.java uses unchecked or unsafe operations

because of the following statement.

ArrayList wordList = new ArrayList<>();

This is because we haven't defined the generic type of the array list. We can fix this warning by specifying generics inside angle brackets <>.

ArrayList<String> wordList = new ArrayList<>();

2. Type annotations

Before Java 8, annotations could be applied to declarations only. Now, type annotations can be used as well. This means that we can place annotations wherever we use a type.

Constructor invocations

new @Readonly ArrayList<>()

Type definitions

@NonNull String str;

This declaration specifies non-null variable str of type String to avoid NullPointerException.

@NonNull List<String> newList;

This declaration specifies a non-null list of type String.

List<@NonNull String> newList;

This declaration specifies a list of non-null values of type String.

Type casts

newStr = (@NonNull String) str;

extends and implements clause

class Warning extends @Localized Message

throws clause

public String readMethod() throws @Localized IOException

Type annotations enable Java code to be analyzed better and provide even stronger type checks.


Types of Annotations

1. Predefined annotations

  1. @Deprecated
  2. @Override
  3. @SuppressWarnings
  4. @SafeVarargs
  5. @FunctionalInterface

2. Meta-annotations

  1. @Retention
  2. @Documented
  3. @Target
  4. @Inherited
  5. @Repeatable

3. Custom annotations

These annotation types are described in detail in the Java Annotation Types tutorial.


Use of Annotations

  • Compiler instructions - Annotations can be used for giving instructions to the compiler, detect errors or suppress warnings. The built-in annotations @Deprecated, @Override, @SuppressWarnings are used for these purposes.
  • Compile-time instructions - Compile-time instructions provided by these annotations help the software build tools to generate code, XML files and many more.
  • Runtime instructions - Some annotations can be defined to give instructions to the program at runtime. These annotations are accessed using Java Reflection.
Did you find this article helpful?