Learn Java practically and Get Certified .

Popular Tutorials

Popular examples, reference materials, learn java interactively, java introduction.

  • Get Started With Java
  • Your First Java Program
  • Java Comments

Java Fundamentals

  • Java Variables and Literals
  • Java Data Types (Primitive)
  • Java Operators
  • Java Basic Input and Output
  • Java Expressions, Statements and Blocks

Java Flow Control

  • Java if...else Statement
  • Java Ternary Operator
  • Java for Loop
  • Java for-each Loop
  • Java while and do...while Loop
  • Java break Statement
  • Java continue Statement
  • Java switch Statement
  • Java Arrays
  • Java Multidimensional Arrays
  • Java Copy Arrays

Java OOP(I)

  • Java Class and Objects
  • Java Methods
  • Java Method Overloading
  • Java Constructors
  • Java Static Keyword
  • Java Strings
  • Java Access Modifiers
  • Java this Keyword
  • Java final keyword
  • Java Recursion
  • Java instanceof Operator

Java OOP(II)

Java Inheritance

Java Method Overriding

  • Java Abstract Class and Abstract Methods
  • Java Interface
  • Java Polymorphism
  • Java Encapsulation

Java OOP(III)

  • Java Nested and Inner Class
  • Java Nested Static Class
  • Java Anonymous Class
  • Java Singleton Class
  • Java enum Constructor
  • Java enum Strings
  • Java Reflection
  • Java Package
  • Java Exception Handling
  • Java Exceptions
  • Java try...catch
  • Java throw and throws
  • Java catch Multiple Exceptions
  • Java try-with-resources

Java Annotations

Java Annotation Types

  • Java Logging
  • Java Assertions
  • Java Collections Framework
  • Java Collection Interface
  • Java ArrayList
  • Java Vector
  • Java Stack Class
  • Java Queue Interface
  • Java PriorityQueue
  • Java Deque Interface
  • Java LinkedList
  • Java ArrayDeque
  • Java BlockingQueue
  • Java ArrayBlockingQueue
  • Java LinkedBlockingQueue
  • Java Map Interface
  • Java HashMap
  • Java LinkedHashMap
  • Java WeakHashMap
  • Java EnumMap
  • Java SortedMap Interface
  • Java NavigableMap Interface
  • Java TreeMap
  • Java ConcurrentMap Interface
  • Java ConcurrentHashMap
  • Java Set Interface
  • Java HashSet Class
  • Java EnumSet
  • Java LinkedHashSet
  • Java SortedSet Interface
  • Java NavigableSet Interface
  • Java TreeSet
  • Java Algorithms
  • Java Iterator Interface
  • Java ListIterator Interface

Java I/o Streams

  • Java I/O Streams
  • Java InputStream Class
  • Java OutputStream Class
  • Java FileInputStream Class
  • Java FileOutputStream Class
  • Java ByteArrayInputStream Class
  • Java ByteArrayOutputStream Class
  • Java ObjectInputStream Class
  • Java ObjectOutputStream Class
  • Java BufferedInputStream Class
  • Java BufferedOutputStream Class
  • Java PrintStream Class

Java Reader/Writer

  • Java File Class
  • Java Reader Class
  • Java Writer Class
  • Java InputStreamReader Class
  • Java OutputStreamWriter Class
  • Java FileReader Class
  • Java FileWriter Class
  • Java BufferedReader
  • Java BufferedWriter Class
  • Java StringReader Class
  • Java StringWriter Class
  • Java PrintWriter Class

Additional Topics

  • Java Keywords and Identifiers
  • Java Operator Precedence
  • Java Bitwise and Shift Operators
  • Java Scanner Class
  • Java Type Casting
  • Java Wrapper Class
  • Java autoboxing and unboxing
  • Java Lambda Expressions
  • Java Generics
  • Nested Loop in Java
  • Java Command-Line Arguments

Java Tutorials

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:

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

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:

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

2. Single element Annotations

A single element annotation contains only one element.

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

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

3. Multiple element Annotations

These annotations contain multiple elements separated by commas.

  • 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

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:

We are getting the warning

because of the following statement.

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 <> .

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

Type definitions

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

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

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

extends and implements clause

throws clause

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

Types of Annotations

1. Predefined annotations

  • @Deprecated
  • @SuppressWarnings
  • @SafeVarargs
  • @FunctionalInterface

2. Meta-annotations

  • @Documented
  • @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.

Table of Contents

  • Types of Java Annotations

Sorry about that.

Related Tutorials

Java Tutorial

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases. See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.

Annotations Basics

The format of an annotation.

In its simplest form, an annotation looks like the following:

The at sign character ( @ ) indicates to the compiler that what follows is an annotation. In the following example, the annotation's name is Override :

The annotation can include elements , which can be named or unnamed, and there are values for those elements:

If there is just one element named value , then the name can be omitted, as in:

If the annotation has no elements, then the parentheses can be omitted, as shown in the previous @Override example.

It is also possible to use multiple annotations on the same declaration:

If the annotations have the same type, then this is called a repeating annotation:

Repeating annotations are supported as of the Java SE 8 release. For more information, see Repeating Annotations .

The annotation type can be one of the types that are defined in the java.lang or java.lang.annotation packages of the Java SE API. In the previous examples, Override and SuppressWarnings are predefined Java annotations . It is also possible to define your own annotation type. The Author and Ebook annotations in the previous example are custom annotation types.

Where Annotations Can Be Used

Annotations can be applied to declarations: declarations of classes, fields, methods, and other program elements. When used on a declaration, each annotation often appears, by convention, on its own line.

As of the Java SE 8 release, annotations can also be applied to the use of types. Here are some examples:

  • Class instance creation expression: new @Interned MyObject();
  • Type cast: myString = (@NonNull String) str;
  • implements clause: class UnmodifiableList<T> implements @Readonly List<@Readonly T> { ... }
  • Thrown exception declaration: void monitorTemperature() throws @Critical TemperatureException { ... }

This form of annotation is called a type annotation . For more information, see Type Annotations and Pluggable Type Systems .

About Oracle | Contact Us | Legal Notices | Terms of Use | Your Privacy Rights

Copyright © 1995, 2022 Oracle and/or its affiliates. All rights reserved.

Javatpoint Logo

Java New Features

Java 9 features, java 8 features, java 7 features, java 4/5 features.

JavaTpoint

Java is a tag that represents the i.e. attached with class, interface, methods or fields to indicate some additional information which can be used by java compiler and JVM.

Annotations in Java are used to provide additional information, so it is an alternative option for XML and Java marker interfaces.

First, we will learn some built-in annotations then we will move on creating and using custom annotations.

There are several built-in annotations in Java. Some annotations are applied to Java code and some to other annotations.

Let's understand the built-in annotations first.

@Override annotation assures that the subclass method is overriding the parent class method. If it is not so, compile time error occurs.

Sometimes, we does the silly mistake such as spelling mistakes etc. So, it is better to mark @Override annotation that provides assurity that method is overridden.

@SuppressWarnings annotation: is used to suppress warnings issued by the compiler.

If you remove the @SuppressWarnings("unchecked") annotation, it will show warning at compile time because we are using non-generic collection.

@Deprecated annoation marks that this method is deprecated so compiler prints warning. It informs user that it may be removed in the future versions. So, it is better not to use such methods.

or Java User-defined annotations are easy to create and use. The element is used to declare an annotation. For example:

Here, MyAnnotation is the custom annotation name.

There are few points that should be remembered by the programmer.

There are three types of annotations.

An annotation that has no method, is called marker annotation. For example:

The @Override and @Deprecated are marker annotations.

An annotation that has one method, is called single-value annotation. For example:

We can provide the default value also. For example:

Let's see the code to apply the single value annotation.

The value can be anything.

An annotation that has more than one method, is called Multi-Value annotation. For example:

We can provide the default value also. For example:

Let's see the code to apply the multi-value annotation.

tag is used to specify at which type, the annotation is used.

The java.lang.annotation. enum declares many constants to specify the type of element where annotation is to be applied such as TYPE, METHOD, FIELD etc. Let's see the constants of ElementType enum:

Element Types Where the annotation can be applied
TYPE class, interface or enumeration
FIELD fields
METHOD methods
CONSTRUCTOR constructors
LOCAL_VARIABLE local variables
ANNOTATION_TYPE annotation type
PARAMETER parameter

Example to specify annoation for a class

Example to specify annotation for a class, methods or fields.

@Retention annotation is used to specify to what level annotation will be available.

RetentionPolicy Availability
RetentionPolicy.SOURCE refers to the source code, discarded during compilation. It will not be available in the compiled class.
RetentionPolicy.CLASS refers to the .class file, available to java compiler but not to JVM . It is included in the class file.
RetentionPolicy.RUNTIME refers to the runtime, available to java compiler and JVM .

Example to specify the RetentionPolicy

Example of custom annotation: creating, applying and accessing annotation.

Let's see the simple example of creating, applying and accessing annotation.

File: Test.java

How built-in annotaions are used in real scenario?

In real scenario, java programmer only need to apply annotation. He/She doesn't need to create and access annotation. Creating and Accessing annotation is performed by the implementation provider. On behalf of the annotation, java compiler or JVM performs some additional operations.

By default, annotations are not inherited to subclasses. The @Inherited annotation marks the annotation to be inherited to subclasses.

@Documented

The @Documented Marks the annotation for inclusion in the documentation.

Youtube

  • Send your Feedback to [email protected]

Help Others, Please Share

facebook

Learn Latest Tutorials

Splunk tutorial

Transact-SQL

Tumblr tutorial

Reinforcement Learning

R Programming tutorial

R Programming

RxJS tutorial

React Native

Python Design Patterns

Python Design Patterns

Python Pillow tutorial

Python Pillow

Python Turtle tutorial

Python Turtle

Keras tutorial

Preparation

Aptitude

Verbal Ability

Interview Questions

Interview Questions

Company Interview Questions

Company Questions

Trending Technologies

Artificial Intelligence

Artificial Intelligence

AWS Tutorial

Cloud Computing

Hadoop tutorial

Data Science

Angular 7 Tutorial

Machine Learning

DevOps Tutorial

B.Tech / MCA

DBMS tutorial

Data Structures

DAA tutorial

Operating System

Computer Network tutorial

Computer Network

Compiler Design tutorial

Compiler Design

Computer Organization and Architecture

Computer Organization

Discrete Mathematics Tutorial

Discrete Mathematics

Ethical Hacking

Ethical Hacking

Computer Graphics Tutorial

Computer Graphics

Software Engineering

Software Engineering

html tutorial

Web Technology

Cyber Security tutorial

Cyber Security

Automata Tutorial

C Programming

C++ tutorial

Control System

Data Mining Tutorial

Data Mining

Data Warehouse Tutorial

Data Warehouse

RSS Feed

HowToDoInJava

Complete Java Annotations Tutorial

