Skip to Content
Course content

164: Java Reflection API Basics

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I see a lot of developers treat the Reflection API like a read-only library—something you use just to inspect a class's metadata or print out a list of methods for debugging. They think of it as a "telescope" for looking at code from a distance.

Reflection is not a read-only telescope

The biggest misconception here is that Reflection is passive. You might think, "Sure, I can see that a field is private, but I still can't actually change it because the Java compiler and the JVM protect it." This is wrong. Reflection isn't just for looking; it's for intervening.

Take this simple class. In any normal scenario, the secretCode is safely tucked away. No matter what you do in your main logic, you cannot touch that integer without a setter method.

public class Vault {
    private int secretCode = 1234;
}

If you tried vaultInstance.secretCode = 5678;, the compiler would scream at you. But with Reflection, we can effectively tell the JVM to ignore those access modifiers entirely. I've used this technique countless times when writing unit tests for legacy code where the original author forgot to provide hooks for testing. It's a powerful, if slightly dangerous, superpower.

Breaking the rules with the setAccessible hammer

To actually manipulate the runtime behavior, you need to move beyond Class.getName() and start using the java.lang.reflect package. The real "magic" happens when you use setAccessible(true).

Here is how we actually bypass that private modifier from the previous example:

Vault myVault = new Vault();
Field field = Vault.class.getDeclaredField("secretCode");

// This is the line that breaks the "read-only" myth
field.setAccessible(true); 

// Now we can change the value of a private field on a specific instance
field.set(myVault, 9999);

System.out.println("The vault code is now: " + field.get(myVault)); 
// Output: The vault code is now: 9999

I'll be honest with you: using this in production application logic is usually a sign of bad design. If you're constantly bypassing private, your architecture is probably leaking. However, this is exactly how frameworks like Spring or Hibernate work. They don't ask you to make every field public; they just use Reflection to inject dependencies or map database columns directly into your private fields.

Walking the class anatomy at runtime

Beyond just flipping switches on private fields, Reflection allows you to treat methods and constructors as objects themselves. You can find a method by its name, check its parameter types, and execute it (invoke it) on an instance of a class without ever having known that class existed at compile time.

Think about a plugin system. You don't know which classes the user will drop into the /plugins folder. You just know that every plugin must have a method called initialize(). You can achieve this by doing the following:

  • Use Class.forName("com.user.PluginImpl") to load the class by its string name.
  • Use getDeclaredMethod("initialize") to grab a reference to that specific logic.
  • Use method.invoke(pluginInstance) to actually run the code.

One warning: Reflection is slower than direct method calls. The JVM can't optimize these calls as easily because it doesn't know which method is being called until the code is actually running. Use it where flexibility is more important than raw nanosecond performance.




📋 Practical Task

Build a Dynamic Method Invoker

Your goal is to create a system that can call any method on an object based on a string input, simulating how a basic command-line interface or a remote procedure call (RPC) system works.

Requirements:

  • Create a class named Robot with three methods: moveForward(), turnLeft(), and beep(). These methods should simply print a message to the console (e.g., "Robot is moving forward!").
  • In your main class, instantiate the Robot.
  • Create a method called executeCommand(Object target, String methodName). This method must use the Reflection API to find the method with the name provided in the string and invoke it on the target object.
  • If the method name provided doesn't exist in the class, catch the NoSuchMethodException and print "Command not recognized".
  • Test your executeCommand method by passing in "moveForward", "beep", and a fake command like "dance" to ensure your error handling works.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.