Annotating Java

Annotations are a means of adding metadata to Java source code. They can be applied to declarations of classes, fields, methods, and types (as of Java8) in order to pass instructions to the compiler. Annotations can even be evaluated at Runtime. For example, @Inject is an annotation from the Dagger dependency injection library used to indicate which constructor should be used to instantiate a class. @Inject also tells Dagger to create the dependencies identified in the constructor parameter list.

Provided by java.lang

  • @Deprecated: don’t use the marked object. This annotation should be accompanied by a comment explaining the reason and alternative.
  • @Override: this method overrides a superclass method.
  • @SuppressWarnings: the compiler will not report warnings generated by this method.

Create your own

Annotations can be used to replace verbose code comment templates, and since they are ostensibly interfaces, they can be created the same way you would any other interface.

1
2
3
4
5
6
7
8
9
// src/CustomAnnotation.java
import java.lang.annotation.Documented;

@Documented // Annotation of an Annotation -- so meta! [1]
@interface CustomAnnotation { // [2]
    int id(); // [3]
    String description();
    String author() default "[unknown]"; // [4]
}
  1. CustomAnnotation has an annotation of its own! The @Documented annotation ensures that CustomAnnotation and its properties will be included in the Javadoc when it is generated.
  2. Declare a new annotation using @interface instead of interface
  3. Fields id and description are considered required because they are not given default values. Values for id and description must be provided when using @CustomAnnotation.
  4. author is an unrequired field because a default value will be used if one is not provided.

Annotations for Annotations

When defining an annotation, you can indicate how it should be used:

  • @RetentionPolicy: How should the annotation be stored? Only in source, included in the generated Class, or passed all the way to the JVM for Runtime evaluation?
  • @Documented: Include the annotation when generating Javadocs (default is false).
  • @Target: A list of locations where the annotation can be used (constructor, field, method, etc).
  • @Inherited: The annotation properties can be inherited from the superclass.
  • @Repeatable: The annotation can be used more than once (declaring multiple authors, for example).

Using your CustomAnnotation

Use @CustomAnnotation to decorate your code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/Main.java
public class Main {

    ...

    @CustomAnnotation(id = 1, description = "Custom description")
    public void printSlogan() {
        System.out.println("This method uses a @CustomAnnotation");
    }

    @CustomAnnotation(id = 2, description = "Custom banner", author = "keighty")
    public void printBanner() {
        System.out.println("This is a printed banner for: " + message);
    }
}

When you generate the javadoc for Main.class, the annotations will be included in the method descriptions:

1
$  javadoc src/com/keighty/Main.java -d .

Annotating a field vs annotating a parameter

There are no hard rules about whether one should annotate a field or a constructor parameter, but which ever you choose you should use that pattern consistently.

If you use the @Nonnull annotation in the constructor, the compiler will warn if there is any use of the constructor where the parameter could be null. If you use the @Nonnull annotation on the field, you will have to do your own null checking when assigning the field.

RESOURCES