Lokesh Gupta

October 15, 2023

An annotation is a kind of metadata in Java that can be applied to various elements of Java source code so that later some tool, debugger, or application program can take advantage of these annotations; and help analyze the program in a positive and constructive way. Just to mention, we can annotate classes, methods, variables, parameters, and packages in Java OR in one word almost everything. It is important to learn that the annotations applied on Java sourcecode are compiled into bytecode with other class members, and using reflection programmer can query this metadata information to decide the appropriate action to perform in any particular context.

In this tutorial, I am discussing all important concepts that you should keep handy with you, to make the best of this wonderful feature of Java language.

History and Overview of Java Annotations

In Java, Annotations were introduced as “A Metadata Facility” through JSR 175 . The JSR description states its purpose as :

“A metadata facility for the Java-TM Programming Language would allow classes, interfaces, fields, and methods to be marked as having particular attributes”.

We are talking about metadata multiple times. What is this metadata in the Java language context? Why do we even care about them? Let’s understand the need for metadata with an example.

Below is a source code of class that is declared as final:

Now we have ‘ final ‘ keyword in the class declaration. And the impact of this declaration is that you can’t extend this class or make a child class of it. How compiler understand this? Simply because of ‘ final ‘ keyword. Right? Well, this is called metadata.

A metadata is data about data. Metadata adds some additional flags on your actual data (i.e. in above case the class MyFinalClass), and in runtime either you or JVM who understand these flags, can utilize this metadata information to make appropriate decisions based on context.

In Java, we use the annotations to denote metadata. We can annotate classes, interfaces, methods, parameters, and even packages. We have to utilize the metadata information represented by these annotations in runtime.

Built-in Annotations in Java

Obliviously you can define your own but Java does provide some in-built annotations too for ready-made use. In this section, we will learn about these in-build annotations and their detailed usages.

Before moving ahead, it’s important to remember that annotations are metadata and they can be applied to any part of the source code and even to other annotations as well. I will start by discussing annotations that should be applied to other annotations because it will make more sense when we start discussing annotations applicable to java source code.

Annotations Applied To Other Annotations

Generally below five annotations below are used inside other annotations to hint compiler how new annotation should be treated by JVM. Let’s explore these 5 annotations one by one.

This annotation specifies how the marked annotation is stored in Java runtime . Whether it is limited to source code only, embedded into the generated class file, or it will be available at runtime through reflection as well.

@Documented

This annotation indicates that new annotation should be included into java documents generated by java document generator tools.

Use @Target annotation to restrict the usage of new annotation on certain java elements such as class, interface or methods. After specifying the targets, you will be able to use the new annotation on given elements only.

When you apply this annotation to any other annotation i.e. @MyCustomAnnotation ; and @MyCustomAnnotation is applied of any class MyParentClass then @MyCustomAnnotation will be available to all child classes of MyParentClass as well. It essentially means that when you try to lookup the annotation @MyCustomAnnotation on any class X, then all the parent classes of X unto n level are queried for @MyCustomAnnotation ; and if annotation is present at any level then result is true, else false.

Please note that by default annotations applied on parent class are not available to child classes.

@Repeatable

By default, an annotation is applied on a java element only once. But, by any requirement, you have to apply a annotation more than once , then use @Repeatable annotation on your new annotation.

@Repeatable has been added in latest java 8 release.

Now use above annotation as below:

Annotations Applied To Java Code

So far we learned about annotation which were meant to be applied on other annotations. Now we will look at other in-built annotations which are primarily targeted towards java sourcecode elements.

This annotation checks that the annotated method is overridden method . It causes a compile time “ error ” if the annotated method is not found in one of the parent classes or implemented interfaces. Very useful annotation and I will recommend to use it frequently.

@Deprecated

Use this annotation on methods or classes which you need to mark as deprecated . Any class that will try to use this deprecated class or method, will get a compiler “ warning “.

@SuppressWarnings

This annotation instructs the compiler to suppress the compile time warnings specified in the annotation parameters. e.g. to ignore the warnings of unused class attributes and methods use @SuppressWarnings("unused") either for a given attribute or at class level for all the unused attributes and unused methods.

To see the list of all supported options to @SuppressWarnings, please refer to specific IDE reference documentation. e.g. for Eclipse refer to this complete list of values .

@SafeVarargs

Introduced in java 7, this annotation ensures that the body of the annotated method or constructor does not perform potentially unsafe operations on its varargs parameter. Applying this annotation to a method or constructor suppresses unchecked warnings about a non-reifiable variable arity (vararg) type and suppresses unchecked warnings about parameterized array creation at call sites.

@FunctionalInterface

This annotation is used to mark an interface as functional interface which are introduced in java 8. To read more about functional interfaces please follow the linked post.

Custom Annotations in Java

All of the above annotations given examples above are in-built Java annotations and you can utilize them into your source code directly. Java allows you to create your own metadata in the form of custom annotations. You can create your own annotations for specific purposes and use them as well. Let’s learn how to create custom annotations.

Creating Custom Annotations

To create a custom annotation, you must use the keyword “ @interface “. Other important things to remember while creating custom annotations are listed below:

  • Each method declaration defines an element of the annotation type.
  • Method declarations must not have any parameters or a throws clause.
  • Return types are restricted to primitives, String, Class, enums, annotations, and arrays of the preceding types.
  • Methods can have default values.

Some example custom annotation definitions and their usage can be listed as:

Using Custom Annotations

You must have got a brief idea of how annotations should be used in the above examples. Still, I am providing a more detailed example which we can later use in the next section where we will read the annotation values through reflection.

Based on the rules above listed, I have created one annotation, which has two attributes i.e. author and version. This can be applied on Java class, interface, enum OR any method only. Default values are provided to if it’s not there then also we print something.

Now to use the above annotation, all we have to do is annotate any class/interface of the method and provide the author name, and version of the file if any.

That’s all. It’s so easy to use annotations, right?

Processing Annotations Using Reflection

Till now, we have only created the annotation and then used it. The main reason we are using annotations are because they are metadata. So it means we should be able to fetch this metadata to utilize the annotation information when we need it.

In java, you have to use reflection API to access annotations on any type (i.e. class or interface) or methods. Let’s learn how to do this with an example.

Before the advent of Annotations, you don’t need to define your source code metadata outside of some properties files. Now, they can directly define this meta-data information in the source code itself. If this feature wisely (as it is used in the latest Java frameworks like Spring and Struts ), the benefits are countless.

Let’s summarize our learning from this post in some bullet points:

  • Annotations are metadata that can be applied on either annotations OR other Java elements in Java source code.
  • Annotations do not directly affect program semantics, but they do affect the way programs are treated by tools and libraries, which can in turn affect the semantics of the running program.
  • Annotations can be read from source files, class files, or reflectively at run time.
  • There are 10 in-built annotations as of today. 5 of them are meant to be applied on custom annotations and the other 5 are meant to be applied on Java source code elements. Read respective sections for more details.
  • Because annotation types are compiled and stored in byte code files just like classes, the annotations returned by these methods can be queried just like any regular Java object. You saw an example above.

That’s all for this lovely and very powerful feature i.e. Annotation. Let me know of your thoughts/queries in the comments section.

Happy Learning !!

Further reading:

  • Python Interview Questions and Answers
  • Java Concurrency Interview Questions
  • Hibernate/JPA Persistence Annotations
  • Java OOP Interview Questions with Answers
  • Java Record Type
  • Spring Boot and GraphQL Tutorial

guest

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Tutorial Series

Privacy Policy

REST API Tutorial

Java Annotations Demystified: A Comprehensive Guide to Creating and Using Custom Annotations

Introduction.

Annotations in Java are a powerful language feature that allows developers to provide metadata about their code. Introduced in Java 5, annotations are used to give hints to the compiler, document code, generate code, or configure code behavior at runtime. This blog post will explore Java annotations in depth, covering built-in annotations, creating custom annotations, and processing them using reflection or annotation processors.

Table of Contents

Understanding Java Annotations

Built-in Java Annotations 2.1. Standard Annotations 2.2. Meta-Annotations

Creating Custom Annotations

Using custom annotations.

Processing Annotations 5.1. Reflection-based Annotation Processing 5.2. Compile-time Annotation Processing

Real-World Applications of Annotations

Best practices for using annotations.

Annotations are a mechanism in Java for providing metadata about your code. They can be applied to classes, interfaces, methods, fields, parameters, and even other annotations. By attaching annotations to these elements, you can convey information to the Java compiler, runtime, other developers, or external tools.

Built-in Java Annotations

Java provides several built-in annotations, which are divided into two categories: standard annotations and meta-annotations.

Standard Annotations

These annotations are used to provide hints to the Java compiler or indicate intended code behavior:

  • @Override : Indicates that a method should override a method in a superclass or implement a method from an interface.
  • @Deprecated : Marks an element as obsolete, indicating that it should not be used anymore.
  • @SuppressWarnings : Instructs the compiler to suppress specified warnings for the annotated element.
  • @SafeVarargs : Asserts that the annotated method or constructor does not perform unsafe operations on its varargs parameter.
  • @FunctionalInterface : Indicates that an interface is intended to be a functional interface, with a single abstract method.

Meta-Annotations

Meta-annotations are used to provide metadata about other annotations:

  • @Retention : Specifies the retention policy of an annotation, determining how long the annotation is retained (source, class, or runtime).
  • @Target : Indicates the kinds of program elements that an annotation can be applied to, such as types, methods, fields, or parameters.
  • @Documented : Indicates that an annotation should be included in the generated Javadoc documentation.
  • @Inherited : Specifies that an annotation should be inherited by subclasses of the annotated class.
  • @Repeatable : Indicates that an annotation can be applied multiple times to the same element.

To create a custom annotation, define an interface with the @interface keyword. Annotation elements can be declared as methods with no parameters and a return type.

Once you have created a custom annotation, you can apply it to your code elements, such as classes, methods, or fields, depending on the specified @Target .

Processing Annotations

Annotations can be processed at runtime using reflection or at compile-time using annotation processors.

Reflection-based Annotation Processing

You can use Java reflection to inspect annotations at runtime and modify code behavior accordingly.

Compile-time Annotation Processing

Compile-time annotation processing allows you to generate code or configuration files based on annotations during compilation, using the javax.annotation.processing.Processor interface.

Annotations are widely used in various applications, including:

  • JUnit: JUnit uses annotations like @Test , @Before , and @After to define test cases and their lifecycle.
  • Spring Framework: Spring uses annotations like @Autowired , @Component , and @RequestMapping for dependency injection, component scanning, and URL mapping.
  • Java EE: Java EE uses annotations like @Entity , @Inject , and @EJB for defining persistence entities, dependency injection, and EJB components.
  • Validation frameworks: Validation frameworks, like Hibernate Validator, use annotations like @NotNull , @Size , and @Email for defining validation constraints.
  • Use annotations judiciously: Don't overuse annotations; use them when they provide clear benefits over other approaches.
  • Prefer built-in annotations: Always use built-in annotations when they suffice, and only create custom annotations when necessary.
  • Document custom annotations: Provide clear documentation for custom annotations, including their purpose, usage, and any constraints.
  • Keep annotations simple : Limit the complexity of custom annotations and their processing logic to ensure maintainability.

