How to create your own annotations in Java

This is a practical tutorial, where you will learn how you can create your own custom annotation types in your Java program. But also an introduction into the Java annotation package, which can be useful for you.

In Java you have annotations such as “@Override”, “@Id” and more. These are used to adjust the behavior of objects, functions and more.
But you can also create your own annotation (annotation type), where you can define what the annotation should do on the target (objects, functions, etc.) where it’s called.
An annotation type is created through a special Java interface class with the identifier “@interface”.

Annotation without an attribute


public @interface MyCustomAnnotation {}

You can use your created annotation type like this:

private String myVariable;

In this example the annotation does not have any attributes. But you can also do that, which we will see in the following sections.

Annotation with one attribute

public @interface CurrentDegreesCity {	String cityName();}

Annotation type must not be “public” like in this example. They can also have other access modifiers (levels) than “public”.

This annotation can be called like this:

private int deegresSeoul;

You can only pass one attribute. But if you pass a different amount of attributes, then you will get a compiler error. If you want that, then you have to extend the interface “CurrentDegreesCity” with an another method declaration.

An annotation type interface cannot have members that throw an exception or have a “void” return value. This will cause a compiler error.


public @interface CurrentDegreesCity {	void cityName();}


public @interface CurrentDegreesCity {	String cityName() throws IOException;}

Annotations with attributes that contain several elements

In this example we will pass an array of string, which contains the names of weekdays.

public @interface WeekdaysDegreesCity {	String cityName();
String[] weekdays();

This annotation can be called like this:

weekdays={ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" })
private int workingWeekDeegresSeoul;

If you pass only one value to the annotation, then you can also remove the curly brackets.

@CurrentDegreesCity(cityName="seoul", weekdays="Monday")
private int workingWeekDeegresSeoul;

Annotations with optional attributes


public @interface CurrentWeatherCity {String cityName() default "New York";}

This annotation can be called like this:

private String currentWeatherNewYork;

The default value “New York” will be used in this case.

Meta annotations


This defines where your annotation can be used. For example only on constructors, local variables, etc.


public @interface CurrentWeatherCity {

In this example you can use this annotation only on “static” (class) variables and object variables.

All available values:

  • ANNOTATION_TYPE — Only on other annotations
  • TYPE — Only on all type declarations. Classes, Interfaces, Enums, etc.
  • CONSTRUCTOR — Only on constructors
  • METHOD — Only on static and non-static methods
  • FIELD — Only on static variables and object variables
  • PARAMETER — Only on parameter variables
  • LOCAL_VARIABLE — Only on local variables
  • PACKAGE — Only on package declarations

Annotations can be used everywhere by default. These values are defined in the class “ElementType”.

If you want to pass only one value, then you must call this annotation like this:

@Target( value = FIELD )
public @interface CurrentWeatherCity {

Or like this:

@Target( ElementType.FIELD )
public @interface CurrentWeatherCity {

This must be also done on other meta annotations.


This controls till when the annotations are available. The available values belong to the class “java.lang.annotation.RetentionPolicy”.

@Retention( RetentionPolicy.RUNTIME )
public @interface CurrentWeatherCity {

In this example the annotation is available everywhere and also during runtime of the application.

This values are available:

  • SOURCE — Available only in the source code and it will be discarded by the compiler before the compiling process.
  • CLASS — Available in the class file. But it is not available in the runtime environment.
  • RUNTIME — Available in the class file and in the runtime environment. Annotation are available everywhere.

The default value is “CLASS”.


This means that this annotation will be mentioned in the documentation “Javadoc”. Annotations are not included in the “Javadoc” by default.

public @interface CurrentWeatherCity {


This means that the annotation for a super class can be inherited by the sub class.

This is used when the annotation is used on a class.
When that specific annotation is requested in the sub class and it does not exist there. Then the super class will be checked and the annotation from the super class will be returned.


@interface LoadWeather {
public class SimpleWeatherState {


This means that the annotation can be repeated. You can make it possible that your annotation can be used multiple times on the same target (object, function, etc.) in a certain class.

@interface CurrentWeatherCity {
String cityName() default "New York";

This annotation can be repeated like this in the class “MyJavaClass”:


This was an introduction into creating your own annotations and the Java package “java.lang.annotation”.

More about Java Annotations in Java 15:

More about Java Annotations in Java 8:

Tutorials about Linux, Java and information about IT —

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store