How do I obtain annotations at runtime using reflection?

This example demonstrate how to obtain annotations of a class and methods. We use the reflection API to get class and method information from where we can read information about annotation attached to the class or the method.

package org.kodejava.lang.annotation;

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

@HelloAnnotation(value = "Hello", greetTo = "Universe")
public class GettingAnnotation {
    public static void main(String[] args) {
        GettingAnnotation demo = new GettingAnnotation();

        Class<? extends GettingAnnotation> clazz = demo.getClass();
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("Annotation Type: " + annotation.annotationType());
        }

        HelloAnnotation annotation = clazz.getAnnotation(HelloAnnotation.class);
        System.out.println("Value  : " + annotation.value());
        System.out.println("GreetTo: " + annotation.greetTo());

        try {
            Method m = clazz.getMethod("sayHi");

            annotation = m.getAnnotation(HelloAnnotation.class);
            System.out.println("Value  : " + annotation.value());
            System.out.println("GreetTo: " + annotation.greetTo());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        demo.sayHello();
    }

    @HelloAnnotation(value = "Hi", greetTo = "Alice")
    public void sayHi() {
    }

    @HelloAnnotation(value = "Hello", greetTo = "Bob")
    public void sayHello() {
        try {
            Method method = getClass().getMethod("sayHello");
            HelloAnnotation annotation = method.getAnnotation(HelloAnnotation.class);

            System.out.println(annotation.value() + " " + annotation.greetTo());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

You can find the HelloAnnotation annotation that we use above on the following example: How do I create a simple annotation?.

The result of our program is:

Annotation Type: interface org.kodejava.lang.annotation.HelloAnnotation
Value  : Hello
GreetTo: Universe
Value  : Hi
GreetTo: Alice
Hello Bob

How do I annotate a class or method?

This example show you how to use the HelloAnnotation annotation on the previous example code, How do I create a simple annotation?. We add the HelloAnnotation annotation to our class and its methods.

package org.kodejava.lang.annotation;

@HelloAnnotation(value = "Good Morning", greetTo = "Universe")
public class HelloAnnotationExample {
    public static void main(String[] args) {
        HelloAnnotationExample hello = new HelloAnnotationExample();
        hello.sayHi();
        hello.sayHello();
    }

    @HelloAnnotation(value = "Hi there", greetTo = "Alice")
    private void sayHi() {
    }

    @HelloAnnotation(value = "Hello there", greetTo = "Bob")
    private void sayHello() {
    }
}

How do I create a simple annotation?

Metadata is a way to add some supplement information to the source code. This information is called annotation will not change how the program runs. This metadata can be used by other tools such as source code generator for instance to generate additional code at the runtime. Or it will be used by a dependency injection framework such as the Spring Framework.

The annotation can be attached to classes, methods, etc. To create an annotation we use the interface keyword and add an @ symbol in front of it. The @ symbol will tell the compiler that it is an annotation.

So now let us see the code for a simple annotation, a HelloAnnotation.

package org.kodejava.lang.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface HelloAnnotation {
    String value();

    String greetTo();
}

All annotations extend the java.lang.annotation.Annotation interface, which means that java.lang.annotation.Annotation is the super-interface of all annotations

An annotation need to have a RetentionPolicy that will be the scope of the annotation where at this point the annotation will be ignored or discarded. The values are RetentionPolicy.SOURCE, RetentionPolicy.CLASS and RetentionPolicy.RUNTIME. When no retention policy defined it will use the default retention policy which is the RetentionPolicy.CLASS.

Annotation with RetentionPolicy.SOURCE retention policy will be retained only in the source code, it is available to the compiler when it compiles the class and will be discarded after that. The RetentionPolicy.CLASS retention policy will make the annotation stored in the class file during compilation, but will not available during the runtime. And the RetentionPolicy.RUNTIME retention policy will store the annotation in the class file during compilation, and it is also available to JVM at runtime.

In the example above you also see that the HelloAnnotation have two members value() and greetTo(). Annotations only have method declaration in it with no implementation body.

How do I create JSpinner component with hour value?

This example shows you how to create a JSpinner that allow you to select an hour value. As the spinner model we are using the SpinnerDateModel and set the calendar field to Calendar.HOUR_OF_DAY.

To correctly display the hour value on the spinner we also change the formatter of the spinner’s text field using SimpleDateFormatter class.

package org.kodejava.swing;

import javax.swing.*;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.DateFormatter;
import java.awt.*;
import java.util.Date;
import java.util.Calendar;
import java.text.SimpleDateFormat;

public class JSpinnerHour extends JFrame {
    public JSpinnerHour() {
        initializeUI();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(
                () -> new JSpinnerHour().setVisible(true));
    }

    private void initializeUI() {
        setSize(500, 500);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        // The following spinner model will have current date as its
        // value and using hour of day as the calendar field. The start
        // and end comparable has a null values which mean it doesn't
        // have minimum or maximum value.
        SpinnerDateModel model = new SpinnerDateModel(new Date(), null,
                null, Calendar.HOUR_OF_DAY);

        JSpinner spinner = new JSpinner(model);

        // Reformat the display of our spinner to show only the hour
        // and minute information part.
        JFormattedTextField textField =
                ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
        DefaultFormatterFactory dff =
                (DefaultFormatterFactory) textField.getFormatterFactory();
        DateFormatter formatter = (DateFormatter) dff.getDefaultFormatter();
        formatter.setFormat(new SimpleDateFormat("hh:mm a"));

        getContentPane().add(spinner, BorderLayout.NORTH);
    }
}

How do I create JSpinner component with date value?

The SpinnerDateModel allow us to display and select date information from the JSpinner component. By default, the initial value of the model will be set to the current date. To change it we can call the setValue method of the JSpinner object.

package org.kodejava.swing;

import javax.swing.*;
import java.awt.*;
import java.util.GregorianCalendar;
import java.util.Calendar;

public class JSpinnerDate extends JFrame {
    public JSpinnerDate() {
        initializeUI();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(
                () -> new JSpinnerDate().setVisible(true));
    }

    private void initializeUI() {
        setSize(500, 500);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        // Create a SpinnerDateModel with current date as the initial value.
        SpinnerDateModel model = new SpinnerDateModel();

        // Set the spinner value to October 9, 2021.
        JSpinner spinner = new JSpinner(model);
        Calendar calendar = new GregorianCalendar(2021, Calendar.OCTOBER, 9);
        spinner.setValue(calendar.getTime());

        getContentPane().add(spinner, BorderLayout.NORTH);
    }
}