Java annotations offer a powerful and flexible way to attach metadata to your code and influence its behavior. By understanding built-in annotations, creating custom annotations, and processing them using reflection or annotation processors, you can harness the full potential of annotations in your Java applications. Whether you're working with testing frameworks, dependency injection, or validation, annotations can help you write cleaner, more expressive, and more maintainable code.

  • Watch & Listen
  • Oracle University

Annotations

Annotations have a number of uses, among them:

  • Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings.
  • Compile-time and deployment-time processing — Software tools can process annotation information to generate code, XML files, and so forth.
  • Runtime processing — Some annotations are available to be examined at runtime.

This section explains where annotations can be used, how to apply annotations, what predefined annotation types are available in the Java Platform, Standard Edition (Java SE API), how type annotations can be used in conjunction with pluggable type systems to write code with stronger type checking, and how to implement repeating annotations.

The Format of an Annotation

In its simplest form, an annotation looks like the following:

The at sign character ( @ ) indicates to the compiler that what follows is an annotation. In the following example, the annotation's name is Override :

The annotation can include elements , which can be named or unnamed, and there are values for those elements:

If there is just one element named value , then the name can be omitted, as in:

If the annotation has no elements, then the parentheses can be omitted, as shown in the previous @Override example.

It is also possible to use multiple annotations on the same declaration:

If the annotations have the same type, then this is called a repeating annotation:

Repeating annotations are supported as of the Java SE 8 release. For more information, see the section Repeating Annotations.

The annotation type can be one of the types that are defined in the java.lang or java.lang.annotation packages of the Java SE API. In the previous examples, Override and SuppressWarnings are predefined Java annotations. It is also possible to define your own annotation type. The Author and Ebook annotations in the previous example are custom annotation types.

Where Annotations Can Be Used

Annotations can be applied to declarations: declarations of classes, fields, methods, and other program elements. When used on a declaration, each annotation often appears, by convention, on its own line.

As of the Java SE 8 release, annotations can also be applied to the use of types. Here are some examples:

Class instance creation expression:

implements clause:

Thrown exception declaration:

This form of annotation is called a type annotation .

Declaring an Annotation Type

Many annotations replace comments in code.

Suppose that a software group traditionally starts the body of every class with comments providing important information:

To add this same metadata with an annotation, you must first define the annotation type. The syntax for doing this is:

The annotation type definition looks similar to an interface definition where the keyword interface is preceded by the at sign ( @ ) ( @ = AT, as in annotation type). Annotation types are a form of interface, which will be covered in a later section. For the moment, you do not need to understand interfaces.

The body of the previous annotation definition contains annotation type element declarations, which look a lot like methods. Note that they can define optional default values.

After the annotation type is defined, you can use annotations of that type, with the values filled in, like this:

Note: To make the information in @ClassPreamble appear in Javadoc-generated documentation, you must annotate the @ClassPreamble definition with the @Documented annotation:

Predefined Annotation Types

A set of annotation types are predefined in the Java SE API. Some annotation types are used by the Java compiler, and some apply to other annotations.

Annotation Types Used by the Java Language

The predefined annotation types defined in java.lang are @Deprecated , @Override , and @SuppressWarnings .

@Deprecated

@Deprecated annotation indicates that the marked element is deprecated and should no longer be used. The compiler generates a warning whenever a program uses a method, class, or field with the @Deprecated annotation. When an element is deprecated, it should also be documented using the Javadoc @deprecated tag, as shown in the following example. The use of the at sign ( @ ) in both Javadoc comments and in annotations is not coincidental: they are related conceptually. Also, note that the Javadoc tag starts with a lowercase d and the annotation starts with an uppercase D .

Note that, as of Java SE 9, a forRemoval attribute has been added to the @Deprecated annotation. It indicates whether the annotated element is subject to removal in a future version. The default value is false .

@Override annotation informs the compiler that the element is meant to override an element declared in a superclass. Overriding methods will is discussed in the section Interfaces and Inheritance.

While it is not required to use this annotation when overriding a method, it helps to prevent errors. If a method marked with @Override fails to correctly override a method in one of its superclasses, the compiler generates an error.

@SuppressWarnings

@SuppressWarnings annotation tells the compiler to suppress specific warnings that it would otherwise generate. In the following example, a deprecated method is used, and the compiler usually generates a warning. In this case, however, the annotation causes the warning to be suppressed.

Every compiler warning belongs to a category. The Java Language Specification lists two categories: deprecation and unchecked. The unchecked warning can occur when interfacing with legacy code written before the advent of generics. To suppress multiple categories of warnings, use the following syntax:

@SafeVarargs

@SafeVarargs annotation, when applied to a method or constructor, asserts that the code does not perform potentially unsafe operations on its varargs parameter. When this annotation type is used, unchecked warnings relating to varargs usage are suppressed.

@FunctionalInterface

@FunctionalInterface annotation, introduced in Java SE 8, indicates that the type declaration is intended to be a functional interface, as defined by the Java Language Specification.

Annotations That Apply to Other Annotations

Annotations that apply to other annotations are called meta-annotations. There are several meta-annotation types defined in java.lang.annotation .

@Retention annotation specifies how the marked annotation is stored:

  • RetentionPolicy.SOURCE – The marked annotation is retained only in the source level and is ignored by the compiler.
  • RetentionPolicy.CLASS – The marked annotation is retained by the compiler at compile time, but is ignored by the Java Virtual Machine (JVM).
  • RetentionPolicy.RUNTIME – The marked annotation is retained by the JVM so it can be used by the runtime environment.

@Documented

@Documented annotation indicates that whenever the specified annotation is used those elements should be documented using the Javadoc tool. (By default, annotations are not included in Javadoc.) For more information, see the Javadoc tools page.

@Target annotation marks another annotation to restrict what kind of Java elements the annotation can be applied to. A target annotation specifies one of the following element types as its value:

  • ElementType.ANNOTATION_TYPE can be applied to an annotation type.
  • ElementType.CONSTRUCTOR can be applied to a constructor.
  • ElementType.FIELD can be applied to a field or property.
  • ElementType.LOCAL_VARIABLE can be applied to a local variable.
  • ElementType.METHOD can be applied to a method-level annotation.
  • ElementType.MODULE can be applied to a module declaration.
  • ElementType.PACKAGE can be applied to a package declaration.
  • ElementType.PARAMETER can be applied to the parameters of a method.
  • ElementType.RECORD_COMPONENT can be applied to the component of a record.
  • ElementType.TYPE can be applied to the declaration of a class, an abtract class, an interface, an annotation interface, an enumeration, or a record declaration.
  • ElementType.TYPE_PARAMETER can be applied on the parameters of a type.
  • ElementType.TYPE_USE can be applied where a type is used, for instance on the declaration of a field.

@Inherited annotation indicates that the annotation type can be inherited from the super class. (This is not true by default.) When the user queries the annotation type and the class has no annotation for this type, the class' superclass is queried for the annotation type. This annotation applies only to class declarations.

@Repeatable

@Repeatable annotation, introduced in Java SE 8, indicates that the marked annotation can be applied more than once to the same declaration or type use. For more information, see the section Repeating Annotations.

Type Annotations and Pluggable Type Systems

Before the Java SE 8 release, annotations could only be applied to declarations. As of the Java SE 8 release, annotations can also be applied to any type use. This means that annotations can be used anywhere you use a type. A few examples of where types are used are class instance creation expressions ( new ), casts, implements clauses, and throws clauses. This form of annotation is called a type annotation and several examples are provided in the section Annotations Basics.

Type annotations were created to support improved analysis of Java programs way of ensuring stronger type checking. The Java SE 8 release does not provide a type checking framework, but it allows you to write (or download) a type checking framework that is implemented as one or more pluggable modules that are used in conjunction with the Java compiler.

For example, you want to ensure that a particular variable in your program is never assigned to null; you want to avoid triggering a NullPointerException . You can write a custom plug-in to check for this. You would then modify your code to annotate that particular variable, indicating that it is never assigned to null. The variable declaration might look like this:

When you compile the code, including the NonNull module at the command line, the compiler prints a warning if it detects a potential problem, allowing you to modify the code to avoid the error. After you correct the code to remove all warnings, this particular error will not occur when the program runs.

You can use multiple type-checking modules where each module checks for a different kind of error. In this way, you can build on top of the Java type system, adding specific checks when and where you want them.

With the judicious use of type annotations and the presence of pluggable type checkers, you can write code that is stronger and less prone to error.

In many cases, you do not have to write your own type checking modules. There are third parties who have done the work for you. For example, you might want to take advantage of the Checker Framework created by the University of Washington. This framework includes a NonNull module, as well as a regular expression module, and a mutex lock module. For more information, see the Checker Framework .

Repeating Annotations

There are some situations where you want to apply the same annotation to a declaration or type use. As of the Java SE 8 release, repeating annotations enable you to do this.

For example, you are writing code to use a timer service that enables you to run a method at a given time or on a certain schedule, similar to the UNIX cron service. Now you want to set a timer to run a method, doPeriodicCleanup() , on the last day of the month and on every Friday at 11:00 p.m. To set the timer to run, create an @Schedule annotation and apply it twice to the doPeriodicCleanup() method. The first use specifies the last day of the month and the second specifies Friday at 11p.m., as shown in the following code example:

The previous example applies an annotation to a method. You can repeat an annotation anywhere that you would use a standard annotation. For example, you have a class for handling unauthorized access exceptions. You annotate the class with one @Alert annotation for managers and another for admins:

For compatibility reasons, repeating annotations are stored in a container annotation that is automatically generated by the Java compiler. In order for the compiler to do this, two declarations are required in your code.

Step 1: Declare a Repeatable Annotation Type

The annotation type must be marked with the @Repeatable meta-annotation. The following example defines a custom @Schedule repeatable annotation type:

The value of the @Repeatable meta-annotation, in parentheses, is the type of the container annotation that the Java compiler generates to store repeating annotations. In this example, the containing annotation type is @Schedules , so repeating @Schedule annotations is stored in an @Schedules annotation.

Applying the same annotation to a declaration without first declaring it to be repeatable results in a compile-time error.

Step 2: Declare the Containing Annotation Type

The containing annotation type must have a value element with an array type. The component type of the array type must be the repeatable annotation type. The declaration for the @Schedules containing annotation type is the following:

Retrieving Annotations

