Java Annotations

Java annotations are a powerful feature that allows you to add metadata to your code. Annotations provide a way to associate additional information with classes, methods, fields, or other program elements without changing their actual behavior. They are widely used in frameworks such as Spring, Hibernate, and Java Persistence API (JPA) for various purposes like configuration, validation, and dependency injection.


What are Java Annotations?

In Java, annotations are special markers that provide metadata about the program but do not affect the program's execution. Annotations are used for a variety of purposes, such as:

  • Providing configuration information (e.g., for dependency injection).
  • Generating code automatically (e.g., in frameworks like Spring).
  • Marking methods or classes for special behavior (e.g., for testing, serialization).

Syntax of Annotations

The basic syntax for an annotation is:

@AnnotationName
public class MyClass {
    // Class implementation
}

An annotation is preceded by the @ symbol and followed by the annotation name.


Built-in Java Annotations

Java provides several built-in annotations that are commonly used in various situations. Here are some of the most frequently used annotations:

1. @Override

The @Override annotation is used to indicate that a method is intended to override a method in a superclass. It helps ensure that the method is properly overridden and that the superclass method exists.

Example Code:

class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}

In this example, the @Override annotation ensures that the sound() method in the Dog class is overriding the sound() method in the Animal class.

2. @Deprecated

The @Deprecated annotation marks a method, class, or field as deprecated. This signals to the developers that the element should no longer be used, and there may be a better alternative.

Example Code:

public class MyOldClass {
    @Deprecated
    public void oldMethod() {
        System.out.println("This method is deprecated.");
    }
}

Using the @Deprecated annotation notifies developers that they should avoid using oldMethod() in favor of a newer, preferred method.

3. @SuppressWarnings

The @SuppressWarnings annotation is used to instruct the compiler to suppress specific types of warnings. This is useful when you know that the warning is harmless or that you are handling the issue in another way.

Example Code:

@SuppressWarnings("unchecked")
public class MyClass {
    public void myMethod() {
        List rawList = new ArrayList();  // Compiler will show an unchecked warning
        rawList.add("item");
    }
}

Here, the @SuppressWarnings("unchecked") annotation prevents the compiler from showing a warning about unchecked type casting.


Creating Custom Annotations in Java

Java allows you to create your own custom annotations. Custom annotations can be used to define specific metadata for your application.

Syntax for Custom Annotations

To create an annotation, use the @interface keyword:

public @interface MyAnnotation {
    String value() default "default value"; // Optional element with a default value
}

Example Code: Custom Annotation

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyCustomAnnotation {
    String description() default "No description";
    int version() default 1;
}

public class MyClass {
    @MyCustomAnnotation(description = "This is a custom annotation", version = 2)
    public void myMethod() {
        System.out.println("Method with custom annotation");
    }
}

Explanation:

  • @Retention(RetentionPolicy.RUNTIME): Specifies that the annotation will be available at runtime.
  • @Target(ElementType.METHOD): Specifies that the annotation can only be applied to methods.
  • description() and version() are elements of the annotation, with default values.

You can then retrieve this annotation and its elements using reflection.


Accessing Annotations via Reflection

Java provides reflection to inspect and retrieve annotations at runtime. You can use the getAnnotation() method of the Class or Method object to access the annotation and its values.

Example Code: Accessing Custom Annotation

import java.lang.annotation.*;
import java.lang.reflect.Method;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyCustomAnnotation {
    String description() default "No description";
    int version() default 1;
}

public class MyClass {
    @MyCustomAnnotation(description = "This method is annotated", version = 2)
    public void myMethod() {
        System.out.println("Method with custom annotation");
    }

    public static void main(String[] args) throws Exception {
        Method method = MyClass.class.getMethod("myMethod");
        if (method.isAnnotationPresent(MyCustomAnnotation.class)) {
            MyCustomAnnotation annotation = method.getAnnotation(MyCustomAnnotation.class);
            System.out.println("Description: " + annotation.description());
            System.out.println("Version: " + annotation.version());
        }
    }
}

Output:

Description: This method is annotated
Version: 2

In this example:

  • We define a custom annotation MyCustomAnnotation.
  • We apply it to the myMethod() method.
  • We use reflection to access the annotation and print its values at runtime.

Retention Policies for Annotations

Java annotations have a @Retention policy that defines how long the annotation is retained. There are three main retention policies:

  1. SOURCE: The annotation is discarded by the compiler and is not retained in the class files.
  2. CLASS: The annotation is recorded in the class file but is not available at runtime.
  3. RUNTIME: The annotation is available at runtime and can be accessed via reflection.

Example Code: Using Retention Policies

@Retention(RetentionPolicy.RUNTIME)
public @interface RuntimeAnnotation {
    String value() default "runtime annotation";
}
In this case, the RuntimeAnnotation will be available at runtime because of the RUNTIME retention policy.