paint-brush
Annotations in Java: Everything You Wanted To Knowby@roland-hewage
1,288 reads
1,288 reads

Annotations in Java: Everything You Wanted To Know

by Roland HewageMarch 19th, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Annotations are a form of metadata that provides data about a program that is not part of the program itself. Annotation can be used by the compiler to detect errors or suppress warnings. Annotations have no direct effect on the operation of the code they annotate. They can apply to packages, types (classes, interfaces, enums and annotation types), variables (class, instance and local variables — including that defined in a for or while loop), constructors, methods and parameters. The at sign character (@) indicates to the compiler that what follows is an annotated piece of code.

People Mentioned

Mention Thumbnail

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Annotations in Java: Everything You Wanted To Know
Roland Hewage HackerNoon profile picture

Annotations are a form of metadata. It provides data about a program that is not part of the program itself. Annotations have no direct effect on the operation of the code they annotate. Annotations were first introduced in the Java language with the third edition of the Java Language Specification and first implemented in Java 5.

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 on.
  • Runtime processing — Some annotations are available to be examined at runtime.

Using annotations, we are able to add metadata information to our source code — build or deployment information, configuration properties, compilation behavior or quality checks.

Here I’m going to explain where annotations can be used, how to apply annotations, what predefined annotation types are available in the Java Platform, Standard Edition (Java SE API).

Annotations Basics

Annotations always appears before the annotated piece of code and by convention, usually in its own line, indented at the same level.

Annotations may apply to packages, types (classes, interfaces, enums and annotation types), variables (class, instance and local variables — including that defined in a for or while loop), constructors, methods and parameters.

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

@Entity

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

@Override
void myAnnotationUsageMethod() { 
... 
}

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

@Author(
   name = "Roland Hewage",
   date = "2019/04/18"
)
class MyClass() { ... }

For example they can be used in a method as follows:

@SuppressWarnings(value = "unchecked")
void myMethod() { ... }

Annotations may include elements that are just name-value pairs separated by commas. Allowed types are primitives, strings, enums, class, annotations and arrays of these types and the default value cannot be null:

@Author(name = "Roland",
 created = "2019/04/18",
 revision = 3,
 reviewers = {"WSO2", "Shankar"})
public class SimpleAnnotationsTest {…}

When the annotation has only one element and its name is value, it can be omitted:

@SuppressWarnings(value = "unchecked")
void myMethod() { ... }

or

@SuppressWarnings("unchecked")
void myMethod() { ... }

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

@Override
void myAnnotationUsageMethod() { ... }

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

@Author(name = "Roland Hewage")
@EBook
class MyClass { ... }

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

@Author(name = "Roland Hewage")
@Author(name = "Rosy Buhat")
class MyClass { ... }

Repeating annotations are supported as of the Java SE 8 release.

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.

Annotations may define default values for some or all of their elements. Elements with default values can be omitted from an annotation declaration.

For example, assuming the Annotation Type Author defines default values for revision (default is 1) and reviewers (default is an empty String array), the following two annotation declarations are equivalent:

@Author(name = "Roland",
        created = "2018/04/18",
        revision = 1,
        reviewers = {})
public class SimpleAnnotationsTest() {…}

is equal to,


@Author(name = "Roland",        // defaults are revision 1
        created = "2018/04/18") // and no reviewers
public class SimpleAnnotationsTest() {…}

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.

Declaring an Annotation Type

Many annotations replace comments in code.

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

public class Generation3List extends Generation2List {

   // Author: Roland Hewaage
   // Date: 2018/04/18
   // Current revision: 6
   // Last modified: 2019/04/18
   // By: Roland Hewage
   // Reviewers: Alice, Bill, Cindy

   // class code goes here
}

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

@interface ClassPreamble {
   String author();
   String date();
   int currentRevision() default 1;
   String lastModified() default "N/A";
   String lastModifiedBy() default "N/A";
   // Note use of array
   String[] reviewers() default {};
}

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.

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:


@ClassPreamble (
   author = "Roxana Chatu",
   date = "2018/06/23",
   currentRevision = 6,
   lastModified = "2018/09/12",
   lastModifiedBy = "Roly Ross",
   // Note array notation
   reviewers = {"Alice", "Bob", "Cindy"}
)
public class Generation3List extends Generation2List {

// class code goes here

}

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


// import this to use @Documented
import java.lang.annotation.*;

@Documented
@interface ClassPreamble {

   // Annotation element definitions
   
}

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.

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


// Javadoc comment follows
/**
 * @deprecated
 * explanation of why it was deprecated
 */
@Deprecated
static void deprecatedMethod() { }

2. @Override

@Override annotation informs the compiler that the element is meant to override an element declared in a superclass.

// mark method as a superclass method
// that has been overridden
@Override 
int overriddenMethod() { }

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.

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


// use a deprecated method and tell 
// compiler not to generate a warning
@SuppressWarnings("deprecation")
void useDeprecatedMethod() {
    // deprecation warning
    // - suppressed
    objectOne.deprecatedMethod();
}

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:

@SuppressWarnings({"unchecked", "deprecation"})

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

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

Since the introduction of annotations, many libraries and frameworks have incorporated annotations into their newer releases. With annotations used in place with source code, these libraries and frameworks have reduced, even removed, the needs for configuration files.

Brilliant examples can be seen in:

  • Java Enterprise Edition and its main components — Enterprise JavaBeans, Java Persistence API or Web Services API’s
  • Spring Framework — used thoroughly for configuration, dependency injection and inversion of control in the core framework and in other Spring projects
  • Seam, Weld, Guice
  • Apache Struts 2

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.

1. @Retention

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

2. @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.)

3. @Target

@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.PACKAGE can be applied to a package declaration.
  • ElementType.PARAMETER can be applied to the parameters of a method.
  • ElementType.TYPE can be applied to any element of a class.

4. @Inherited

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

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