Unravel โบ Java concepts โบ OOP and types
Reflection
Reflection lets code look at classes, methods and fields by name at run time, and call or change them, without knowing them at compile time.
Learn these first
At a glance
Instead of knowing the staff by name, you walk into the building with a directory: "find everybody whose badge says Manager, and ask each one to sign this".
- 1Class<?> c = Class.forName("com.shop.Order") or Order.class gets the class objectc.getDeclaredMethods(), getDeclaredFields() and getDeclaredConstructor() list its members.
- 2method.invoke(target, args) calls a method; field.set(obj, value) writes a field; constructor.newInstance(args) creates an object
- 3setAccessible(true) bypasses privateModern Java restricts this for JDK internals through the module system.
- 4Annotation processing at run time is reflection: m.isAnnotationPresent(Test.class) is how test runners find tests
- Reflection hides dependencies from the compiler: renaming a method breaks code that looks it up by a string, and the error appears only at run time
- Security: reflective access to private members can break encapsulation; never build class names or method names from user input
- Class objects are created by the class loader
import java.lang.reflect.Method;public class Runner { static void runAll(Object target) throws Exception { for (Method m : target.getClass().getDeclaredMethods()) { if (m.isAnnotationPresent(Deprecated.class)) continue; m.setAccessible(true); if (m.getParameterCount() == 0) m.invoke(target); } }}- line 1 uses Method, the core of Reflection
- line 4 uses Method, the core of Reflection
- line 5 uses isAnnotationPresent, the core of Reflection
- line 6 uses setAccessible, the core of Reflection
- line 7 uses invoke, the core of Reflection
Read the full explanation (about 1 min)
Reflection lets code look at classes, methods and fields by name at run time, and call or change them, without knowing them at compile time. Frameworks use it to find your annotated classes and create your objects.
A mental model
Instead of knowing the staff by name, you walk into the building with a directory: "find everybody whose badge says Manager, and ask each one to sign this".
How it works
Class<?> c = Class.forName("com.shop.Order") or Order.class gets the class object. c.getDeclaredMethods(), getDeclaredFields() and getDeclaredConstructor() list its members.
method.invoke(target, args) calls a method; field.set(obj, value) writes a field; constructor.newInstance(args) creates an object.
setAccessible(true) bypasses private. Modern Java restricts this for JDK internals through the module system.
Annotation processing at run time is reflection: m.isAnnotationPresent(Test.class) is how test runners find tests.
Going deeper
Reflection hides dependencies from the compiler: renaming a method breaks code that looks it up by a string, and the error appears only at run time. It is also slower than a direct call and defeats some optimisations, so cache Method objects.
Security: reflective access to private members can break encapsulation; never build class names or method names from user input.
For code that must run fast, prefer method handles or generate code; GraalVM native-image needs reflection to be declared up front.
Under the hood
Class objects are created by the class loader. After a few calls Method.invoke is compiled to a generated accessor, and since Java 18 it uses method handles. Exceptions from the target method are wrapped in InvocationTargetException.
Common mistakes
- Catching
InvocationTargetExceptionand forgetting to look atgetCause(). - Looking up members by string and losing refactoring safety.
- Calling
getMethods()repeatedly in a hot path instead of caching.
How Unravel recognises it
When you paste code, Unravel looks for these signs of reflection. Spotting them yourself is a good habit when you read unfamiliar code:
- Types:
MethodConstructorModifier - Method calls:
Class.forName()getDeclaredMethods()getDeclaredFields()getDeclaredMethod()getDeclaredField()getDeclaredConstructor()getMethods()getMethod()getAnnotation()isAnnotationPresent()setAccessible()newInstance()invoke()
Part of a learning path
- Object-oriented Java in depth ยท previous: Custom annotations ยท next: Dynamic proxies
Related concepts
Builds on this
Frequently asked questions
What is Reflection?
Reflection lets code look at classes, methods and fields by name at run time, and call or change them, without knowing them at compile time. Frameworks use it to find your annotated classes and create your objects.
What are the most common mistakes with Reflection?
Catching InvocationTargetException and forgetting to look at getCause(). Looking up members by string and losing refactoring safety. Calling getMethods() repeatedly in a hot path instead of caching.
How can I see Reflection in real code?
Paste your own Java into Unravel and it will point out where reflection appears, explain how it works at the detail level you choose, and draw the flow of the code around it.