There are several methods available in the Reflection API that can be used to retrieve annotations. The behavior of the methods that return a single annotation, such as AnnotatedElement.getAnnotation(Class<T>) , are unchanged in that they only return a single annotation if one annotation of the requested type is present. If more than one annotation of the requested type is present, you can obtain them by first getting their container annotation. In this way, legacy code continues to work. Other methods were introduced in Java SE 8 that scan through the container annotation to return multiple annotations at once, such as AnnotatedElement.getAnnotationsByType(Class<T>) . See the AnnotatedElement class specification for information on all of the available methods.

Design Considerations

When designing an annotation type, you must consider the cardinality of annotations of that type. It is now possible to use an annotation zero times, once, or, if the annotation's type is marked as @Repeatable , more than once. It is also possible to restrict where an annotation type can be used by using the @Target meta-annotation. For example, you can create a repeatable annotation type that can only be used on methods and fields. It is important to design your annotation type carefully to ensure that the programmer using the annotation finds it to be as flexible and powerful as possible.

In this tutorial

Last update: September 14, 2021

DZone

  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
  • Manage My Drafts

Low-Code Development: Leverage low and no code to streamline your workflow so that you can focus on higher priorities.

Feeling secure? Tell us your top security strategies in 2024, influence our research, and enter for a chance to win $!

Launch your software development career: Dive head first into the SDLC and learn how to build high-quality software and teams.

Open Source Migration Practices and Patterns : Explore key traits of migrating open-source software and its impact on software development.

  • Dependency Injection in Spring
  • Singleton: 6 Ways To Write and Use in Java Programming
  • The Long Road to Java Virtual Threads
  • Exploring Exciting New Features in Java 17 With Examples
  • Leveraging Test Containers With Docker for Efficient Unit Testing
  • How To Compare DOCX Documents in Java
  • Developer Git Commit Hygiene
  • Strategies for Building Self-Healing Software Systems

Creating Annotations in Java

This comprehensive look at annotations in java not only goes into how to create them but also advise on how to use them and how they're processed by the jvm..

Justin Albano user avatar

Join the DZone community and get the full member experience.

Annotations are a powerful part of Java, but most times we tend to be the users rather than the creators of annotations. For example, it is not difficult to find Java source code that includes the @Override annotation processed by the Java compiler, the @Autowired annotation used by the Spring framework , or the @Entity  annotation used by the Hibernate framework , but rarely do we see custom annotations. While custom annotations are an often-overlooked aspect of the Java language, they can be a very useful asset in developing readable code and just as importantly, useful in understanding how many common frameworks, such as Spring or Hibernate, succinctly accomplish their goals.

In this article, we will cover the basics of annotations, including what annotations are, how they are useful in large-than-academic examples, and how to process them. In order to demonstrate how annotations work in practice, we will create a Javascript Object Notation (JSON) serializer that processes annotated objects and produces a JSON string representing each object. Along the way, we will cover many of the common stumbling blocks of annotations, including the quirks of the Java reflection framework and visibility concerns for annotation consumers. The interested reader can find the source code for the completed JSON serializer on GitHub .

What Are Annotations?

Annotations are decorators that are applied to Java constructs, such as classes, methods, or fields, that associate metadata with the construct. These decorators are benign and do not execute any code in-and-of-themselves, but can be used by runtime frameworks or the compiler to perform certain actions. Stated more formally, the Java Language Specification (JLS), Section 9.7 , provides the following definition:

An annotation is a marker which associates information with a program construct, but has no effect at run time.

It is important to note the last clause in this definition: Annotations have no effect on a program at runtime. This is not to say that a framework may not change its behavior based on the presence of an annotation at runtime, but that the inclusion of an annotation does not itself change the runtime behavior of a program. While this may appear to be a nuanced distinction, it is a very important one that must be understood in order to grasp the usefulness of annotations.

For example, adding the @Autowired annotation to an instance field does not in-and-of-itself change the runtime behavior of a program: The compiler simply includes the annotation at runtime, but the annotation does not execute any code or inject any logic that alters the normal behavior of the program (the behavior expected when the annotation is omitted). Once we introduce the Spring framework at runtime, we are able to gain powerful Dependency Injection (DI) functionality when our program is parsed. By including the annotation, we have instructed the Spring framework to inject an appropriate dependency into our field. We will see shortly (when we create our JSON serializer) that the annotation itself does not accomplish this, but rather, the annotation acts as a marker, informing the Spring framework that we desire a dependency to be injected into the annotated field.

Retention and Target

Creating an annotation requires two pieces of information: (1) a retention policy and (2) a target. A retention policy specifies how long, in terms of the program lifecycle, the annotation should be retained for. For example, annotations may be retained during compile-time or runtime, depending on the retention policy associated with the annotation. As of Java 9, there are three standard retention policies , as summarized below:

Policy Description
Source Annotations are discarded by the compiler
Class Annotations are recorded in the class file generated by the compiler but are not required to be retained by the Java Virtual Machine (JVM) that processes the class file at runtime
Runtime Annotations are recorded in the class file by the compiler and retained at runtime by the JVM

As we will see shortly, the runtime option for annotation retention is one of the most common, as it allows for Java programs to reflectively access the annotation and execute code based on the presence of an annotation, as well as access the data associated with an annotation. Note that an annotation has exactly one associated retention policy.

The target of an annotation specifies which Java constructs an annotation can be applied to. For example, some annotations may be valid for methods only, while others may be valid for both classes and fields. As of Java 9, there are eleven standard annotation targets , as summarized in the following table:

Target Description
Annotation Type Annotates another annotation
Constructor Annotates a constructor
Field
Annotates a field, such as an instance variable of a class or an
Local variable Annotates a local variable
Method Annotates a method of a class
Module Annotates a module (new in Java 9)
Package Annotates a package
Parameter Annotates a parameter to a method or constructor
Type Annotates a type, such as a class, interfaces, annotation types, or enum declarations
Type Parameter Annotates a type parameter, such as those used as formal generic parameters
Type Use Annotates the use of a type, such as when an object of a type is created using the keyword, when an object is cast to a specified type, when a class implements an interface, or when the type of a throwable object is declared using the throws keyword (for more information, see the )

For more information on these targets, see Section 9.7.4 of the JLS . It is important to note that one or more targets may be associated with an annotation. For example, if the field and constructor targets are associated with an annotation, then the annotation may be used on either fields or constructors. If on the other hand, an annotation only has an associated target of method, then applying the annotation to any construct other than a method results in an error during compilation.

Annotation Parameters

Annotations may also have associated parameters. These parameters may be a primitive (such as int or double ), String , class, enum, annotation, or an array of any of the five preceding types (see Section 9.6.1 of the JLS ). Associating parameters with an annotation allows for an annotation to provide contextual information or can parameterize a processor of an annotation. For example, in our JSON serializer implementation, we will allow for an optional annotation parameter that specifies the name of a field when it is serialized (or use the variable name of the field by default if no name is specified).

How Are Annotations Created?

For our JSON serializer, we will create a field annotation that allows a developer to mark a field to be included when serializing an object. For example, if we create a car class, we can annotate the fields of the car (such as make and model) with our annotation. When we serialize a car object, the resulting JSON will include make and model keys, where the values represent the value of the make and model fields, respectively. For the sake of simplicity, we will assume that this annotation will be used only for fields of type String , ensuring that the value of the field can be directly serialized as a string.

To create such a field annotation, we declare a new annotation using the @interface  keyword:

The core of our declaration is the public @interface JsonField , which declares an annotation type with a public modifier, allowing our annotation to be used in any package (assuming the package is properly imported if in another module). The body of the annotation declares a single String parameter, named value , that has a type of String and a default value of an empty string.

Note that the variable name value has a special meaning: It defines a Single-Element Annotation ( Section 9.7.3. of the JLS ) and allows users of our annotation to supply a single parameter to the annotation without specifying the name of the parameter. For example, a user can annotate a field using @JsonField("someFieldName") and is not required to declare the annotation as @JsonField(value = "someFieldName") , although the latter may still be used (but it is not required). The inclusion of a default value of empty string allows for the value to be omitted, resulting in value holding an empty string if no value is explicitly specified. For example, if a user declares the above annotation using the form @JsonField , then the value parameter is set to an empty string.

The retention policy and target of the annotation declaration are specified using the @Retention and @Target annotations, respectively. The retention policy is specified using the java.lang.annotation.RetentionPolicy enum and includes constants for each of the three standard retention policies. Likewise, the target is specified using the java.lang.annotation.ElementType enum, which includes constants for each of the eleven standard target types.

In summary, we created a public, single-element annotation named JsonField , which is retained by the JVM during runtime and may only be applied to fields. This annotation has a single parameter, value , of type String with a default value of an empty string. With our annotation created, we can now annotate fields to be serialized.

How Are Annotations Used?

Using an annotation requires only that the annotation is placed before an appropriate construct (any valid target for the annotation). For example, we can create a Car class using the following class declaration:

This class exercises the two major uses of the @JsonField annotation: (1) with an explicit value and (2) with a default value. We could have also annotated a field using the form @JsonField(value = "someName") , but this style is overly verbose and does not aid in the readability of our code. Therefore, unless the inclusion of an annotation parameter name in a single-element annotation adds to the readability of code, it should be omitted. For annotations with more than one parameter, the name of each parameter is required to differentiate between parameters (unless only one argument is provided, in which case, the argument is mapped to the value parameter if no name is explicitly provided).

Given the above uses of the @JsonField annotation, we would expect that a Car ject is serialized into a JSON string of the form {"manufacturer":"someMake", "model":"someModel"}  (note, as we will see later, we will disregard the order of the keys– manufacturer  and model –in this JSON string). Before we proceed, it is important to note that adding the @JsonField annotations does not change the runtime behavior of the Car class. If we compile this class, the inclusion of @JsonField annotations does not enhance the behavior of the Car class anymore than had we omitted the annotations. These annotations are simply recorded, along with the value of the value parameter, in the class file for the Car class. Altering the runtime behavior of our system requires that we process these annotations.

How are Annotations Processed?

Processing annotations is accomplished through the Java Reflection Application Programming Interface (API) . Sidelining the technical nature of the reflection API for a moment, the reflection API allows us to write code that will inspect the class, methods, fields, etc. of an object. For example, if we create a method that accepts a Car object, we can inspect the class of this object (namely, Car ) and discover that this class has three fields: (1) make , (2) model , and (3) year . Furthermore, we can inspect these fields to discover if each is annotated with a specific annotation.

Using this capability, we can iterate through each field of the class associated with the object passed to our method and discover which of these fields are annotated with the @JsonField annotation. If the field is annotated with the @JsonField annotation, we record the name of the field and its value. Once all the fields have been processed, then we can create the JSON string using these field names and values.

Determining the name of the field requires more complex logic than determining the value. If the @JsonField includes a provided value for the value parameter (such as "manufacturer" in the previous @JsonField("manufacturer") use), we will use this provided field name. If the value of the value parameter is an empty string, we know that no field name was explicitly provided (since this is the default value for the value parameter), or else, an empty string was explicitly provided. In either case, we will use the variable name of the field as the field name (for example, model  in the private final String model declaration).

Combining this logic into a JsonSerializer class, we can create the following class declaration:

Note that multiple responsibilities have been combined into this class for the sake of brevity. For a refactored version of this serializer class, see this branch in the codebase repository. We also create an exception that will be used to denote if an error has occurred while processing the object supplied to our serialize method:

Although the JsonSerializer class appears complex, it consists of three main tasks: (1) finding all fields of the supplied class annotated with the @JsonField annotation, (2) recording the field name (or the explicitly provided field name) and value for all fields that include the @JsonField annotation, and (3) converting the recorded field name and value pairs into a JSON string.

The line requireNonNull(object).getClass() s imply checks that the supplied object is not null  (and throws a NullPointerException if it is) and obtains the Class object associated with the supplied object. We will use this Class object shortly to obtain the fields associated with the class. Next, we create a Map of String s to String s, which will be used store the field name and value pairs.

With our data structures established, we next iterate through each field declared in the class of the supplied object. For each field, we configure the field to suppress Java language access checking when accessing the field. This is a very important step since the fields we annotated are private. In the standard case, we would be unable to access these fields, and attempting to obtain the value of the private field would result in an IllegalAccessException being thrown. In order to access these private fields, we must instruct the reflection API to suppress the standard Java access checking for this field using the setAccessible method. The setAccessible(boolean)  documentation defines the meaning of the supplied boolean flag as follows:

A value of true indicates that the reflected object should suppress Java language access checking when it is used. A value of false indicates that the reflected object should enforce Java language access checks.

Note that with the introduction of modules in Java 9, using the setAccessible  method requires that the package containing the class whose private fields will be accessed should be declared open in its module definition. For more information, see this explanation by Michał Szewczyk and Accessing Private State of Java 9 Modules by Gunnar Morling .

After gaining access to the field, we check if the field is annotated with the @JsonField . If it is, we determine the name of the field (either through an explicit name provided in the @JsonField annotation or the default name, which equals the variable name of the field) and record the name and field value in our previously constructed map. Once all fields have been processed, we then convert the map of field names to field values ( jsonElements ) into a JSON string.

We accomplish by converting the map into a stream of entries (key-value pairs for each entry in the map), mapping each entry to a string of the form "<fieldName>":"<fieldValue>" , where <fieldName> is the key for the entry and <fieldValue> is the value for the entry. Once all entries have been processed, we combine all of these entry strings with a comma. This results in a string of the form "<fieldName1>":"<fieldValue1>","<fieldName2>":"<fieldValue2>",... . Once this terminal string has been joined, we surround it with curly braces, creating a valid JSON string.

In order to test this serializer, we can execute the following code:

This results in the following output:

As expected, the maker and model fields of the Car object have been serialized, using the name of the field (or the explicitly supplied name in the case of the maker field) as the key and the value of the field as the value. Note that the order of JSON elements may be reversed from the output seen above. This occurs because there is no definite ordering for the array of declared fields for a class, as stated in the getDeclaredFields documentation :

The elements in the returned array are not sorted and are not in any particular order.

Due to this limitation, the order of the elements in the JSON string may vary. To make the order of the elements deterministic, we would have to impose ordering ourselves (such as by sorting the map of field names to field values). Since a JSON object is defined as an unordered set of name-value pairs, as per the JSON standard , imposing ordering is unneeded. Note, however, a test case for the serialize method should pass for either {"model":"F150","manufacturer":"Ford"}  or {"manufacturer":"Ford","model":"F150"} .

Java annotations are a very powerful feature in the Java language, but most often, we are the users of standard annotations (such as @Override ) or common framework annotations (such as @Autowired ), rather than their developers. While annotations should not be used in place of interfaces or other language constructs that properly accomplish a task in an object-oriented manner, they can greatly simplify repetitive logic. For example, rather than creating a toJsonString method within an interface and having all classes that can be serialized implement this interface, we can annotate each serializable field. This takes the repetitive logic of the serialization process (mapping field names to fields values) and places it into a single serializer class. It also decouples the serialization logic from the domain logic, removing the clutter of manual serialization from the conciseness of the domain logic.

While custom annotations are not frequently used in most Java applications, knowledge of this feature is a requirement for any intermediate or advanced user of the Java language. Not only will knowledge of this feature enhance the toolbox of a developer, which is just as important, but it will also aid in the understanding of the common annotations in the most popular Java frameworks.

Opinions expressed by DZone contributors are their own.

Partner Resources

  • About DZone
  • Send feedback
  • Community research
  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone
  • Terms of Service
  • Privacy Policy
  • 3343 Perimeter Hill Drive
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • Enterprise Java
  • Web-based Java
  • Data & Java
  • Project Management
  • Visual Basic
  • Ruby / Rails
  • Java Mobile
  • Architecture & Design
  • Open Source
  • Web Services

Developer.com

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More .

Annotation-based Java development is certainly one of the most notable recent development trends. Annotation-based development relieves Java developers from the pain of cumbersome configuration. First introduced in Java 5.0, annotations are one of the features in that JDK version that shifted the responsibility for writing boilerplate Java code from the programmer to the compiler. When the source code is free of boilerplate code, it becomes easier to maintain. The resulting code is also less likely to contain bugs.

Java annotations are one of the main ease-of-development features introduced in JDK 5. Annotations are like meta-tags that you can add to your code and apply to package declarations, type declarations, constructors, methods, fields, parameters and variables. They provide a helpful way to indicate whether your methods are dependent on other methods, whether they are incomplete, whether your classes have references to other classes, and so on.

Quoting from Oracle’s official site , “It [annotation-based development] lets us avoid writing boilerplate code under many circumstances by enabling tools to generate it from annotations in the source code. This leads to a declarative programming style where the programmer says what should be done and tools emit the code to do it.”

Simply speaking, an annotation is a mechanism for associating a meta-tag with program elements and allowing the compiler or the VM to extract program behaviors from these annotated elements and generate interdependent code when necessary.

In the first part of this three-article series, I’ll describe some basics of Java annotations, their benefits, as well as provide some example usages.

Java Annotations Basics

There are two things you need to consider with annotations. One is the “annotation” itself; another is the “annotation type.” An annotation is the meta-tag that you will use in your code to give it some life. Annotation type is used for defining an annotation. You will use it when you want to create your own custom annotation. The type is the actual construct used, and the annotation is the specific usage of that type.

An annotation type definition takes an “at” (@) sign, followed by the interface keyword plus the annotation name. On the other hand, an annotation takes the form of an “at” sign (@), followed by the annotation type. This is simplest form of annotation. Additionally, you can put data within parenthesis after the annotation name. An example of each can be seen below:

Example to Define an Annotation (Annotation Type)

Example to annotate your code (annotation), java annotation types.

There are three annotation types:

Marker: Marker type annotations have no elements, except the annotation name itself.

Rules of Thumb for Defining Java Annotation Types

Here are some rules-of-thumb when defining an annotation type:

  • Annotation declaration should start with an ‘at’ sign like @, following with an interface keyword, following with the annotation name.
  • Method declarations should not have any parameters.
  • Method declarations should not have any throws clauses.
  • array of the above types

There are two types of annotations available with JDK5:

  • Simple annotations: These are the basic types supplied with Tiger, which you can use to annotate your code only; you cannot use those to create a custom annotation type.
  • Meta annotations: These are the annotation types designed for annotating annotation-type declarations. Simply speaking, these are called the annotations-of-annotations.

Simple Java Annotations

There are only three types of simple annotations provided by JDK5. They are:

  • Suppresswarnings

It’s important to note that JDK5 (in other words, Tiger) actually does not have many built-in annotations; rather, it allows core Java the ability to support the annotation feature. The charter for JSR-175 strictly dictated it was to define a metadata facility. It was left to the programmers to write custom annotation types and to other JSRs to write a set of standard annotation types. The following sections will describe each simple annotation in more depth, along with examples.

The Override Annotation

An override annotation indicates that the annotated method is required to override a method in a super class. If a method with this annotation does not override its super-class’s method, the compiler will generate an error. Example 1 demonstrates the override annotation:

Java Annotation Example 1

What happens if a spelling mistake occurs with the method name? For example, if you change the name of the toString method to “tostring” and compile the code, you will get something like the following:

The Deprecated Annotation

This annotation indicates that when a deprecated program element is used, the compiler should warn you about it. Example 2 shows you the deprecated annotation.

Java Annotation Example 2

First, create a class with the deprecated method as follows:

Next, try to invoke this method from another class:

The doSomething() method in this example is declared as a deprecated method. Therefore, this method should not be used when this class is instantiated by other classes. If you compile Test_Deprecated.java, no warning messages will be generated by the compiler. But, if you try to compile TestAnnotations.java where the deprecated method is used, you will see something like this:

The Suppresswarnings Annotation

This annotation indicates that compiler warnings should be shielded in the annotated element and all of its sub-elements. The set of warnings suppressed in an element is the superset of the warnings in all of its containing sub-elements. As an example, if you annotate a class to suppress one warning and one of its methods to suppress another warning, both warnings will be suppressed at the method level only. See Example 3 for the suppresswarnings annotation.

Java Annotation Example 3

In this example, you are suppressing the deprecation warning for the method listing shown in Example 2. Because the method is suppressed, you are unlikely to view the “deprecation” warning any more.

Note: It is a good idea to use this annotation at the most deeply nested element where it is effective. Therefore, if you want to suppress a warning in a particular method, you should annotate that method rather than its class.

Meta-Annotations (Java Annotation Types)

Meta-annotations, which are actually known as the annotations of annotations, contain four types. These are:

The Target Annotation

The target annotation indicates the targeted elements of a class in which the annotation type will be applicable. It contains the following enumerated types as its value:

  • @Target(ElementType.TYPE) —can be applied to any element of a class
  • @Target(ElementType.FIELD) —can be applied to a field or property
  • @Target(ElementType.METHOD) —can be applied to a method level annotation
  • @Target(ElementType.PARAMETER) —can be applied to the parameters of a method
  • @Target(ElementType.CONSTRUCTOR) —can be applied to constructors
  • @Target(ElementType.LOCAL_VARIABLE) —can be applied to local variables
  • @Target(ElementType.ANNOTATION_TYPE) —indicates that the declared type itself is an annotation type

Example 4 demonstrates the target annotation:

Java Annotation Example 4

First, define an annotation named Test_Target with @Target metadata, as follows:

Next, create a class that will use the Test_Target annotation:

The @Target(ElementType.METHOD) indicates that this annotation type can be used to annotate only at the method levels. If you compile the preceding code, no warning messages will be shown. Now, if you declare a String variable and apply your newly created annotation, what will happen? Let me demonstrate this as follows:

