Java reflection mechanism

Published 2026-07-29 10:55 Updated 2026-10-13 17:14 1329 words 7 min read ... Page views AI-reviewed An AI proof-read this post, but it still deserves a careful read. AI-rewritten Someone else wrote the original; AI helped me rewrite and polish it.

AI-reviewed An AI proof-read this post, but it still deserves a careful read.

This article introduces the core concepts and usage methods of Java reflection mechanism, and explains how to dynamically obtain class information, create objects, access fields, and call methods at run time through Class objects. Combined with actual cases, this paper demonstrates the application of reflection in implementing a general DAO, but points out that it has limitations such as the consistency of class names and table names, strict field mapping, and emphasizes that attention should be paid to security, readability and exception handling when using reflection. It is recommended to use it only when necessary and the input needs to be strictly verified.

Java reflection mechanism

Overview of reflection

Java reflection refers to the mechanism by which a program obtains structural information of a class during runtime and dynamically creates objects, accesses fields, calls methods, or calls constructors.

Normally, the code is clear at compile time which type to use. Using reflection, a program can decide which class to load at run time based on the class name or configuration file, so reflection is often used in frameworks, dependency injection, object mapping, and common tool classes.

Loading of classes and Class object

When the JVM loads a class, it creates a unique class for that type. Class object.Class Objects hold structural information such as class names, fields, methods, constructors, and annotations, and are entrances to using reflection.

obtain Class object

by Class.forName() obtain

