Nearby lessons

106 of 125

Java - Reflection API

📌 What You Will Learn
  • What reflection means
  • How to inspect a class at run time
  • Creating objects and calling methods with reflection
  • Why reflection powers every big framework

Reflection API is a core concept of the Java language. This lesson explains What is Reflection?, Normal Code vs Reflective Code and The Gate — Class Object with complete, runnable code examples, clear step-by-step explanations, and common mistakes to avoid with exam-style MCQs at the end.

What is Reflection?

Reflection is the ability of a Java program to look at itself while it is running — to find out the methods, fields and constructors of a class, and even to use them, without knowing the class details at compile time.

In simple words: Reflection lets a program inspect and use its own classes while it is running — you can discover a class's methods and fields even if you did not know them when writing the code.

Think of a mirror: the program holds a mirror to its own classes and examines them at run time. All of this lives in the java.lang.reflect package.

Normal code says: I know exactly which class I am using. Reflective code says: Let me first find out what this class has, then I will decide what to do.

Normal Code vs Reflective Code

PointNormal (direct) codeReflection code
What you knowThe class name and types at compile timeThe class is known only at run time
How objects are madenew ClassName()Class.forName(...).newInstance()
Compiler checks?Yes — mistakes found at compile timeNo — mistakes appear at run time
SpeedFastSlower
When usedEveryday programmingFrameworks, tools, testing

The Gate — Class Object

Every loaded class has a Class object that holds its full description. We get it in three ways:

In simple words: The `Class` object is the doorway to reflection. Everything — methods, fields, constructors — is reached through it, and you get it from .class, getClass() or Class.forName().
Example03
JCode Cell
1// Way 1 - using the .class literal
2Class<?> c1 = String.class;
3 
4// Way 2 - using the object's getClass()
5String s = "hello";
6Class<?> c2 = s.getClass();
7 
8// Way 3 - using Class.forName() with the full class name
9Class<?> c3 = Class.forName("java.lang.String");

Inspecting a Class

Example04
JCode Cell
1import java.lang.reflect.*;
2 
3class ReflectDemo {
4 public static void main(String[] args) throws Exception {
5 Class<?> c = Class.forName("java.util.ArrayList");
6 
7 System.out.println("Class name: " + c.getName());
8 System.out.println("Super class: " + c.getSuperclass().getName());
9 
10 System.out.println("\n--- Public methods ---");
11 for (Method m : c.getMethods()) {
12 System.out.println(m.getName() + "()");
13 }
14 }
15}
Output
Class name: java.util.ArrayList Super class: java.util.AbstractList --- Public methods --- add() get() size() remove() ... (many methods printed)

Creating an Object and Calling a Method

With reflection we can create an object even when we know the class only as a string, and call its methods using invoke().

In simple words: With reflection, the class name can be a plain string. Class.forName(...) loads it, newInstance() builds the object, and invoke() calls a method — no compile-time new needed.
Example05
JCode Cell
1import java.lang.reflect.*;
2 
3class ReflectUse {
4 public static void main(String[] args) throws Exception {
5 // load the class by name
6 Class<?> c = Class.forName("java.util.ArrayList");
7 
8 // create an object without knowing the type at compile time
9 Object list = c.getDeclaredConstructor().newInstance();
10 
11 // find the add method (one Object parameter)
12 Method add = c.getMethod("add", Object.class);
13 add.invoke(list, "Hello");
14 add.invoke(list, "World");
15 
16 Method size = c.getMethod("size");
17 System.out.println("Size = " + size.invoke(list));
18 }
19}
Output
Size = 2

Private Members — The Power (and Danger)

Reflection can even access private fields and methods by calling setAccessible(true). This is powerful but must be used carefully — it breaks encapsulation.

In simple words: `setAccessible(true)` unlocks private fields and methods for reflection. It is powerful for frameworks and testing, but it breaks encapsulation, so use it with care.
Example06
JCode Cell
1import java.lang.reflect.*;
2 
3class Secret {
4 private String password = "secret123";
5}
6 
7class HackDemo {
8 public static void main(String[] args) throws Exception {
9 Secret s = new Secret();
10 Field f = Secret.class.getDeclaredField("password");
11 f.setAccessible(true); // unlock the private field
12 System.out.println("Read: " + f.get(s));
13 f.set(s, "changed");
14 System.out.println("Set to: " + f.get(s));
15 }
16}
Output
Read: secret123 Set to: changed

Why Reflection Matters — The Framework Secret

Reflection is the engine behind every big framework. Here is the insight:

  • JUnit uses reflection to find and run all methods starting with @Test.
  • Spring uses reflection to create objects (beans) from classes and to inject dependencies.
  • Hibernate uses reflection to map your class fields to database columns.
  • Annotations (Chapter 20) are processed at run time using reflection.
Trainer's Note: This is how Spring creates objects without you writing new. The framework reads the class, checks its annotations, and builds everything with reflection. So when you learn reflection, you are actually learning how frameworks work from inside.

Performance Note

Reflection is slower than normal code and the compiler cannot check it (so errors appear at run time). Real applications therefore use reflection at startup time (to build objects), then switch to normal calls for the rest of the program.

Reading Fields, Methods and Modifiers

Beyond listing methods, reflection can inspect a class's fields, their modifiers, and a method's parameters — this is exactly what frameworks do to understand your class:

getDeclaredFields() gives all fields (even private), Modifier.toString(...) turns access flags into words like public final, and getParameterTypes() lists a method's parameters. These three calls are the heart of framework inspection.

Example09
JCode Cell
1import java.lang.reflect.*;
2 
3class InspectDemo {
4 public static void main(String[] args) throws Exception {
5 Class<?> c = Class.forName("java.util.ArrayList");
6 
7 System.out.println("--- Fields ---");
8 for (Field f : c.getDeclaredFields()) {
9 System.out.println(Modifier.toString(f.getModifiers()) + " " + f.getName());
10 }
11 
12 System.out.println("--- Method signatures ---");
13 for (Method m : c.getDeclaredMethods()) {
14 System.out.println(m.getReturnType().getSimpleName() + " " + m.getName()
15 + "(" + java.util.Arrays.toString(m.getParameterTypes()) + ")");
16 }
17 }
18}
📝 Key Takeaways
  • Reflection lets a program inspect and use its classes at run time.
  • The Class object (Class.forName, .class, getClass()) is the gateway.
  • We can list methods/fields, create objects, and call methods with invoke().
  • setAccessible(true) reaches private members — powerful but risky.
  • Reflection powers frameworks: JUnit, Spring, Hibernate, annotation processing.
  • It is slower and unchecked, so use it at startup, not in hot loops.

🧠 Test Your Knowledge

8 Questions
Progress: 0 / 8