Lesson 31 • Advanced

    Reflection API

    Inspect and manipulate classes, methods, and fields at runtime — the engine behind Spring, Hibernate, and JUnit.

    Before You Start

    You should understand OOP & Interfaces (Lessons 9–11), Annotations basics, and JVM Internals (Lesson 30). Reflection operates at the JVM level, bypassing normal compile-time checks.

    What You'll Learn

    • ✅ Getting Class objects at runtime
    • ✅ Inspecting fields, methods, and constructors
    • ✅ Invoking methods dynamically
    • ✅ Accessing private members with setAccessible
    • ✅ Creating instances without the new keyword
    • ✅ Performance implications and security concerns

    1️⃣ What is Reflection?

    💡 Analogy: Opening the Remote

    Normally you use objects like a TV remote — press buttons without knowing internals. Reflection is like opening the case: you can see every chip and wire, and even rewire things. Powerful, but you can break things if you're not careful.

    With reflection, code written before your class existed can still work with it. That's how Spring creates beans, Hibernate maps entities, and JUnit finds @Test methods — all without hardcoded references.

    Use for: Frameworks, serialization, testing tools, plugin systems

    Don't use for: Regular application logic — prefer interfaces and polymorphism

    Try It: Inspecting & Invoking

    Try it Yourself »
    JavaScript
    // Reflection — Inspecting & Invoking
    console.log("=== Reflection: Inspect & Invoke ===\n");
    
    class User {
        constructor(name, age) {
            this.name = name;
            this.age = age;
            this._secret = "hidden123";
        }
        greet() { return "Hi, I'm " + this.name; }
        getAge() { return this.age; }
        _privateMethod() { return "secret: " + this._secret; }
    }
    
    let user = new User("Alice", 30);
    
    // 1. Get class info
    console.log("1. INSPECTING CLASS:");
    console.log("  Class name:", user.co
    ...

    2️⃣ Core Reflection Operations

    OperationAPINotes
    Get classClass.forName("pkg.MyClass")By fully-qualified name
    List methodsgetDeclaredMethods()Including private (not inherited)
    Get fieldfield.get(obj)May need setAccessible(true)
    Invokemethod.invoke(obj, args)Dynamic dispatch by string name
    Createconstructor.newInstance()No-arg or parameterized

    Try It: Dynamic Proxy & Framework Patterns

    Try it Yourself »
    JavaScript
    // Dynamic Proxy & Framework Patterns
    console.log("=== Framework Patterns ===\n");
    
    // 1. Simple DI container (like Spring)
    console.log("1. MINI DEPENDENCY INJECTION CONTAINER:");
    
    class DIContainer {
        constructor() { this.registry = new Map(); }
        register(name, factory) { this.registry.set(name, factory); }
        resolve(name) {
            let factory = this.registry.get(name);
            if (!factory) throw new Error("No bean: " + name);
            return factory(this);
        }
    }
    
    class UserRepositor
    ...

    Try It: Performance & Caching

    Try it Yourself »
    JavaScript
    // Reflection Performance & Best Practices
    console.log("=== Reflection Performance ===\n");
    
    class Calculator {
        add(a, b) { return a + b; }
        multiply(a, b) { return a * b; }
    }
    
    let calc = new Calculator();
    
    // 1. Direct vs reflective call performance
    console.log("1. PERFORMANCE COMPARISON:");
    let iterations = 100000;
    
    let t1 = performance.now();
    for (let i = 0; i < iterations; i++) calc.add(i, i);
    let directTime = (performance.now() - t1).toFixed(2);
    
    let methodName = "add";
    let t2 = perf
    ...

    Common Mistakes

    Not caching Method objects: Reflection lookup is expensive. Cache Method and Field objects if called repeatedly.
    setAccessible in production code: Bypasses encapsulation and breaks with Java modules. Use public APIs instead.
    String-based method names: Typos only surface at runtime. Use constants or annotations to reduce risk.

    Pro Tips

    💡 MethodHandle (Java 7+) is faster than reflection and JIT-optimizable — use for performance-sensitive reflective calls.

    💡 Proxy.newProxyInstance() creates interface implementations at runtime — the foundation of Spring AOP.

    💡 Compile-time annotation processing (Lombok, MapStruct) generates code with zero runtime cost.

    📋 Quick Reference

    ConceptAPINotes
    Get ClassClass.forName("pkg.MyClass")By fully-qualified name
    List fieldsgetDeclaredFields()Including private
    Invokemethod.invoke(obj, args...)Dynamic dispatch
    Bypass accesssetAccessible(true)Use with caution
    ProxyProxy.newProxyInstance()Dynamic interface impl

    🎉 Lesson Complete!

    You've mastered Java's Reflection API — the engine behind every major framework!

    Next: Annotations — creating and processing metadata for cleaner, declarative code.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service