Appearance
Lesson 01 · Annotations
Beyond the 1Z0-830 exam
Annotations aren't a named 1Z0-830 objective, but they're everywhere a working developer or SDET looks — JUnit (@Test), Mockito, Spring, Jackson. Understanding retention and how frameworks read annotations at runtime is essential to using and building test tooling.
Objectives
After this lesson you will be able to:
- Use the built-in annotations and explain what each enforces.
- Define a custom annotation with
@Retentionand@Target. - Read annotations at runtime with reflection.
Built-in annotations
| Annotation | Effect |
|---|---|
@Override | compile error if it doesn't actually override |
@FunctionalInterface | compile error unless exactly one abstract method |
@Deprecated | marks an API as obsolete (warning on use); @Deprecated(since, forRemoval) |
@SuppressWarnings("unchecked") | silences specific compiler warnings |
@SafeVarargs | suppresses unsafe-varargs warnings on a safe generic varargs method |
Defining a custom annotation
An annotation is declared with @interface. Members look like methods and may have defaults.
java
@Retention(RetentionPolicy.RUNTIME) // keep it at runtime so reflection can read it
@Target(ElementType.METHOD) // where it may be placed
@interface Timed {
String value() default ""; // a member; `value` allows @Timed("x")
int threshold() default 100;
}
@Timed("login")
void login() { }@Retention and @Target (meta-annotations)
A meta-annotation annotates an annotation:
@Retention— how long it's kept:SOURCE(compiler only, e.g.@Override),CLASS(in the.classbut not loaded — the default), orRUNTIME(readable via reflection).@Target— what it can annotate (TYPE,METHOD,FIELD,PARAMETER, …).
Gotcha
Only RUNTIME-retained annotations are visible to reflection. A framework like JUnit can find @Test only because it's RetentionPolicy.RUNTIME — the default CLASS retention would be invisible at runtime.
Reading annotations at runtime
java
Method m = MyTest.class.getMethod("login");
if (m.isAnnotationPresent(Timed.class)) {
Timed t = m.getAnnotation(Timed.class);
System.out.println(t.value() + " / " + t.threshold());
}SDET note
This is exactly how a test runner discovers tests: scan classes, find methods annotated with a RUNTIME annotation, and invoke them reflectively. Writing a tiny annotation + reflective runner is the clearest way to understand JUnit's machinery (Module 14).
Key Takeaways
- Built-ins:
@Override,@FunctionalInterface,@Deprecated,@SuppressWarnings,@SafeVarargs— each enforces or signals something at compile time. - Declare custom annotations with
@interface; members have types and optionaldefaults (valueenables the shorthand@A("x")). @Retention(RUNTIME)is required for reflective discovery;@Targetrestricts placement.- Read with
isAnnotationPresent/getAnnotation— the basis of test runners and DI frameworks.
Lesson Quiz
Which retention policy lets reflection read an annotation at runtime?
What does @Override do?
How do you declare a custom annotation?
What is the DEFAULT retention if you don't specify @Retention?
Why can JUnit find methods annotated @Test?
Next: Reflection (basics). Run the matching code in labs/src/main/java/com/jse21/m11_language/.