Working with Annotations
1. Understanding Built-in Annotations
| Annotation | Purpose |
|---|---|
@Override | Method overrides supertype |
@Deprecated(since, forRemoval) | Mark for removal |
@SuppressWarnings("unchecked") | Silence compiler warnings |
@FunctionalInterface | Single-abstract-method interface |
@SafeVarargs | Generic varargs are safe |
2. Using @Override
| Use | Detail |
|---|---|
| Catches typos | Compile error if not actually overriding |
| Required for | Interface methods (Java 6+) |
3. Using @Deprecated
| Element | Detail |
|---|---|
since | Version deprecated in |
forRemoval | true → terminal deprecation |
4. Using @SuppressWarnings
| Value | Suppresses |
|---|---|
"unchecked" | Generic cast warnings |
"deprecation" | Deprecated API use |
"rawtypes" | Raw type warnings |
"all" | All (avoid) |
5. Using @FunctionalInterface
| Aspect | Detail |
|---|---|
| Effect | Compile error if not exactly one abstract method |
| Doesn't prevent | Default/static methods |
6. Creating Custom Annotations
Example: Custom annotation
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Audited {
String value() default "";
String[] roles() default {};
int level() default 1;
}
| Element | Allowed Types |
|---|---|
| Element types | Primitives, String, Class, enum, annotation, arrays of these |
value() | Special: can be omitted in usage |
7. Using @Target
| ElementType | Applies To |
|---|---|
TYPE | Class/interface/enum |
METHOD | Methods |
FIELD | Fields |
PARAMETER | Method params |
CONSTRUCTOR | Constructors |
TYPE_USE | Any type usage (Java 8+) |
MODULE | Modules (Java 9+) |
8. Using @Retention
| Policy | Available |
|---|---|
SOURCE | Compile time only (e.g., @Override) |
CLASS | In .class but not at runtime (default) |
RUNTIME | Available via reflection |
9. Using @Documented
| Aspect | Detail |
|---|---|
| Effect | Annotation appears in Javadoc |
10. Using @Inherited
| Aspect | Detail |
|---|---|
| Effect | Subclass inherits class-level annotation |
| Limitation | Only for class types, not interfaces or methods |
11. Using @Repeatable JAVA 8+
Example: Repeatable
@Repeatable(Schedules.class)
@interface Schedule { String day(); }
@interface Schedules { Schedule[] value(); }
@Schedule(day = "MON")
@Schedule(day = "WED")
class Job {}
| Step | Detail |
|---|---|
| 1 | Define container annotation with value() array |
| 2 | Annotate child with @Repeatable(Container.class) |
12. Processing Annotations at Runtime
Example: Reflection
Class<?> cls = MyService.class;
if (cls.isAnnotationPresent(Audited.class)) {
Audited a = cls.getAnnotation(Audited.class);
System.out.println(a.value());
}
for (Method m : cls.getDeclaredMethods()) {
Audited a = m.getAnnotation(Audited.class);
if (a != null) ...
}
| Method | Returns |
|---|---|
getAnnotation(cls) | Single annotation |
getAnnotationsByType(cls) | Repeatable annotations |
isAnnotationPresent(cls) | boolean |
13. Using Annotation Processors
| Aspect | Detail |
|---|---|
| API | javax.annotation.processing |
| Base class | Extend AbstractProcessor |
| Run time | Compile time only |
| Examples | Lombok, Dagger, MapStruct, Immutables |