The only change you can see from above is that the annotation declaration is shifted from method-level to field-level, which is not correct. Because you have defined your annotation @Test_Target to be applicable only at method-level, if you try to compile this class, you are likely to get something like this:

The Retention Annotation

The retention annotation indicates where and how long annotations with this type are to be retained. There are three values:

  • RetentionPolicy.SOURCE —Annotations with this type will be by retained only at the source level and will be ignored by the compiler
  • RetentionPolicy.CLASS —Annotations with this type will be by retained by the compiler at compile time, but will be ignored by the VM
  • RetentionPolicy.RUNTIME —Annotations with this type will be retained by the VM so they can be read only at run-time

Example 5 shows you the RetentionPolicy.RUNTIME value in action:

Java Annotation Example 5

In this example, the @Retention(RetentionPolicy.RUNTIME) annotation indicates that your Test_Retention annotation is to be retained by the VM so that it can be read reflectively at run-time.

The Documented Annotation

The documented annotation indicates that an annotation with this type should be documented by the javadoc tool. By default, annotations are not included in javadoc. But if @Documented is used, it then will be processed by javadoc-like tools and the annotation type information will also be included in the generated document. Example 6 demonstrates using @Documented further:

Java Annotation Example 6

Next, update your TestAnnotations class as follows:

Now, if you run the javadoc command and view the generated TestAnnotations.html file, you will see something like Figure 1.

As you can see from the screenshot, there is no annotation-type information for the doSomeTestRetention() method. But, this description is provided for the doSomeTestDocumented() method. This is because of the @Documented tag attached with your Test_Documented annotation. Your earlier annotation Test_Retention did not include this tag.

The Inherited Annotation

This is a bit of a complex annotation type. It indicates that the annotated class with this type is automatically inherited. More specifically, if you define an annotation with the @Inherited tag, then annotate a class with your annotation, and finally extend the class in a subclass, all properties of the parent class will be inherited into its subclass. With Example 7, you will get an idea about the benefits of using the @Inherited tag.

Java Annotation Example 7

First, define your annotation:

Next, annotate a class with your annotation:

As you can see, you do not have to define the interface methods inside the implementing class. These are automatically inherited because of using the @Inherited tag. What would happen if you define the implementing class in old-fashioned Java-style? Take a look at this—defining the implementation class in an old-style-java way:

Do you see the difference? You can see that you will have to implement all the methods that the parent interface owns. Besides the isInherited() and doSomething() methods from myParentObject, you will have to implement the equals(), toString(), and hasCode() methods of java.lang.Object and also the annotationType() method of java.lang.annotation.Annotation class. It does not matter whether you want to implement these methods or not; you will have to include these in your inherited object.

This article has shown you how you can make your development easier through the use of JDK5’s annotation feature. Annotations do not directly affect the semantics of a program. Development and deployment tools can read these annotations and process them in some fashion, perhaps producing additional Java programming language source files, XML documents, or other artifacts to be used in conjunction with the program containing the annotations. You now can do the same things as you would do before, but with less code and better compile-time error detection. The objective is to spend less time on unhandy code-writing and focus more on business logic rules. This article is Part I of a series on Java Annotations. In Part II, you will learn about how to use annotations to develop a simple Web application with a flat table. Lastly, in Part III you will see a complex example that includes multiple database tables relationships.

Java Annotation Resources

  • New Features and Enhancements J2SE 5.0 at http://www.mathcs.carleton.edu/courses/course_resources/j2se-1.5.0-docs/relnotes/features.html
  • J2SE 5.0 in a Nutshell at http://java.sun.com/developer/technicalArticles/releases/j2se15/
  • Annotations in Tiger, Part 1: Add metadata to Java code at http://www-128.ibm.com/developerworks/java/library/j-annotate1/
  • What’s New in Java 1.5? at http://www.cs.indiana.edu/classes/jett/sstamm/
  • Tiger in NetBeans4 at http://cropcrusher.web.infoseek.co.jp/shufujava/sunone/nb/nb4tiger_en.html
  • Taming the tiger at http://www.denverjug.org/meetings/files/200408_Tiger.pdf

About the Author

M. M. Islam Chisty currently works as a Software Engineer for M&H Informatics. His responsibilities include development and re-engineering of Web-based applications using J2EE technologies. M. Chisty has a B.S. degree in computer science from North South University. He loves spending his free time doing R&D on latest Java based technologies, watching TV, and listening to music. And, he’s a great WWE fan, too. You can contact M.Chisty at [email protected] .

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

What is the role of a project manager in software development, how to use optional in java, overview of the jad methodology, microsoft project tips and tricks, how to become a project manager in 2023, related stories, understanding types of thread synchronization errors in java, understanding memory consistency in java threads.

Developer.com

Implementation:

Note: This program throws compiler error because we have mentioned override, but not overridden, we have overloaded display.
   

Output:  

If we remove parameter (int x) or we remove @override, the program compiles fine. 

Categories of Annotations

There are broadly 5 categories of annotations as listed:

  • Marker Annotations
  • Single value Annotations
  • Full Annotations
  • Type Annotations
  • Repeating Annotations

Let us discuss and we will be appending code wherever required if so. 

Category 1: Marker Annotations

The only purpose is to mark a declaration. These annotations contain no members and do not consist of any data. Thus, its presence as an annotation is sufficient. Since the marker interface contains no members, simply determining whether it is present or absent is sufficient. @Override is an example of Marker Annotation. 

Category 2: Single value Annotations 

These annotations contain only one member and allow a shorthand form of specifying the value of the member. We only need to specify the value for that member when the annotation is applied and don’t need to specify the name of the member. However, in order to use this shorthand, the name of the member must be a value. 

Category 3: Full Annotations 

These annotations consist of multiple data members, names, values, pairs. 

Category 4: Type Annotations 

These annotations can be applied to any place where a type is being used. For example, we can annotate the return type of a method. These are declared annotated with @Target annotation .

     

Category 5: Repeating Annotations 

These are the annotations that can be applied to a single item more than once. For an annotation to be repeatable it must be annotated with the @Repeatable annotation, which is defined in the java.lang.annotation package. Its value field specifies the container type for the repeatable annotation. The container is specified as an annotation whose value field is an array of the repeatable annotation type. Hence, to create a repeatable annotation, firstly the container annotation is created, and then the annotation type is specified as an argument to the @Repeatable annotation.

  Predefined/ Standard Annotations

Java popularly defines seven built-in annotations as we have seen up in the hierarchy diagram.

  • Four are imported from java.lang.annotation: @Retention , @Documented , @Target , and @Inherited .
  • Three are included in java.lang: @Deprecated, @Override and @SuppressWarnings

Annotation 1: @Deprecated 

  • It is a marker annotation. It indicates that a declaration is obsolete and has been replaced by a newer form.
  • The Javadoc @deprecated tag should be used when an element has been deprecated.
  • @deprecated tag is for documentation and @Deprecated annotation is for runtime reflection.
  • @deprecated tag has higher priority than @Deprecated annotation when both are together used.

Annotation 2: @Override

It is a marker annotation that can be used only on methods. A method annotated with @Override must override a method from a superclass. If it doesn’t, a compile-time error will result (see this for example). It is used to ensure that a superclass method is actually overridden, and not simply overloaded.

 

Annotation 3: @SuppressWarnings 

It is used to inform the compiler to suppress specified compiler warnings. The warnings to suppress are specified by name, in string form. This type of annotation can be applied to any type of declaration.

Java groups warnings under two categories. They are deprecated and unchecked . Any unchecked warning is generated when a legacy code interfaces with a code that uses generics.

Annotation 4: @Documented 

It is a marker interface that tells a tool that an annotation is to be documented. Annotations are not included in ‘Javadoc’ comments. The use of @Documented annotation in the code enables tools like Javadoc to process it and include the annotation type information in the generated document.

Annotation 5: @Target 

It is designed to be used only as an annotation to another annotation. @Target takes one argument, which must be constant from the ElementType enumeration. This argument specifies the type of declarations to which the annotation can be applied. The constants are shown below along with the type of the declaration to which they correspond.

Be
ANNOTATION_TYPE Another annotation
CONSTRUCTOR Constructor
FIELD Field
LOCAL_VARIABLE Local variable
METHOD Method
PACKAGE Package
PARAMETER Parameter
TYPE Class, Interface, or enumeration

We can specify one or more of these values in a @Target annotation. To specify multiple values, we must specify them within a braces-delimited list. For example, to specify that an annotation applies only to fields and local variables, you can use this @Target annotation: @Target({ElementType.FIELD, ElementType.LOCAL_VARIABLE}) @Retention Annotation It determines where and how long the annotation is retent. The 3 values that the @Retention annotation can have:

  • SOURCE: Annotations will be retained at the source level and ignored by the compiler.
  • CLASS: Annotations will be retained at compile-time and ignored by the JVM.
  • RUNTIME: These will be retained at runtime.

Annotation 6: @Inherited 

@Inherited is a marker annotation that can be used only on annotation declaration. It affects only annotations that will be used on class declarations. @Inherited causes the annotation for a superclass to be inherited by a subclass. Therefore, when a request for a specific annotation is made to the subclass, if that annotation is not present in the subclass, then its superclass is checked. If that annotation is present in the superclass, and if it is annotated with @Inherited, then that annotation will be returned. 

Annotation 7: User-defined (Custom) 

User-defined annotations can be used to annotate program elements, i.e. variables, constructors, methods, etc. These annotations can be applied just before the declaration of an element (constructor, method, classes, etc). 

Syntax: Declaration

Do keep these certain points as rules for custom annotations before implementing user-defined annotations. 

  • AnnotationName is an interface.
  • The parameter should not be associated with method declarations and throws clause should not be used with method declaration.
  • Parameters will not have a null value but can have a default value.
  • default value is optional.
  • The return type of method should be either primitive, enum, string, class name, or array of primitive, enum, string, or class name type.
 

Please Login to comment...

Similar reads.

  • java-basics

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

Java Custom Annotations Example

author image

In this tutorial, we will show you how to create two custom annotations – @Test and @TestInfo , to simulate a simple unit test framework.

P.S This unit test example is inspired by this official Java annotation article .

1. @Test Annotation

This @interface tells Java this is a custom annotation. Later, you can annotate it on method level like this @Test(enable=false) .

2. @TesterInfo Annotation

This @TesterInfo is applied on class level, store the tester details. This shows the different use of return types – enum, array and string.

3. Unit Test Example

Create a simple unit test example, and annotated with the new custom annotations – @Test and @TesterInfo .

4. Java reflection – Read the Annotation

Below example show you how to use Java reflection APIs to read and process the custom annotations.

  • Wikipedia : Java annotation
  • Oracle JavaSE docs – annotations
  • ElementType JavaDoc
  • RetentionPolicy JavaDoc

java-json-tutorials

Java JSON Tutorials

Parsing JSON with Jackson, Moshi, Gson etc.

About Author

author image

I love Java!!!

do you? Me too!

Good class!! We have so much in common!

So… this is only useful to output some simple stuff via System.out.println()… can only be run via a whole bunch of reflection code… doesn’t have any useful purpose… and would’ve been so much less code using a static utility method inside the code than an annotation?

wouldn’t a better example have been something…. useful? like do something on a RestController to prevent having a ton of extra code inside the multiple controller methods???

How to pass the json file values using custom annotation in java

But, annotations on vars?

Sir, let’s say i have many classes in different different packages then how can i specify them instead of Class obj = TestExample.class;

// Process @TesterInfo if (obj.isAnnotationPresent(TesterInfo.class)) { Please help in this..

Question – If custom annotations are placed while writing code, what is the point of having a RetentionPolicy.RUNTIME?

It is very Help full thanks .

I’m wondering what would be the reason why the order is TestA, TestC, and TestB… What happened in the background which made this order?

Very helpful, thank you!!

Nice article. Suppose I create an annotation @AdditionalInfo(client=”testclient”). Now I want to execute only those @Test methods which have “testclient” set in @AdditionalInfo. Selective execution. Similar to grouping, but I wish to do it through annotations. Can anyone help how can I do that?

I also looking same kind of answer Varun.

Based on the article above and a few that I have read on other sites. I have concerns about the implementation part of annotation. I somehow get the feeling that much of the heavy lifting of scanning the classes that have used the annotation is left to end user. However, I wish to understand how do libraries like Jackson(for JSON parsing) or so are able to extend their annotation and yet we do not have to do any explicit scan of classes or so while using them.

Need your help to implement a library with features that can be extended via annotations.

Good one.. Very helpful

Good one..very helpful thanks

simply spectacular 😀

Simple and Neat .. (Y)

I have a doubt can we do the package level annoatation without adding the adpaters and package-info.java in the same package. Real Qstn is : I have different packages around 20 packges which has to use this annotations. so is it neccessery to put adpaters as well as package-info.java in each and every package. Is there any alternate way for it? please help…

Thanks, good explanation

hi friends; how can I read fields , methods ,… of a class by using annotations thanks thanks

Hi, do you have sample of initialize a object through annotation http://stackoverflow.com/questions/28539917/how-to-initialize-a-object-using-annotation?noredirect=1#comment45397115_28539917

Good one… Annotations demystified largely.

I created a custom method_annotation that allows me to change the order of parts of text in toString() method. Is it possible to annotate a method before call it (beyond a class definition)?

Here is an expected code:

System.out.println(“Person: ” + person.@ToStringOrder(non-default-parameter) toString() );

How to annotate person.toString() ?

What is the correct syntax if it possible?

Thanks in advance

good example simple but clear, thanks

is it possible to write a custom annotaion which will set a default value to a java bean variable. for example if there is a list and the getter method should be initialised to a new arraylist through a custom annotation. can some one suggest.

very helpful. thanks

This: Annotation annotation = obj.getAnnotation(TesterInfo.class); TesterInfo testerInfo = (TesterInfo) annotation; …can simply be written as: TesterInfo testerInfo = obj.getAnnotation(TesterInfo.class);

It is not necessary to assign to an intermediate variable of type “Annotation” and then downcast it at runtime – the Java Generics mechanism already handles the type conversion for you at compile time.

Can you do the same tutorial using AspectJ ?

Scanning Java Annotations at Runtime

Last updated: January 16, 2024

write annotation java

  • Java Annotations

announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, you can get started over on the documentation page .

And, you can also ask questions and leave feedback on the Azure Container Apps GitHub page .

Get non-trivial analysis (and trivial, too!) suggested right inside your IDE or Git platform so you can code smart, create more value, and stay confident when you push.

Get CodiumAI for free and become part of a community of over 280,000 developers who are already experiencing improved and quicker coding.

Write code that works the way you meant it to:

>> CodiumAI. Meaningful Code Tests for Busy Devs

DbSchema is a super-flexible database designer, which can take you from designing the DB with your team all the way to safely deploying the schema .

The way it does all of that is by using a design model , a database-independent image of the schema, which can be shared in a team using GIT and compared or deployed on to any database.

And, of course, it can be heavily visual, allowing you to interact with the database using diagrams, visually compose queries, explore the data, generate random data, import data or build HTML5 database reports.

>> Take a look at DBSchema

Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.

The Jet Profiler was built for MySQL only , so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.

Critically, it has very minimal impact on your server's performance, with most of the profiling work done separately - so it needs no server changes, agents or separate services.

Basically, you install the desktop application, connect to your MySQL server , hit the record button, and you'll have results within minutes:

>> Try out the Profiler

A quick guide to materially improve your tests with Junit 5:

Do JSON right with Jackson

Download the E-book

Get the most out of the Apache HTTP Client

Get Started with Apache Maven:

Working on getting your persistence layer right with Spring?

Explore the eBook

Building a REST API with Spring?

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> REST With Spring (new)

Get started with Spring and Spring Boot, through the reference Learn Spring course:

>> LEARN SPRING

Looking for the ideal Linux distro for running modern Spring apps in the cloud?

Meet Alpaquita Linux : lightweight, secure, and powerful enough to handle heavy workloads.

This distro is specifically designed for running Java apps . It builds upon Alpine and features significant enhancements to excel in high-density container environments while meeting enterprise-grade security standards.

Specifically, the container image size is ~30% smaller than standard options, and it consumes up to 30% less RAM:

>> Try Alpaquita Containers now.

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth , to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project .

You can explore the course here:

>> Learn Spring Security

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot .

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

1. Introduction

As we know, in the Java world, annotation is a very useful way of obtaining meta information about classes and methods.

In this tutorial, we’re going to discuss scanning Java annotations at runtime.

2. Defining Custom Annotation

Let’s start by defining a sample annotation and a sample class that uses our custom annotation:

Now, we are ready to resolve the “name” attribute of this custom annotation on both class-based and method-based usages .

3. Scanning Annotations with Java Reflection

With the help of Java Reflection , we can scan a specific annotated class or annotated method(s) of a specific class.

In order to achieve this goal, we need to load the class by using ClassLoader . So this method is useful when we know in which class(es) to scan annotation:

4. Scanning Annotations with Spring Context Library

Another way of scanning the annotations is using ClassPathScanningCandidateComponentProvider  class which is included in the Spring Context library.

Let’s start by adding spring-context dependency:

And let’s continue with a simple example:

Completely different from Java Reflections , we can scan all classes without the need to know the specific class names .

5. Scanning Annotations with Spring Core Library

Although Spring Core doesn’t directly provide full scanning of all annotations in our code, we can still develop our own full annotation scanner by using some utility classes of this library .

First, we need to add spring-core dependency:

Here comes a simple example:

With the help of  AnnotationUtils and ClassUtils , it’s possible to find the methods and classes annotated with a specific annotation.

6. Scanning Annotations with Reflections Library

Reflections is a library that is said to be written in the spirit of Scannotations library. It scans and indexes the project’s classpath metadata .

Let’s add  reflections dependency:

Now we are ready to use the library for searching the annotated classes, methods, fields and types:

As we can see, the  Reflections library provides a flexible way of scanning all annotated classes and methods. So we don’t need to start with SampleAnnotatedClass .

7. Scanning Annotations with Jandex Library

Now let’s take a look at a different library named Jandex which we can use to scan the annotations at runtime by reading the generated Jandex files of our code .

This library introduces a Maven plugin to generate a Jandex file that contains meta information related to our project:

As we can see, after running the maven-install command, the file is generated in the classpath under the META-INF directory with the name jandex.idx. We can also modify the name of the file with rename plugin of Maven if it’s needed.

Now we are ready to scan any kind of annotation. First, we need to add the jandex dependency:

Now it’s time to scan the annotations:

8. Conclusion

Depending on our requirement; there are various ways of scanning annotations at runtime. Each of these ways has its own pros and cons. We can decide considering what we need.

The implementations of these examples are available over on GitHub .

Just published a new writeup on how to run a standard Java/Boot application as a Docker container, using the Liberica JDK on top of Alpaquita Linux:

>> Spring Boot Application on Liberica Runtime Container.

Slow MySQL query performance is all too common. Of course it is.

The Jet Profiler was built entirely for MySQL , so it's fine-tuned for it and does advanced everything with relaly minimal impact and no server changes.

Explore the secure, reliable, and high-performance Test Execution Cloud built for scale. Right in your IDE:

Basically, write code that works the way you meant it to.

Get started with Spring Boot and with core Spring, through the Learn Spring course:

Build your API with SPRING - book cover

Follow the Java Category

write annotation java

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

How to write a Java annotation processor?

I may be just looking in the wrong direction but I find the JSE documentation on annotation processing very ... sparse. I want to write an annotation processor which processes annotated String fields and local variables to substitute them with a computed String expression. This should not be too complicated but I'm pretty lost in the Javadoc for javax.annotation.processing.

EDIT: I need to process annotations at compile time because I want to modify the generated code. It should replace annotated constant String expressions with a computed String expression.

  • annotations

Christian Schlichtherle's user avatar

  • Agreed, my entry point was this tutorial: tutorials.jenkov.com/java-reflection/annotations.html –  Konrad Reiche Commented Jul 8, 2012 at 18:39
  • 2 Do you want to process annotations at compile time or runtime? Note that annotations on local variables are effectively useless due to a silly javac limitation. –  Paul Bellora Commented Jul 8, 2012 at 18:43
  • I want to process them at compile time, so this would obviously only work for constant string expressions. –  Christian Schlichtherle Commented Jul 8, 2012 at 19:03
  • You might be able to use ANT's replace task , but that might depend on what "computed" means. See this post for example. –  Paul Bellora Commented Jul 8, 2012 at 23:33
  • Maybe it will be useful: github.com/vbauer/jackdaw –  Vladislav Bauer Commented Mar 22, 2015 at 14:19

3 Answers 3

This can not be done with a compile time annotation processor. Compile time time annotation processors can only generate new files (and classes) they can not modify existing classes. You can do reflection at runtime but strictly speaking you that is not called annotation processing. Also you won't have access to local variables.

If you're looking on how to write a compile time annotation processor check out https://github.com/pellaton/spring-configuration-validation-processor

Graham Borland's user avatar

  • Theoretically, you could use an annotation processor + Apache BCEL (or something similar) to modify the original .class file. But that sounds messy. –  vanza Commented Jul 8, 2012 at 18:53
  • Err... what? I cannot modify the source code before compilation using the annotation framework? –  Christian Schlichtherle Commented Jul 8, 2012 at 19:11
  • 1 I looked at the linked code. Obviously it doesn't generate code, it just validates it. I was hoping I could modify the Abstract Syntax Tree before the actual code generation step. –  Christian Schlichtherle Commented Jul 8, 2012 at 19:28
  • 1 I think your only options are bytecode manipulation (using e.g. ASM, BCEL) or some classpath tricks like reference to the class that is generated by the annotation processor instead to the original file or something like that... –  s106mo Commented Jul 8, 2012 at 20:30
  • 1 @christian-schlichtherle Yes, you can't modify. Check out the apt documentation . "These reflective APIs provide a build-time, source-based, read-only view of program structure." "runs annotation processors that can produce new source code and other files " –  Philippe Marschall Commented Jul 9, 2012 at 7:32

