Fundamentals 16 min read

Unlock Java’s Power: Master Reflection for Dynamic Code

This article explains Java's reflection mechanism, showing how classes are represented by Class objects, how to obtain them at runtime, and demonstrates common reflective operations such as inspecting fields, constructors, methods, and arrays with practical code examples and typical interview questions.

Programmer DD
Programmer DD
Programmer DD
Unlock Java’s Power: Master Reflection for Dynamic Code

1. Concept

Reflection maps Java components to corresponding Class objects, enabling runtime inspection and manipulation of classes, fields, methods, and constructors.

Reflection is a Java language feature that allows a program to examine and modify its own structure at runtime, something not available in languages like Pascal, C, or C++.

JavaBean is a practical use of reflection, allowing tools to dynamically load and access component properties.

Reflection has existed since Java 1.2 and is used by many frameworks; the Class object represents a class or interface in a running JVM.

Basic Java types (boolean, byte, char, short, int, long, float, double) and void are also represented by Class objects. The Class object is created automatically by the JVM when a class is loaded.

Person p1 = new Person();
// three ways to obtain the bytecode
Class c1 = Date.class();
Class c2 = p1.getClass();
Class c3 = Class.forName("java.lang.String");

Using Class.forName() loads the bytecode into the JVM; if the class is not yet loaded, the class loader loads it.

2. Common Methods

1. isPrimitive() – checks whether a Class object represents a primitive type.

public class TestReflect {
    public static void main(String[] args) {
        String str = "abc";
        Class cls1 = str.getClass();
        Class cls2 = String.class;
        Class cls3 = null;
        try { cls3 = Class.forName("java.lang.String"); } catch (ClassNotFoundException e) { e.printStackTrace(); }
        System.out.println(cls1 == cls2); // true
        System.out.println(cls1 == cls3); // true
        System.out.println(cls1.isPrimitive()); // false
        System.out.println(int.class.isPrimitive()); // true
        System.out.println(int.class == Integer.class); // false
        System.out.println(int.class == Integer.TYPE); // true
        System.out.println(int[].class.isPrimitive()); // false
        System.out.println(int[].class.isArray()); // true
    }
}

2. getConstructor() / getConstructors() – retrieve constructors by parameter types.

public class TestReflect {
    public static void main(String[] args) throws Exception {
        String str = "abc";
        System.out.println(String.class.getConstructor(StringBuffer.class));
    }
}

3. Field – represents a member variable of a class.

import java.lang.reflect.Field;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        ReflectPointer rp1 = new ReflectPointer(3, 4);
        Field fieldX = rp1.getClass().getField("x");
        System.out.println(fieldX.get(rp1));
        Field fieldY = rp1.getClass().getDeclaredField("y");
        fieldY.setAccessible(true);
        System.out.println(fieldY.get(rp1));
    }
}
class ReflectPointer {
    public int x = 0;
    private int y = 0;
    public ReflectPointer(int x, int y) { this.x = x; this.y = y; }
}

3. Typical Exercises

1. Replace all ‘b’ with ‘a’ in String fields

import java.lang.reflect.Field;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        ReflectPointer rp1 = new ReflectPointer(3, 4);
        changeBtoA(rp1);
        System.out.println(rp1);
    }
    private static void changeBtoA(Object obj) throws Exception {
        for (Field field : obj.getClass().getFields()) {
            if (field.getType() == String.class) {
                String oldValue = (String) field.get(obj);
                String newValue = oldValue.replace('b', 'a');
                field.set(obj, newValue);
            }
        }
    }
}
class ReflectPointer {
    private int x = 0;
    public int y = 0;
    public String str1 = "ball";
    public String str2 = "basketball";
    public String str3 = "itcat";
    @Override
    public String toString() {
        return "ReflectPointer [str1=" + str1 + ", str2=" + str2 + ", str3=" + str3 + "]";
    }
}

2. Invoke the main method of a class given its name

import java.lang.reflect.Method;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        String className = args[0];
        Method m = Class.forName(className).getMethod("main", String[].class);
        m.invoke(null, (Object) new String[]{"111", "222", "333"});
    }
}
class Inter {
    public static void main(String[] args) {
        for (Object obj : args) {
            System.out.println(obj);
        }
    }
}

3. instanceof / isInstance

class S {}
public class IsInstance {
    public static void main(String[] args) {
        try {
            Class cls = Class.forName("S");
            System.out.println(cls.isInstance(new Integer(37))); // false
            System.out.println(cls.isInstance(new S())); // true
        } catch (Throwable e) { e.printStackTrace(); }
    }
}

4. Method Class

The Method class represents a method of a class (not an object).

import java.lang.reflect.Method;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        String str = "shfsfs";
        Method mtCharAt = String.class.getMethod("charAt", int.class);
        Object ch = mtCharAt.invoke(str, 1);
        System.out.println(ch);
        System.out.println(mtCharAt.invoke(str, new Object[]{2}));
    }
}

5. Array Reflection

The Array utility class helps perform reflective operations on arrays.

import java.util.Arrays;
public class TestReflect {
    public static void main(String[] args) {
        int[] a = new int[3];
        int[] b = new int[]{4,5,5};
        int[][] c = new int[3][2];
        String[] d = new String[]{"jjj", "kkkk"};
        System.out.println(a == b); // false
        System.out.println(a.getClass() == b.getClass()); // true
        System.out.println(a.getClass()); // class [I
        System.out.println(a.getClass().getName()); // [I
        System.out.println(a.getClass().getSuperclass()); // class java.lang.Object
        System.out.println(d.getClass().getSuperclass()); // class java.lang.Object
        System.out.println(Arrays.asList(b)); // [[I@...]
        System.out.println(Arrays.asList(d)); // [jjj, kkkk]
    }
}

6. Conclusion

Reflection is a core Java feature that enables dynamic behavior, widely used in frameworks such as Spring to instantiate objects and invoke methods based on configuration strings, thereby reducing coupling and increasing flexibility.

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.

ReflectionRuntimeTutorialcodeClass
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

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.