What you'll learn
Annotations attach metadata to your code, and reflection lets a program inspect and manipulate itself at runtime. Together they power the frameworks you'll use every day — JUnit, Spring, Hibernate, Jackson. This module reveals the magic behind them.
By the end you'll be able to:
- Use built-in annotations and create your own
- Control annotations with
@Retentionand@Target - Inspect classes, methods, and fields with reflection
- Invoke methods dynamically
- Understand how frameworks combine the two — and the trade-offs
Built-in annotations
An annotation is metadata — a note on your code that tools, the compiler, or a framework can read. You've already used @Override. The JDK ships a few you'll see constantly:
class Base {
void speak() { }
}
class Dog extends Base {
@Override // compiler verifies this overrides
void speak() { System.out.println("Woof"); }
@Deprecated // warns callers this is obsolete
void oldTrick() { }
@SuppressWarnings("unchecked") // silences a specific warning
void risky() { }
}@Override— the compiler checks you really are overriding a method@Deprecated— marks something obsolete; callers get a warning@SuppressWarnings— silences a specific compiler warning@FunctionalInterface— enforces the single-abstract-method rule (Module 10)
Custom annotations
You can define your own annotations with @interface. Two meta-annotations configure them: @Retention says how long the annotation survives (source only, in the class file, or available at RUNTIME for reflection), and @Target says where it can be applied (methods, fields, classes…):
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) // keep it available at runtime
@Target(ElementType.METHOD) // may only annotate methods
@interface Test { }
class MathTests {
@Test void addsCorrectly() { /* ... */ }
@Test void subtractsCorrectly() { /* ... */ }
void helperNotATest() { /* ... */ }
}Note
@Retention(RetentionPolicy.RUNTIME). The default keeps it only in the class file, invisible to reflection.Reflection
Reflection (the java.lang.reflect package) lets code examine itself at runtime — list a class's methods and fields, read annotations, even access private members. Every object can hand you its Class object, the gateway to all of this:
import java.lang.reflect.*;
Class<?> c = "hello".getClass(); // get the runtime type
System.out.println(c.getName()); // java.lang.String
// look up a method by name and CALL it dynamically
Method m = String.class.getMethod("toUpperCase");
Object result = m.invoke("hello");
System.out.println(result);Dynamic invocation
Reflection can go further and call methods chosen at runtime by name, or create objects, without knowing the types at compile time. This is how a framework runs your annotated methods without ever having seen your class:
import java.lang.reflect.*;
// This is (roughly) how a test runner finds and runs tests:
for (Method m : MathTests.class.getDeclaredMethods()) {
if (m.isAnnotationPresent(Test.class)) {
System.out.println("Running test: " + m.getName());
m.invoke(new MathTests());
}
}How frameworks use it
Annotations + reflection is the recipe behind almost every Java framework. You sprinkle annotations on your code; the framework scans for them with reflection and does the heavy lifting:
You add annotations
@Test, @Autowired, @Entity…
Framework scans classes
using reflection at startup
It acts on them
runs tests, injects deps, maps tables
Use it sparingly in your own code
Recap & quick check
Key takeaways
- Annotations attach metadata; built-ins include @Override, @Deprecated, @SuppressWarnings.
- Create your own with @interface; configure with @Retention (RUNTIME for reflection) and @Target.
- Reflection inspects classes, methods, and fields at runtime via the Class object.
- It can invoke methods and create objects dynamically by name.
- Frameworks combine annotations + reflection; use reflection sparingly in your own code (slow, unsafe).
Quick check
1. What are annotations?
2. For a custom annotation to be readable by reflection, its retention must be…
3. What does reflection let a program do?
4. How do frameworks like JUnit and Spring work under the hood?
5. A downside of reflection is that it…
Great — you've seen the machinery behind Java's frameworks. Next up: Module 27 — JVM Internals & Memory Management.