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'.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With