skip to content

Dynamic Invocation & Instantiation

Field.get and set, Method.invoke and getDeclaredConstructor().newInstance() are how frameworks build and populate objects at runtime. Interviewers ask about the performance cost and why Class.newInstance was deprecated.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

How do you call a method on an object dynamically at runtime using reflection, and what does Method.invoke return?

level: juniorimportance: must knowfreq 60%

answer

  1. getMethod (public+inherited) vs getDeclaredMethod (any access, this class only)
  2. invoke(target, args); target null for static
  3. return is Object; void -> null; primitives boxed
  4. InvocationTargetException wraps the method's own throw — getCause()
  5. setAccessible(true) for non-public

basics

~20 s

Get a Method object from the class (e.g. clazz.getMethod("name", paramTypes)), then call method.invoke(target, args). The first argument is the object to call it on (null for static methods); it returns the method's result as an Object.

solid answer

~40 s

Reflection lets you call a method whose name you only know at runtime. You obtain a java.lang.reflect.Method via getMethod (public, including inherited) or getDeclaredMethod (any access level, declared on that class only), passing the method name and the parameter types as Class objects. Then you call method.invoke(target, args...): target is the receiving instance (null for a static method) and args are autoboxed Objects. The return value is always Object — you cast it, and a void method returns null. Primitive returns are boxed (int becomes Integer). Checked exceptions from the target are wrapped in InvocationTargetException; use getCause() to reach the real one. If the method is non-public you must call setAccessible(true) first (subject to module rules).

code

java · 6 lines
java
Method m = obj.getClass().getMethod("greet", String.class);
try {
    String out = (String) m.invoke(obj, "world"); // obj.greet("world")
} catch (InvocationTargetException e) {
    Throwable real = e.getCause(); // exception thrown inside greet()
}

go deeper

for a junior

Knows the basic recipe: getMethod, then invoke(target, args), result is Object, null target for static.

for a middle

Distinguishes getMethod vs getDeclaredMethod, knows primitives box/unbox, and unwraps InvocationTargetException via getCause().

for a senior

Explains the access-control interaction (setAccessible, module openness) and why exception wrapping exists; handles the full exception set cleanly.

for a principal

Discusses when reflective invocation is appropriate vs MethodHandles/codegen, caching Method objects, and module-system constraints in library design.

## What problem this solves Normally in Java you call a method by writing its name directly: `obj.doThing()`. The compiler checks it exists and links the call. **Reflection** is the Java API (in `java.lang.reflect`) that lets your program inspect and use classes, methods, and fields whose names it may not know until the program is already running. "Dynamic invocation" means: *call a method chosen at runtime*, for example a method whose name came from a config file or a plugin. ## Step 1 — get a `Class` object Everything starts from a `java.lang.Class` instance, which represents a loaded type. You get one via `obj.getClass()`, `MyType.class`, or `Class.forName("com.acme.MyType")`. ## Step 2 — get a `Method` object A `java.lang.reflect.Method` represents one method. Two lookups: - `clazz.getMethod(String name, Class<?>... parameterTypes)` — returns a **public** method, **including inherited** ones (searches superclasses/interfaces). - `clazz.getDeclaredMethod(String name, Class<?>... parameterTypes)` — returns a method of **any** access level (private, protected, package), but **only one declared directly on that class** (not inherited). You must pass the exact **parameter types** as `Class` objects so Java can find the right overload. For a method `greet(String, int)` you pass `String.class, int.class`. Primitives use their `.class` literal (`int.class`, not `Integer.class`). ## Step 3 — invoke ```java Object result = method.invoke(target, arg1, arg2); ``` - `target` is the **instance** the call runs on. For a **static** method pass `null`. - The remaining arguments are the call arguments, **autoboxed** into `Object` (an `int` argument is passed as an `Integer`). - The **return type is always `Object`**. You cast it to the type you expect. A `void` method returns `null`. A primitive return is **boxed** (an `int` result comes back as an `Integer`). ## Exceptions you must handle - `NoSuchMethodException` — thrown by the lookup if no matching method exists. - `IllegalAccessException` — the method isn't accessible from your code (e.g. it's private and you didn't enable access). - `IllegalArgumentException` — wrong target type or wrong argument types/count. - `InvocationTargetException` — **the most important one**: if the target method itself throws an exception, reflection catches it and rethrows it wrapped. Call `getCause()` to get the original exception. This wrapping exists so reflection can distinguish *"the call mechanism failed"* from *"your method threw."* ## Access control If you looked up a non-public member, you must call `method.setAccessible(true)` before invoking, which suppresses Java's access checks. Under the Java Platform Module System (Java 9+) this only works if the target package is **open** to your module; otherwise you get an `InaccessibleObjectException`. ## Full example ```java Method m = obj.getClass().getMethod("greet", String.class); String out = (String) m.invoke(obj, "world"); // calls obj.greet("world") ``` From this you can derive: how to call any named method, how primitives are boxed both ways, and why you unwrap `InvocationTargetException`.

  • Your invoked method throws an IllegalStateException. What exception does the caller of invoke() actually catch?
    InvocationTargetException. The real IllegalStateException is its getCause(). Reflection wraps any exception thrown by the target method so you can distinguish it from invocation-mechanism failures.
  • What's the difference between getMethod and getDeclaredMethod?
    getMethod returns only public methods but searches the whole hierarchy (inherited too). getDeclaredMethod returns methods of any access level but only those declared directly on that class, not inherited ones.

saying these in an interview costs you the question

  • Thinking the target method's checked exception propagates directly — it's wrapped in InvocationTargetException.
  • Passing Integer.class instead of int.class for a primitive parameter (overload won't be found).
  • Assuming getMethod finds private methods — it only finds public ones.
  • Forgetting that invoke returns Object and a void method returns null, not the receiver.

context

open as a page

Why is Class.newInstance() deprecated, and what is the modern way to create an instance reflectively?

level: middleimportance: must knowfreq 55%

basics

~10 s

Class.newInstance() is deprecated because it silently passes through any checked exception the constructor throws, breaking Java's checked-exception checking. Use clazz.getDeclaredConstructor(paramTypes).newInstance(args) instead, which wraps those exceptions in InvocationTargetException.

open as a page

How do you read and write a field (including a private one) reflectively, and what does setAccessible(true) actually do?

level: middleimportance: should knowfreq 45%

basics

~10 s

Get a Field via getDeclaredField("name"), call field.setAccessible(true) if it's private, then field.get(obj) to read and field.set(obj, value) to write. Pass null as the object for static fields.

open as a page

Why is reflective invocation slower than a direct call, and how can you reduce that cost in a hot path?

level: seniorimportance: should knowfreq 50%

basics

~20 s

Reflection is slower because each call does extra work the compiler normally does up front: looking up members, checking access, boxing arguments into an Object[], and it inhibits some JIT optimizations. To cut the cost, look up Method/Field/Constructor objects once and cache them, call setAccessible(true), and reuse them — or use MethodHandles/codegen for the hottest paths.

open as a page

When would you choose MethodHandles or VarHandle over the classic reflection API for dynamic invocation and field access?

level: principalimportance: nice to knowfreq 35%

basics

~20 s

Use classic reflection (Method/Field/Constructor) for occasional, flexible introspection like config parsing or scanning annotations. Use MethodHandles and VarHandle when you call/access repeatedly on a hot path and need speed, because they're strongly typed, JIT-inlinable, and (VarHandle) give controlled memory ordering for fields.

open as a page