Java
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented Java
-
Section 4: Collections Framework
-
Section 5: Exception Handling
-
Section 6: Generics
-
Section 7: Functional Java
-
Section 8: Concurrency
-
Section 9: I/O and NIO
-
Section 10: JVM Internals
-
Section 11: Modern Java Features
-
Section 12: Build Tools and Project Structure
-
Section 13: Testing
-
Section 14: Databases and Persistence
-
Section 15: Networking
-
Section 16: Design and Best Practices
-
Section 17: Reflection and Annotations
-
Section 18: Logging and Diagnostics
-
Section 19: Date, Time, and Internationalization
-
Section 20: Java Platform Module System
-
Section 21: Security in Java
-
Section 22: Advanced Collections and Data Structures
-
Section 23: More Concurrency Patterns
-
Section 24: Compression, Files, and System Integration
-
Section 25: GUI Programming
-
Section 26: Practical Projects
-
Section 27: Data Structures and Algorithms
-
Section 28: Interview and Algorithm Practice
-
Section 29: JSON and Data Interchange
-
Section 30: More Concurrency Utilities
-
Section 31: More Collections and Streams Practice
-
Section 32: More File and System Programming
-
Section 33: Standard Library Deep Dive
-
Section 34: More Practice and Drills
-
Section 35: More Testing and Quality
-
Section 36: More Design Patterns and Architecture
-
Section 37: Career and Ecosystem
-
Section 38: More OOP and Architecture Practice
-
Section 39: More Enterprise Concepts
-
Section 40: Advanced JavaFX
-
Section 41: More Interview Practice
164: Java Reflection API Basics
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
Robotwith three methods:moveForward(),turnLeft(), andbeep(). 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
NoSuchMethodExceptionand print "Command not recognized". - Test your
executeCommandmethod by passing in "moveForward", "beep", and a fake command like "dance" to ensure your error handling works.
There are no comments for now.