Two tools that do this are Project Lombok and DuctileJ . Both of these tools existed at the time the question was originally asked; additional tools now surely exist.

The key idea is to write an annotation processor that traverses and modifies the program's AST (abstract syntax tree) during compilation, before code generation. The compiler won't change the source code on disk, but the generated .class file will reflect the changes that your annotation processor makes.

You may be able to adapt one of these tools to suit your needs, or you could implement your own tool inspired by their implementation techniques.

Compile-time processing has two advantages over class-file processing. One is that the compiler usually has more information than is available from compiled code. Another is that everything happens in one step, during compilation, rather than requiring the developer to run a separate tool to rewrite the .class files after compilation.

rob's user avatar

  • 2 sure, and worth mentioning that both use a hack to modify the AST, exploiting a bug in the current annotation processor in Java, making use of internal javac APIs which could be fixed/removed in some future JDK (which goes down as a big disadvantage to me). –  Neil Stockton Commented Nov 11, 2015 at 16:58
  • I'm sorry, but as helpful this answer might be, its statements simply are not true. The mentioned tools are not aspect processors, but compiler plugins (completely different method, not as well supported in some tools). You cannot modify AST with aspect processor -- only generate new code in new compilation units (e.g. new classes) –  pwes Commented Dec 6, 2022 at 10:27
  • Javassist http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
  • ASM http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
  • Byteman (for runtime) http://www.jboss.org/byteman/

Ondra Žižka's user avatar

  • I have looked at Javassist and ASM. Maybe they would do the job, but they are about byte code manipulation. I would very much prefer to use a tool which would allow me to manipulate the Abstract Syntax Tree. Byte code manipulation would only be my last resort. –  Christian Schlichtherle Commented Jul 8, 2012 at 22:41
  • OK, after investigating the options, it seems that byte code manipulation is the only viable option left. The next challenge is to integrate this into a Maven build - not just for me, but for the users of my library, too. –  Christian Schlichtherle Commented Jul 9, 2012 at 12:53

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged java annotations or ask your own question .

  • Featured on Meta
  • We spent a sprint addressing your requests — here’s how it went
  • Upcoming initiatives on Stack Overflow and across the Stack Exchange network...
  • Policy: Generative AI (e.g., ChatGPT) is banned
  • The [lib] tag is being burninated
  • What makes a homepage useful for logged-in users

Hot Network Questions

  • Phantom points in QGIS do not dissapear
  • Correlation for Small Dataset?
  • Was BCD a limiting factor on 6502 speed?
  • How is the result of this integral obtained by the function `Integrate`?
  • Turning Misty step into a reaction to dodge spells/attacks
  • Book that I read around 1975, where the main character is a retired space pilot hired to steal an object from a lab called Menlo Park
  • Use multiple image texture frames in Geometry Nodes
  • Use of Compile[] to optimize the code to run faster
  • Can you arrange 25 whole numbers (not necessarily all different) so that the sum of any three successive terms is even but the sum of all 25 is odd?
  • Ideal diode in parallel with resistor and voltage source
  • I want to leave my current job during probation but I don't want to tell the next interviewer I am currently working
  • mirrorlist.centos.org no longer resolve?
  • Position where last x halfmoves are determined
  • Is arxiv strictly for new stuff?
  • Explicit Construction of the Alternating Subgroup of a Coxeter Group
  • in Arizona, under which conditions must a person stop and speak with law enforcement outside of legal traffic stops
  • Did Tolkien give his son explicit permission to publish all that unfinished material?
  • Can you help me to identify the aircraft in a 1920s photograph?
  • Duplicating Matryoshka dolls
  • Is it prohibited to consume things that unclean animals produce?
  • Is there an economic incentive to use p2wsh over p2tr?
  • What does ‘a grade-hog’ mean?
  • Is "conversational" used precisely in this context?
  • How do guitarists remember what note each string represents when fretting?

write annotation java

IMAGES

  1. Annotations in Java: Explained With Examples

    write annotation java

  2. Java Annotations Tutorial: Different Types of Annotations in Java Explained

    write annotation java

  3. Annotations in Java

    write annotation java

  4. How to declare an annotation type?

    write annotation java

  5. Java 9

    write annotation java

  6. Java annotations

    write annotation java

VIDEO

  1. Java Qualifier Annotation

  2. Java Annotation Processing

  3. What is an annotation?

  4. [자바 강의] 20-1. Annotation (Annotation, Java)

  5. What is Annotation in java #java #annotations #javainterview #javahack #coding #ai #api #programming

  6. Use of Primary Annotation in Java

COMMENTS

  1. Creating a Custom Annotation in Java

    Class Level Annotation Example. The first step toward creating a custom annotation is to declare it using the @interface keyword: public @interface JsonSerializable {. } Copy. The next step is to add meta-annotations to specify the scope and the target of our custom annotation:

  2. Java Annotations (With Examples)

    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.

  3. Lesson: Annotations (The Java™ Tutorials > Learning the Java ...

    This lesson explains where annotations can be used, how to apply annotations, what predefined annotation types are available in the Java Platform, Standard Edition (Java SE API), how type annotations can be used in conjunction with pluggable type systems to write code with stronger type checking, and how to implement repeating annotations.

  4. Annotations Basics (The Java™ Tutorials > Learning the Java Language

    The annotation type can be one of the types that are defined in the java.lang or java.lang.annotation packages of the Java SE API. In the previous examples, Override and SuppressWarnings are predefined Java annotations. It is also possible to define your own annotation type. The Author and Ebook annotations in the previous example are custom ...

  5. How to Create Your Own Annotations in Java?

    By default, Java annotations are not shown in the documentation created using the Javadoc tool. To ensure that our custom annotations are shown in the documentation, we use @Documented annotation to annotate our custom annotations. @Documented is a meta-annotation (an annotation applied to other annotations) provided in java.lang.annotation package

  6. Java: Creating and Using Custom Annotations

    Custom annotations help: Reduce the effort of writing code, by adding default behavior to methods. Add custom behavior to classes and interfaces. Save the effort of writing XML descriptors and ...

  7. Java Annotations

    Java Annotations. Java Annotation is a tag that represents the metadata i.e. attached with class, interface, methods or fields to indicate some additional information which can be used by java compiler and JVM. Annotations in Java are used to provide additional information, so it is an alternative option for XML and Java marker interfaces.

  8. Complete Java Annotations Tutorial

    An annotation is a kind of metadata in Java that can be applied to various elements of Java source code so that later some tool, debugger, or application program can take advantage of these annotations; and help analyze the program in a positive and constructive way. Just to mention, we can annotate classes, methods, variables, parameters, and packages in Java OR in one word almost everything.

  9. Mastering Java Annotations: A Comprehensive Guide to Creating, Using

    This blog post will explore Java annotations in depth, covering built-in annotations, creating custom annotations, and processing them using reflection or annotation processors. Table of Contents . Understanding Java Annotations . Built-in Java Annotations 2.1. Standard Annotations 2.2. Meta-Annotations . Creating Custom Annotations

  10. Annotations

    Repeating annotations are supported as of the Java SE 8 release. For more information, see the section Repeating Annotations. The annotation type can be one of the types that are defined in the java.lang or java.lang.annotation packages of the Java SE API. In the previous examples, Override and SuppressWarnings are predefined Java annotations ...

  11. Creating Annotations in Java

    33. } This class exercises the two major uses of the @JsonField annotation: (1) with an explicit value and (2) with a default value. We could have also annotated a field using the form @JsonField ...

  12. A Guide to Java Annotations with Examples

    First introduced in Java 5.0, annotations are one of the features in that JDK version that shifted the responsibility for writing boilerplate Java code from the programmer to the compiler. When the source code is free of boilerplate code, it becomes easier to maintain. The resulting code is also less likely to contain bugs.

  13. Java Annotation Essentials Guide

    Java annotations are one of the cornerstone features of modern Java development, offering a powerful way to describe and control the behavior of code elements. Introduced in Java 5 through JSR 175 ...

  14. Java Annotation Processing and Creating a Builder

    A quick and practical guide to annotation processing in Java, showing you how to create a builder from a POJO. ... (PrintWriter out = new PrintWriter(builderFile.openWriter())) { // writing generated file to out … } The complete code of the writeBuilderFile method is provided below. We only need to calculate the package name, fully qualified ...

  15. Java Annotations

    Here is a @Target Java annotation example: import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target({ElementType.METHOD}) public @interface MyAnnotation { String value(); } This example shows a Java annotation that can only be used to annotate methods. The ElementType class contains the following possible targets:

  16. Customize Java Annotation with Examples

    1. Class Level Annotation. The first step to creating a custom annotation is to declare it using the @interface keyword : public @interface GFG {. } The next step is to specify the scope and the target of our custom annotation : @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.Type) public @interface GFG {.

  17. Annotations in Java

    Category 5: Repeating Annotations These are the annotations that can be applied to a single item more than once. For an annotation to be repeatable it must be annotated with the @Repeatable annotation, which is defined in the java.lang.annotation package. Its value field specifies the container type for the repeatable annotation.The container is specified as an annotation whose value field is ...

  18. Custom annotations in Java

    To create a custom annotation in Java, you define an @interface and specify the properties you want to include in the annotation. Here is an example of a custom annotation definition: import java ...

  19. Java Custom Annotations Example

    P.S This unit test example is inspired by this official Java annotation article. 1. @Test Annotation. This @interface tells Java this is a custom annotation. Later, you can annotate it on method level like this @Test(enable=false). Test.java. package com.mkyong.test.core; import java.lang.annotation.ElementType;

  20. Scanning Java Annotations at Runtime

    3. Scanning Annotations with Java Reflection. With the help of Java Reflection, we can scan a specific annotated class or annotated method (s) of a specific class. In order to achieve this goal, we need to load the class by using ClassLoader. So this method is useful when we know in which class (es) to scan annotation:

  21. The Power of Custom Annotations and Annotation Processors in Java

    Learn How to Unleash Automation, Validation, and Code Enhancement with Custom Annotations and Processors in Java. Learn how these tools improve documentation, automate activities, expedite ...

  22. How to write a Java annotation processor?

    Two tools that do this are Project Lombok and DuctileJ.Both of these tools existed at the time the question was originally asked; additional tools now surely exist. The key idea is to write an annotation processor that traverses and modifies the program's AST (abstract syntax tree) during compilation, before code generation.