Annotations were added in Java 5 to provide metadata that can be used by the compiler and various frameworks. Initially, they helped tools (such as JUnit or Hibernate) to better interact with the code without the need to write repetitive or external configuration.
Annotations allow adding information to classes, methods, fields, parameters, and even local variables. They can be used during compilation, runtime, or source code processing for validation, generating additional files, or changing the program's behavior.
To declare your own annotation, the @interface keyword is used.
Example code:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation { String value(); } class Example { @MyAnnotation("Test") public void annotatedMethod() {} }
Key features:
Do annotations only affect runtime?
No, annotations can be limited to source code (SOURCE), bytecode (CLASS), or be available at runtime (RUNTIME). Their influence depends on RetentionPolicy.
@Retention(RetentionPolicy.SOURCE) public @interface SourceOnly {}
Can annotation parameters be of any type?
No, acceptable types are only primitives, strings, enums, other annotations, and arrays of these types. Objects cannot be used.
Can annotations be inherited?
Strictly speaking, annotations are not inherited like classes. The exception is an annotation with @Inherited, which only applies to subclasses (not affecting methods).
A developer in a large project created dozens of different annotations for test automation without bothering to write them down, document, and limit their scope. As a result, a new team member found it difficult to understand where different annotations worked.
Pros:
Cons:
The team implemented a strict strategy for writing their annotations: they added only what was necessary, described each in detail, and limited their scope.
Pros:
Cons: