Accessing Methods, Fields, and Constructors in Java Using Reflection with Examples

Illustration for Accessing Methods, Fields, and Constructors in Java Using Reflection with Examples
By Last updated:

A common mistake developers make with Reflection is assuming it is only about loading classes dynamically. In reality, one of its most powerful features is the ability to access methods, fields, and constructors at runtime—even private ones. Misunderstanding or misusing this can lead to serious bugs, such as breaking encapsulation or causing performance bottlenecks.

In real-world frameworks:

  • Spring uses reflection to inject dependencies into fields and call lifecycle methods.
  • Hibernate uses it to populate entity fields directly from database results.
  • JUnit discovers and invokes test methods at runtime using reflection.

Reflection acts like having the master key to a locked house—you can open any door (constructor), peek inside any drawer (field), or flip any switch (method), even those that were originally private. With great power comes great responsibility, and knowing how to correctly access and use these objects is critical for building safe and efficient Java applications.


Accessing Methods Using Reflection

Example: Invoking Public and Private Methods

import java.lang.reflect.Method;

class UserService {
    public void greet(String name) {
        System.out.println("Hello, " + name);
    }

    private String getSecret() {
        return "Top Secret!";
    }
}

public class MethodExample {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = UserService.class;
        UserService userService = new UserService();

        // Access public method
        Method greetMethod = clazz.getMethod("greet", String.class);
        greetMethod.invoke(userService, "Alice");

        // Access private method
        Method secretMethod = clazz.getDeclaredMethod("getSecret");
        secretMethod.setAccessible(true);
        System.out.println(secretMethod.invoke(userService));
    }
}

Output:

Hello, Alice
Top Secret!

Real-World Use

  • JUnit calls test methods annotated with @Test.
  • Spring uses reflective method invocation for lifecycle callbacks like @PostConstruct.

Accessing Fields Using Reflection

Example: Reading and Modifying Fields

import java.lang.reflect.Field;

class Product {
    private String name = "Default";

    @Override
    public String toString() {
        return "Product{name='" + name + "'}";
    }
}

public class FieldExample {
    public static void main(String[] args) throws Exception {
        Product product = new Product();
        Class<?> clazz = product.getClass();

        // Access private field
        Field field = clazz.getDeclaredField("name");
        field.setAccessible(true);
        field.set(product, "Laptop");

        System.out.println(product);
    }
}

Output:

Product{name='Laptop'}

Real-World Use

  • Hibernate sets private entity fields without using setters.
  • Serialization frameworks like Jackson use reflection to read/write object fields.

Accessing Constructors Using Reflection

Example: Instantiating Objects Dynamically

import java.lang.reflect.Constructor;

class Order {
    private int id;
    private String customer;

    public Order(int id, String customer) {
        this.id = id;
        this.customer = customer;
    }

    @Override
    public String toString() {
        return "Order{id=" + id + ", customer='" + customer + "'}";
    }
}

public class ConstructorExample {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Order.class;

        Constructor<?> constructor = clazz.getConstructor(int.class, String.class);
        Object order = constructor.newInstance(101, "John Doe");

        System.out.println(order);
    }
}

Output:

Order{id=101, customer='John Doe'}

Real-World Use

  • Spring creates beans dynamically by invoking constructors.
  • Dependency injection frameworks resolve parameters and instantiate services via reflection.

📌 What's New in Java Versions?

  • Java 5 – Expanded reflection API to support annotations.
  • Java 8 – Introduced Executable as a superclass of Method and Constructor.
  • Java 9 – Strong encapsulation in modules restricted reflective access (warnings for setAccessible(true)).
  • Java 11 – No major changes for reflection.
  • Java 17 – Further restrictions under strong encapsulation (--add-opens required for deep reflection).
  • Java 21 – No significant updates for reflection.

Pitfalls and Best Practices

Pitfalls

  • Excessive use of reflection slows down applications.
  • Bypassing encapsulation can break security and maintainability.
  • Forgetting exception handling (NoSuchMethodException, IllegalAccessException).

Best Practices

  • Use reflection for framework-level logic, not regular application code.
  • Cache reflective lookups for performance.
  • Avoid overusing setAccessible(true); prefer public APIs.
  • Document reflection use in codebases for maintainability.

Summary + Key Takeaways

  • Reflection allows dynamic access to methods, fields, and constructors.
  • Frameworks like Spring, Hibernate, and JUnit rely on these capabilities.
  • While powerful, reflection should be used responsibly due to performance and security trade-offs.
  • Always prefer direct access when possible, and limit reflection to situations where dynamic behavior is essential.

FAQ

  1. How do I invoke a private method using reflection?
    Use getDeclaredMethod() and call setAccessible(true) before invoking.

  2. Can reflection modify private fields?
    Yes, with setAccessible(true), but this breaks encapsulation and should be used carefully.

  3. How does reflection handle constructors with parameters?
    Use getConstructor() with parameter types, then call newInstance().

  4. What is the difference between getDeclaredFields() and getFields()?
    getDeclaredFields() includes all fields (private, protected, public), while getFields() returns only public ones.

  5. Why is reflection slower than direct method calls?
    Reflection bypasses JVM optimizations and incurs security/validation checks at runtime.

  6. Is reflection safe in modular applications (Java 9+)?
    Not always—strong encapsulation may block reflective access unless modules explicitly export packages.

  7. How do frameworks like Hibernate use reflection?
    Hibernate sets fields directly to populate entities from database results.

  8. Can I use reflection for dependency injection?
    Yes, frameworks like Spring rely on it heavily for DI.

  9. What’s the risk of calling setAccessible(true)?
    It breaks encapsulation, may cause InaccessibleObjectException in Java 9+, and introduces security concerns.

  10. When should I avoid reflection?
    Avoid reflection in performance-critical loops, instead use standard APIs or design patterns.