try {
    Class<?> personClass = Class.forName("com.hyxy.Person");
    System.out.println(personClass.getName());
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

This method loads the class through the full class name, which is suitable for scenarios where the class name comes from the configuration file or the target type cannot be directly referenced at compile time.

Obtained through class literals

Class<Person> personClass = Person.class;

When the target type is already known at compile time, use the 类型.class The most direct and will not throw ClassNotFoundException。

Get through objects

Person person = new Person();
Class<?> personClass = person.getClass();

When you already hold an object but need to get its runtime type, you can call the getClass()。

public static void printType(Object object) {
    Class<?> objectClass = object.getClass();
    System.out.println(objectClass.getName());
}

Class Common methods for classes

methodrole
getName()Get the complete class name, including package name
getSimpleName()Gets the class name that does not contain the package name
getDeclaredField(String name)Gets the field with the specified name in the current class
getDeclaredFields()Gets all fields declared by the current class
getDeclaredMethod(String name, Class<?>... parameterTypes)Gets the method based on the method name and parameter type
getDeclaredMethods()Gets all methods declared by the current class
getDeclaredConstructor(Class<?>... parameterTypes)Gets the constructor based on the parameter type
getDeclaredConstructors()Gets all constructors declared by the current class

Class.newInstance() It’s outdated. When creating an object, you should first obtain the constructor and then call the constructor’s newInstance()。

Object object = personClass.getDeclaredConstructor().newInstance();

use Field operation field

each Field An object represents a field declared in a class. by Field You can obtain the field name, field type, and read or assign values to the fields of the specified object.

Common methods are as follows:

methodrole
getName()Get field name
getType()Get field type
setAccessible(true)Allow reflection access to non-public fields
set(Object object, Object value)Assign values to the fields of the specified object
get(Object object)Reads the field value of the specified object

the following example creates a Student Object and modify it through reflection name Fields:

package com.hyxy;

import java.lang.reflect.Field;

public class FieldTest {
    public static void main(String[] args) {
        try {
            Class<?> studentClass = Class.forName("com.hyxy.Student");
            Object student = studentClass.getDeclaredConstructor().newInstance();

            Field nameField = studentClass.getDeclaredField("name");
            nameField.setAccessible(true);
            nameField.set(student, "Tom");

            Object name = nameField.get(student);
            System.out.println(name);
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
    }
}

getDeclaredField() Fields declared by the current class, including private fields, can be obtained, but will not be automatically looked up to the parent class. Calling the setAccessible(true)。

use Method calling method

each Method An object represents a method in a class. call invoke() When, the first parameter is the object to which the method belongs, and the subsequent parameters are the arguments that need to be passed in to call the method.

package com.hyxy;

import java.lang.reflect.Method;

public class MethodTest {
    public static void main(String[] args) {
        try {
            Class<?> studentClass = Class.forName("com.hyxy.Student");
            Object student = studentClass.getDeclaredConstructor().newInstance();

            Method method1 = studentClass.getDeclaredMethod("study");
            Method method2 = studentClass.getDeclaredMethod(
                    "study",
                    String.class,
                    int.class
            );

            method1.setAccessible(true);
            method2.setAccessible(true);

            method1.invoke(student);
            method2.invoke(student, "Java", 24);
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
    }
}

When looking for overloaded methods, you must provide not only the method name, but also an accurate list of parameter types. During calling a method, exceptions thrown inside the target method are wrapped as InvocationTargetException。

For static methods, call invoke() When the first parameter can be passed in null。

method.invoke(null, "参数");

use Constructor create objects

each Constructor An object represents a constructor in a class. You can get the specified constructor through the parameter type, and then call the newInstance() Create objects.

package com.hyxy;

import java.lang.reflect.Constructor;

public class ConstructorTest {
    public static void main(String[] args) {
        try {
            Class<Student> studentClass = Student.class;
            Constructor<Student> constructor = studentClass.getDeclaredConstructor(
                    String.class,
                    int.class,
                    int.class
            );

            constructor.setAccessible(true);
            Student student = constructor.newInstance("Tom", 20, 110011);

            System.out.println(
                    student.getName() + "," +
                    student.getAge() + "," +
                    student.getNo()
            );
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
    }
}

Reflection implements universal DAO

basic ideas

Traditional DAOs usually write add, delete, modify, and check codes for each table separately. The universal DAO can read the class name and field information of entity classes through reflection, and then dynamically generate SQL.

A simple agreement is:

  • The entity class name corresponds to the table name.
  • Entity class field names correspond to column names.
  • The primary key field name is passed in by the caller.
  • Self-added primary keys are not passed in as a placeholder parameter when inserted.

In real projects, class names and table names, field names and column names are often not exactly the same, so the mapping is usually completed in conjunction with annotations.

Examples of common new methods

package com.hyxy.dao;

import org.apache.commons.dbutils.QueryRunner;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class CommonDao {
    public int insert(Object entity, String primaryKeyName, boolean autoIncrement) {
        Class<?> entityClass = entity.getClass();
        String tableName = entityClass.getSimpleName();
        Field[] fields = entityClass.getDeclaredFields();

        List<String> columnNames = new ArrayList<>();
        List<String> placeholders = new ArrayList<>();
        List<Object> parameterValues = new ArrayList<>();

        for (Field field : fields) {
            String fieldName = field.getName();

            if (autoIncrement && fieldName.equals(primaryKeyName)) {
                continue;
            }

            field.setAccessible(true);
            columnNames.add(fieldName);
            placeholders.add("?");

            try {
                parameterValues.add(field.get(entity));
            } catch (IllegalAccessException e) {
                throw new RuntimeException("读取字段失败:" + fieldName, e);
            }
        }

        String sql = "insert into " + tableName +
                "(" + String.join(",", columnNames) + ") values(" +
                String.join(",", placeholders) + ")";

        QueryRunner queryRunner = new QueryRunner();

        try (Connection connection = DBUtil.getConnection()) {
            return queryRunner.update(
                    connection,
                    sql,
                    parameterValues.toArray()
            );
        } catch (SQLException e) {
            throw new RuntimeException("执行新增操作失败", e);
        }
    }
}

This example shows the basic combination of reflection and JDBC encapsulation, but still has the following limitations:

  • The entity class name must be consistent with the table name.
  • The field name must be consistent with the column name.
  • Field order relies on reflection return results and should not be used as a fixed database order.
  • Real projects also need to deal with primary keys, inherited fields, static fields, transactions, and exception regimes.
  • Table names and column names cannot use precompiled placeholders, so they must come from trusted mapping information and cannot be directly entered by user.

Considerations for use of reflection

Reflection improves program dynamics, but it also reduces code readability and bypasses some compile-time type checking. The following principles should be followed when using:

  • When it can be called directly, ordinary Java code is preferred.
  • Perform type and parameter verification on the reflection entrance.
  • Don’t treat unverified user input directly as class names, method names, table names, or column names.
  • on ReflectiveOperationException Conduct unified processing.
  • In modular Java projects, access to non-public members may also be restricted by module access rules.

Written by AI-rewritten

If you enjoyed this, leave a comment~

Loading...