Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between declaration annotations and type annotations

Java 8 introduced type annotations with JSR308. According to the Java language specifications

type annotations can be used anywhere a type is used, such as declarations, generic arguments, casts etc.

I'm relatively new to Java, Java 8 was the first version of java I used, so I'm not familiar with non-'type annotations', i.e. declaration annotations.

How are declaration annotations different from type annotations? I want to know because I keep hearing about them in manuals and it looks like 'type annotations' are a superset of 'declaration annotations'.

like image 979
saga Avatar asked May 01 '18 15:05

saga


2 Answers

Both type annotations and declaration annotations still exist in Java, and they are distinct and non-overlapping.

A type annotation can be written on any use of a type. It conceptually creates a new, more specific type. That is, it describes what values the type represents.

As an example, the int type contains values ..., -2, -1, 0, 1, 2, ...
The @Positive int type contains values 1, 2, ...
Therefore, @Positive int is a subtype of int.

A declaration annotation can be written on any declaration (a class, method, or variable). It describes the thing being declared, but does not describe run-time values. Here are examples of declaration annotations:

@Deprecated
class MyClass { ... }

says that programmers should not use MyClass.

@Override
void myMethod() { ... }

says that myMethod overrides a declaration in a superclass or interface.

@SuppressWarnings(...)
int myField = INITIALIZATION-EXPRESSION;

says that the compiler should not issue warnings about code in the initialization expression.

Here are examples that use both a declaration annotation and a type annotation:

@Override
@NonNull String myMethod() { ... }

@GuardedBy("myLock")
@Regex String myField;

Note that the type annotation describes the value, and the declaration annotation says something about the method or use of the field.

As a matter of style, declaration annotations are written on their own line, and type annotations are written directly before the type, on the same line.

like image 80
mernst Avatar answered Nov 19 '22 06:11

mernst


Most annotations right now are declaration annotations, for example @Override:

class Foo implements Runnable {
    @Override // applies to the declaration of Foo.run()
    public void run() {
    }
}

Type annotations expand the possible annotation targets to uses of types which are not declarations (casts, type arguments and so on). Type annotations can appear in declarations, but type annotations are not a superset of declaration annotations. For example, @Override is never a type annotation.

In cases which are ambiguous, for example @Foo int x;, JLS §9.7.4 outlines specific rules for whether it's the declaration or type that's considered to be annotated. In some cases, it's even considered as both.

The following are a few unambiguous examples of type annotations:

// cast
String str = (@Foo String) take();
// type argument
List<@Foo String> list = new ArrayList<>();

I suppose I could also add that the issue with type annotations at the moment is that there's no official API that lets an annotation processor (basically a compiler plug-in) do anything meaningful with them. As a result of this, type annotations are generally only used by third-party tools, like Lombok and the Eclipse compiler.

like image 2
Radiodef Avatar answered Nov 19 '22 05:11

Radiodef