Understanding Java Reflection Mechanism and Its Practical Applications

This article explains Java's reflection mechanism, outlines its capabilities such as runtime class inspection, object instantiation, method invocation, and dynamic proxy creation, and provides numerous code examples demonstrating how to retrieve class information, manipulate fields, invoke methods, and apply reflection in patterns like factories.

Java Captain
Java Captain
Java Captain
Understanding Java Reflection Mechanism and Its Practical Applications

1. What is the reflection mechanism

Reflection in Java allows a program, while running, to discover all attributes and methods of any class and to invoke them dynamically on any object.

2. What can reflection do

Determine the class of any object at runtime.

Instantiate objects of any class at runtime.

Inspect the fields and methods that a class possesses.

Invoke any method on an object at runtime.

Create dynamic proxies.

3. Related APIs and code examples

Obtaining a class name from an object:

package net.xsoftlab.baike;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        TestReflect testReflect = new TestReflect();
        System.out.println(testReflect.getClass().getName());
        // Result: net.xsoftlab.baike.TestReflect
    }
}

Instantiating a Class object:

package net.xsoftlab.baike;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        Class<?> class1 = null;
        Class<?> class2 = null;
        Class<?> class3 = null;
        // Common ways
        class1 = Class.forName("net.xsoftlab.baike.TestReflect");
        class2 = new TestReflect().getClass();
        class3 = TestReflect.class;
        System.out.println("Class name   " + class1.getName());
        System.out.println("Class name   " + class2.getName());
        System.out.println("Class name   " + class3.getName());
    }
}

Getting a class's superclass and implemented interfaces:

package net.xsoftlab.baike;
import java.io.Serializable;
public class TestReflect implements Serializable {
    private static final long serialVersionUID = -2862585049955236662L;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        // Superclass
        Class<?> parentClass = clazz.getSuperclass();
        System.out.println("Superclass: " + parentClass.getName());
        // Interfaces
        Class<?>[] interfaces = clazz.getInterfaces();
        System.out.println("Implemented interfaces:");
        for (int i = 0; i < interfaces.length; i++) {
            System.out.println((i + 1) + ": " + interfaces[i].getName());
        }
    }
}

Instantiating an object via reflection and using constructors:

package net.xsoftlab.baike;
import java.lang.reflect.Constructor;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        Class<?> class1 = Class.forName("net.xsoftlab.baike.User");
        // Default constructor
        User user = (User) class1.newInstance();
        user.setAge(20);
        user.setName("Rollen");
        System.out.println(user);
        // All constructors
        Constructor<?>[] cons = class1.getConstructors();
        for (int i = 0; i < cons.length; i++) {
            Class<?>[] paramTypes = cons[i].getParameterTypes();
            System.out.print("cons[" + i + "] (");
            for (int j = 0; j < paramTypes.length; j++) {
                System.out.print(paramTypes[j].getName());
                if (j < paramTypes.length - 1) System.out.print(",");
            }
            System.out.println(")");
        }
        user = (User) cons[0].newInstance("Rollen");
        System.out.println(user);
        user = (User) cons[1].newInstance(20, "Rollen");
        System.out.println(user);
    }
}
class User {
    private int age;
    private String name;
    public User() { }
    public User(String name) { this.name = name; }
    public User(int age, String name) { this.age = age; this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    @Override
    public String toString() { return "User [age=" + age + ", name=" + name + "]"; }
}

Retrieving all fields of a class:

package net.xsoftlab.baike;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class TestReflect implements Serializable {
    private static final long serialVersionUID = -2862585049955236662L;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        System.out.println("=== Declared fields ===");
        Field[] fields = clazz.getDeclaredFields();
        for (Field f : fields) {
            int mod = f.getModifiers();
            String priv = Modifier.toString(mod);
            Class<?> type = f.getType();
            System.out.println(priv + " " + type.getName() + " " + f.getName() + ";");
        }
        System.out.println("=== Public fields (including inherited) ===");
        Field[] publicFields = clazz.getFields();
        for (Field f : publicFields) {
            int mod = f.getModifiers();
            String priv = Modifier.toString(mod);
            Class<?> type = f.getType();
            System.out.println(priv + " " + type.getName() + " " + f.getName() + ";");
        }
    }
}

Retrieving all methods of a class:

package net.xsoftlab.baike;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class TestReflect implements Serializable {
    private static final long serialVersionUID = -2862585049955236662L;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        Method[] methods = clazz.getMethods();
        for (Method m : methods) {
            Class<?> retType = m.getReturnType();
            Class<?>[] params = m.getParameterTypes();
            int mods = m.getModifiers();
            System.out.print(Modifier.toString(mods) + " ");
            System.out.print(retType.getName() + " ");
            System.out.print(m.getName() + " (");
            for (int i = 0; i < params.length; i++) {
                System.out.print(params[i].getName() + " arg" + i);
                if (i < params.length - 1) System.out.print(", ");
            }
            Class<?>[] ex = m.getExceptionTypes();
            if (ex.length > 0) {
                System.out.print(") throws ");
                for (int i = 0; i < ex.length; i++) {
                    System.out.print(ex[i].getName());
                    if (i < ex.length - 1) System.out.print(", ");
                }
            } else {
                System.out.print(")");
            }
            System.out.println();
        }
    }
}

Invoking a method via reflection:

package net.xsoftlab.baike;
import java.lang.reflect.Method;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        Method m1 = clazz.getMethod("reflect1");
        m1.invoke(clazz.newInstance());
        Method m2 = clazz.getMethod("reflect2", int.class, String.class);
        m2.invoke(clazz.newInstance(), 20, "张三");
    }
    public void reflect1() { System.out.println("Java reflection - invoke method1."); }
    public void reflect2(int age, String name) {
        System.out.println("Java reflection - invoke method2.");
        System.out.println("age -> " + age + ". name -> " + name);
    }
}

Manipulating a private field via reflection:

package net.xsoftlab.baike;
import java.lang.reflect.Field;
public class TestReflect {
    private String property = null;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        Object obj = clazz.newInstance();
        Field field = clazz.getDeclaredField("property");
        field.setAccessible(true);
        field.set(obj, "Java reflection");
        System.out.println(field.get(obj));
    }
}

Dynamic proxy example using reflection:

// Get class loader
TestReflect testReflect = new TestReflect();
System.out.println("ClassLoader " + testReflect.getClass().getClassLoader().getClass().getName());
package net.xsoftlab.baike;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Subject {
    String say(String name, int age);
}
class RealSubject implements Subject {
    public String say(String name, int age) { return name + " " + age; }
}
class MyInvocationHandler implements InvocationHandler {
    private Object obj = null;
    public Object bind(Object obj) {
        this.obj = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(this.obj, args);
    }
}
public class TestReflect {
    public static void main(String[] args) throws Exception {
        MyInvocationHandler demo = new MyInvocationHandler();
        Subject sub = (Subject) demo.bind(new RealSubject());
        String info = sub.say("Rollen", 20);
        System.out.println(info);
    }
}

4. Application examples

Adding a String to an ArrayList<Integer> via reflection:

package net.xsoftlab.baike;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        ArrayList<Integer> list = new ArrayList<Integer>();
        Method addMethod = list.getClass().getMethod("add", Object.class);
        addMethod.invoke(list, "Java reflection example.");
        System.out.println(list.get(0));
    }
}

Inspecting and modifying an array via reflection:

package net.xsoftlab.baike;
import java.lang.reflect.Array;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        int[] temp = {1,2,3,4,5};
        Class<?> comp = temp.getClass().getComponentType();
        System.out.println("Array type: " + comp.getName());
        System.out.println("Length: " + Array.getLength(temp));
        System.out.println("First element: " + Array.get(temp, 0));
        Array.set(temp, 0, 100);
        System.out.println("After modification: " + Array.get(temp, 0));
    }
}

Changing array size with reflection:

package net.xsoftlab.baike;
import java.lang.reflect.Array;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        int[] temp = {1,2,3,4,5,6,7,8,9};
        int[] newTemp = (int[]) arrayInc(temp, 15);
        print(newTemp);
        String[] arr = {"a","b","c"};
        String[] str1 = (String[]) arrayInc(arr, 8);
        print(str1);
    }
    public static Object arrayInc(Object obj, int len) {
        Class<?> comp = obj.getClass().getComponentType();
        Object newArr = Array.newInstance(comp, len);
        int oldLen = Array.getLength(obj);
        System.arraycopy(obj, 0, newArr, 0, oldLen);
        return newArr;
    }
    public static void print(Object obj) {
        Class<?> c = obj.getClass();
        if (!c.isArray()) return;
        System.out.println("Array length: " + Array.getLength(obj));
        for (int i = 0; i < Array.getLength(obj); i++) {
            System.out.print(Array.get(obj, i) + " ");
        }
        System.out.println();
    }
}

Using reflection in a factory pattern to create objects without modifying the factory class:

package net.xsoftlab.baike;
interface Fruit { void eat(); }
class Apple implements Fruit { public void eat() { System.out.println("Apple"); } }
class Orange implements Fruit { public void eat() { System.out.println("Orange"); } }
class Factory {
    public static Fruit getInstance(String className) {
        try { return (Fruit) Class.forName(className).newInstance(); }
        catch (Exception e) { e.printStackTrace(); return null; }
    }
}
public class TestReflect {
    public static void main(String[] args) throws Exception {
        Fruit f = Factory.getInstance("net.xsoftlab.baike.Apple");
        if (f != null) f.eat();
    }
}

The article concludes with a promotional block for a Java community, which is not part of the technical content.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend DevelopmentReflectionCode ExampleDynamic Proxy
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.