Annotations   «Prev  Next»

Metadata Annotation

Annotations are a form of metadata providing information about a program that is not part of the program itself. Annotations have no direct effect on the operation of the code they annotate. Unlike comments, which are just information for developers, annotations have a number of uses.
  1. Annotations can be used by the compiler to detect errors or suppress warnings.
    In Java SE 17, the @Override annotation serves to indicate that a method in a subclass is intended to override a method in its superclass. While not mandatory, its use is considered good practice as it aids in preventing errors by instructing the compiler to verify that the method signature in the subclass matches a method in the superclass. If no such match exists, the compiler will issue an error, thus highlighting potential mistakes early in the development process.
  2. Software Tools can process Annotation information to do something like generate code, XML files, during deployment time processing. You might be familiar with Spring annotations such as @Controller and @AutoWired.

Runtime Annotations:
Some annotations are available to be examined at runtime, but they have no effect on the runtime code.
In Java SE 17, a @Runtime annotation, or more precisely, an annotation with the RetentionPolicy.RUNTIME value, is one that is retained by the Java Virtual Machine (JVM) at runtime. This means the annotation's metadata is accessible during program execution through reflection, allowing runtime processing and examination of the code.
I will be covering the following exam objectives in the next few modules.
Annotations
  1. Describe the purpose open annotations and typical usage patterns.
  2. Apply annotations to classes and methods.
  3. Describe commonly used annotations in the JDK
  4. Declare custom annotations

What are Metadata Annotations in Java?

Metadata annotations in Java are like little descriptive tags you can stick onto your Java code, classes, methods, fields, parameters, even other annotations. Think of them as a way to provide extra information about your code, but this information isn't part of the code's logic itself.
Java annotations start with the `@` symbol, followed by the annotation name. Here's a simple example:
@Override
public String toString() {
    return "MyObject";
}

In this case, `@Override` is an annotation that tells the Java compiler that this `toString()` method is intended to override a method from its superclass. If you misspell the method name or its signature doesn't match the superclass, the compiler will catch it and give you an error. But annotations can do much more than just compiler checks. They can be processed by various tools and frameworks at compile time or runtime to influence how your code behaves.
Here's a breakdown of why they're so useful:
  • Providing Information to the Compiler: As seen with `@Override`, annotations can give the compiler instructions or help it detect errors. Other built-in annotations like `@Deprecated` (marking code as obsolete) and `@SuppressWarnings` (telling the compiler to ignore certain warnings) fall into this category.
  • Runtime Behavior Modification: Frameworks like Spring and Hibernate heavily rely on annotations. For instance, `@Autowired` in Spring tells the framework to automatically inject dependencies, and `@Entity` in Hibernate marks a class as a database table. These annotations are read and acted upon at runtime.
  • Code Generation: Some tools use annotations to generate boilerplate code. For example, Lombok uses annotations like `@Getter`, `@Setter`, and `@Data` to automatically generate corresponding methods, reducing the amount of repetitive code you need to write.
  • Documentation and Configuration: Annotations can serve as a form of documentation or configuration that can be processed by documentation generators or other utilities.


Key aspects of Java Annotations:**
  • Syntax: They always start with `@` followed by the annotation name. They can also include elements (name-value pairs) within parentheses:
    @MyAnnotation(value = "some info", count = 5)`. 
    
    If an annotation has only one element named "value", you can often omit the "value =" part: @MyAnnotation("some info").
  • Retention Policy: This determines how long the annotation is available. It can be one of three values from the java.lang.annotation.RetentionPolicy enum:
    • `SOURCE`: The annotation is only available in the source code and is discarded by the compiler.
    • `CLASS`: The annotation is recorded in the class file by the compiler but is not available at runtime (this is the default).
    • `RUNTIME`: The annotation is recorded in the class file and is available to the JVM at runtime, allowing for reflection-based processing.
  • Target: This specifies the types of program elements that the annotation can be applied to. It's defined using the `java.lang.annotation.Target` annotation and can include types like `TYPE` (class, interface, enum), `METHOD`, `FIELD`, `PARAMETER`, `CONSTRUCTOR`, etc.

    In essence, metadata annotations in Java provide a powerful and flexible way to add declarative information to your code, enabling various tools and frameworks to operate more intelligently and reducing the need for verbose, imperative code.** They are a cornerstone of many modern Java development practices.



    Example of Metadata Annotation using Java 22

    Give an Example of a Metadata Annotation using Java SE 22.
    In Java SE 22, a metadata annotation is essentially a custom annotation used to attach information (metadata) to Java code elements such as classes, methods, fields, etc. This metadata can then be accessed at **compile time** or **runtime** using **reflection** or **annotation processors**.
    βœ… Example: Creating and Using a Metadata Annotation
    Let’s define a custom metadata annotation called `@AuthorInfo`:
    1. Define the Annotation
      import java.lang.annotation.*;
      
      @Retention(RetentionPolicy.RUNTIME)  // Make it available at runtime
      @Target({ElementType.TYPE, ElementType.METHOD}) // Apply to classes and methods
      public @interface AuthorInfo {
          String name();
          String date();
          String version() default "1.0";
      }
          

    2. Use the Annotation
      @AuthorInfo(name = "Thomas Hauck", date = "2025-04-21", version = "2.0")
      public class MyService {
      
          @AuthorInfo(name = "Thomas Hauck", date = "2025-04-21")
          public void processData() {
              System.out.println("Processing data...");
          }
      }
          

    3. Access the Metadata via Reflection
      import java.lang.reflect.Method;
      
      public class AnnotationReader {
          public static void main(String[] args) throws Exception {
              Class<MyService> clazz = MyService.class;
      
              // Read class-level annotation
              if (clazz.isAnnotationPresent(AuthorInfo.class)) {
                  AuthorInfo info = clazz.getAnnotation(AuthorInfo.class);
                  System.out.println("Class Author: " + info.name() + ", Date: " + info.date() + ", Version: " + info.version());
              }
      
              // Read method-level annotation
              Method method = clazz.getMethod("processData");
              if (method.isAnnotationPresent(AuthorInfo.class)) {
                  AuthorInfo info = method.getAnnotation(AuthorInfo.class);
                  System.out.println("Method Author: " + info.name() + ", Date: " + info.date());
              }
          }
      }
          

    πŸ“ Output
    Class Author: Thomas Hauck, Date: 2025-04-21, Version: 2.0
    Method Author: Thomas Hauck, Date: 2025-04-21
    

    πŸ” Annotation Meta-Annotations Used
    Annotation Purpose
    @Retention Specifies how long annotations are retained (e.g., runtime)
    @Target Specifies where the annotation can be used (e.g., class, method)
    @interface Used to declare a custom annotation

    SEMrush Software