HuntExams Academy logo
JavaAdvanced#jvm

What is reflection in Java?

Answer

API to inspect and modify classes, methods, and fields at runtime. Used by frameworks (Spring, Hibernate) and serializers. Comes with performance and security trade-offs.

Example

Class<?> clazz = Class.forName("java.util.ArrayList");
Method[] methods = clazz.getDeclaredMethods();
Object instance = clazz.getDeclaredConstructor().newInstance();

Detailed explanation

Reflection in Java is the ability to inspect a program’s types and interact with their members at runtime, even when those types are not known at compile time. Its main entry point is a Class<?> object, which represents a loaded type. Through this object and APIs in java.lang.reflect, you can discover constructors, methods, fields, modifiers, and runtime-retained annotations. You can also create instances, invoke methods, and read or update permitted field values. Reflection does not, by itself, rewrite method bodies or add members to an existing class.

You can obtain a Class object using SomeType.class, object.getClass(), or Class.forName("fully.qualified.Name"). In the supplied example, Class.forName("java.util.ArrayList") loads and normally initializes ArrayList, getDeclaredMethods() retrieves methods declared directly by that class, and getDeclaredConstructor().newInstance() invokes its no-argument constructor. getDeclaredMethods() includes non-public declarations but excludes inherited methods; getMethods() returns public methods, including inherited ones. To invoke a particular method, look it up using its name and parameter types, then call Method.invoke(receiver, arguments). For a static method, the receiver can be null.

Under the hood, reflection exposes runtime type information maintained by the JVM. Instead of resolving every operation through ordinary, statically checked Java expressions, your code performs member lookup and supplies targets and arguments dynamically. This enables frameworks to provide generic behaviour: Spring can inspect constructors and annotations for dependency injection, Hibernate can access entity state, and serializers can discover properties without hard-coding every application class. These tools may also use generated code or method handles rather than reflection for every operation.

The trade-offs are weaker compile-time guarantees, additional runtime failure paths, and possible performance overhead from lookup, invocation machinery, and argument handling. The cost depends on the operation and JVM, so avoid claiming reflection is always prohibitively slow. Access checks still apply: setAccessible(true) can suppress certain checks, but Java’s module boundaries may prevent it. Reflective code must handle failures such as missing members and InvocationTargetException, which wraps an exception thrown by an invoked method or constructor. Interviewers usually expect practical uses, API distinctions, and these limitations.

Key points to remember

  • Class<?> is the entry point; Method, Field, and Constructor provide reflective operations.
  • Reflection supports runtime inspection, object construction, method invocation, and permitted field access.
  • getDeclaredMethods() lists directly declared methods of all visibilities; getMethods() includes inherited public methods.
  • Frameworks use reflection to discover annotations, inject dependencies, map entities, and serialize objects.
  • Reflection trades compile-time checking and straightforward access for flexibility, with runtime, performance, and encapsulation concerns.

Common mistakes candidates make

  • Claiming reflection can freely change class definitions or bypass every access restriction.
  • Confusing getDeclaredMethods() with getMethods(), especially regarding inheritance and visibility.
  • Ignoring runtime exceptions and access failures, or claiming reflective calls have a fixed performance penalty.

Likely follow-up questions

Can reflection access private fields?

A private field can be discovered with getDeclaredField(), but discovery does not grant access to its value. setAccessible(true) may enable access, while module restrictions can block it; trySetAccessible() returns false when access cannot be enabled.

What happens when a reflectively invoked method throws an exception?

Method.invoke() wraps the exception thrown by the target method in InvocationTargetException. Use getCause() to inspect the original failure, and distinguish it from reflection failures such as IllegalAccessException.

How can you reduce reflection overhead?

Cache resolved Method, Field, or Constructor objects instead of repeatedly looking them up. For frequently executed paths, consider ordinary calls, generated code, or method handles, and benchmark on the target JVM rather than assuming one approach is always faster.

Interview tip: Define reflection first, walk through the supplied example, then explain one framework use and the access, runtime-safety, and performance trade-offs.

Related Interview Questions

1
JavaIntermediate#generics

What are Java generics?

Open
2
JavaAdvanced#generics

Difference between '? extends T' and '? super T'?

Open
3
JavaAdvanced#concurrency#jvm

What is the Java Memory Model (JMM)?

Open