Java 反射 API 教程与示例

⚡ 智能摘要

Java 反射 API 在运行时分析并修改类的功能,包括其字段、方法和构造函数。本资源解释了 java.lang.reflect 包、java.lang.Class 的关键方法,以及四个读取类、变量、方法和构造函数元数据的示例。

  • 🔍 定义: 反射可以在运行时检查和更改类及其成员,甚至包括私有成员。
  • 📦 反射包: 字段类、方法类、构造函数类和修饰符类收集有关成员的声明性信息。
  • 🏷️ 类方法: getName()、getSuperclass()、getInterfaces() 和 getModifiers() 返回核心类元数据。
  • 🧪 示例: 四个项目tract 类的元数据,包括变量、方法和构造函数。
  • ⚠️ 警告: Reflection 可以访问私密成员,但速度较慢,因此请将其作为最后的手段。

Java 反射 API 教程

什么是反射 Java?

Java 反射是指在运行时分析和修改类的所有功能的过程。反射 API 中 Java 用于在运行时操作类及其成员,包括字段、方法、构造函数等。

Reflection API 的一个优势是 Java 它还可以操纵类的私有成员。

java.lang.reflect 包提供了许多用于实现反射的类。java.lang.Class 类的方法用于收集特定类的完整元数据。

java.lang.reflect 包中的类

以下是名单 各个 Java 类 在 java.lang.reflect 包中实现反射:

  • 领域: 此类用于收集声明性信息,例如变量的数据类型、访问修饰符、名称和值。
  • 方法: 此类用于收集方法的声明性信息,例如访问修饰符、返回类型、名称、参数类型和异常类型。
  • 构造函数: 此类用于收集声明性信息,例如构造函数的访问修饰符、名称和参数类型。
  • 修饰符: 此类用于收集有关特定访问修饰符的信息。

java.lang.Class 中使用的方法

  • public String getName(): 返回类名。
  • public Class getSuperclass(): 返回超类引用。
  • public Class[] getInterfaces(): 返回指定类实现的接口数组。
  • public int getModifiers(): 返回一个表示指定类的修饰符的整数值,该值需要作为参数传递给“public static String toString(int i)”方法,该方法返回给定类的访问说明符。

如何获取有关课程的完整信息

获取有关信息 变量要了解一个类的方法和构造函数,我们需要创建一个该类的对象。以下示例展示了创建“Class”类对象的几种不同方法:

java.lang.Class 中使用的方法

public class Guru99ClassObjectCreation {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1 - By using Class.forName() method
        Class c1 = Class.forName("Guru99ClassObjectCreation");
        // 2 - By using getClass() method
        Guru99ClassObjectCreation guru99Obj = new Guru99ClassObjectCreation();
        Class c2 = guru99Obj.getClass();
        // 3 - By using .class
        Class c3 = Guru99ClassObjectCreation.class;
    }
}

示例 1:如何获取类的元数据

以下示例展示了如何获取类的元数据,例如类名、超类名、已实现的接口和访问修饰符。

我们将获取以下名为“ Guru99Base.class:

获取类的元数据

import java.io.Serializable;
public abstract class Guru99Base implements Serializable, Cloneable {
}
  1. 该类的名称是: Guru99个基地
  2. 其访问权限修饰符为:public 和 abstract
  3. 它已实现接口:Serializable 和 Cloneable
  4. 由于它没有显式继承任何类,因此它的超类是:java.lang.Object

以下类将获取元数据 Guru99Base.class 并打印出来:

获取类的元数据

import java.lang.reflect.Modifier;
public class Guru99GetclassMetaData {
    public static void main(String[] args) throws ClassNotFoundException {
        // Create Class object for Guru99Base.class
        Class<Guru99Base> guru99ClassObj = Guru99Base.class;

        // Print name of the class
        System.out.println("Name of the class is : " + guru99ClassObj.getName());

        // Print super class name
        System.out.println("Name of the super class is : " + guru99ClassObj.getSuperclass().getName());

        // Get the list of implemented interfaces using getInterfaces() method
        Class[] guru99InterfaceList = guru99ClassObj.getInterfaces();

        // Print the implemented interfaces using a for-each loop
        System.out.print("Implemented interfaces are : ");
        for (Class guru99class1 : guru99InterfaceList) {
            System.out.print(guru99class1.getName() + " ");
        }
        System.out.println();

        // Get access modifiers using getModifiers() and Modifier.toString()
        int guru99AccessModifier = guru99ClassObj.getModifiers();
        System.out.println("Access modifiers of the class are : " + Modifier.toString(guru99AccessModifier));
    }
}
  1. 使用getName()方法打印类名。
  2. 使用 getSuperclass().getName() 方法打印超类的名称。
  3. 打印已实现接口的名称。
  4. 打印出该类使用的访问修饰符。

获取类的元数据

获取类的元数据

示例 2:如何获取变量的元数据

以下示例展示了如何获取变量的元数据。

在这里,我们将创建一个名为 Guru99VariableMetaData.class 包含一些变量:

package guru;
public class Guru99VariableMetaData {
    public static int guru99IntVar1 = 1111;
    static int guru99IntVar2 = 2222;
    static String guru99StringVar1 = "guru99.com";
    static String guru99StringVar2 = "Learning Reflection API";
}

获取上述类中变量的元数据的步骤:

  1. 创建上述类的类对象,即: Guru99VariableMetaData.class,如下所示:
    Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
    Class guru99ClassObjVar = guru99ClassVar.getClass();
  2. 使用以下方式以字段数组的形式获取元数据: 获取字段() or 获取声明字段() 方法如下:
    Field[] guru99Field1 = guru99ClassObjVar.getFields();
    Field[] guru99Field2 = guru99ClassObjVar.getDeclaredFields();

获取字段() 该方法返回指定类及其超类中公共变量的元数据。

获取声明字段() 该方法仅返回指定类中所有变量的元数据。

  1. 使用“public String getName()”方法获取变量名称。
  2. 使用“public Class getType()”方法获取变量的数据类型。
  3. 使用“public xxx get(Field)”方法获取变量的值。这里的 xxx 可以是字节、短整型或任何我们想要获取的值类型。
  4. 使用 getModifiers() 和 Modifier.toString(int i) 方法获取变量的访问修饰符。

这里,我们正在编写一个类来获取类中存在的变量的元数据。 Guru99VariableMetaData.class:

获取变量的元数据

package guru;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Guru99VariableMetaDataTest {
    public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
        // Create Class object for Guru99VariableMetaData.class
        Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
        Class guru99ClassObjVar = guru99ClassVar.getClass();

        // Get the metadata of all the fields of the class
        Field[] guru99Field1 = guru99ClassObjVar.getDeclaredFields();

        // Print name, data types, access modifiers and values of the variables
        for (Field field : guru99Field1) {
            System.out.println("Variable name : " + field.getName());
            System.out.println("Datatype of the variable : " + field.getType());

            int guru99AccessModifiers = field.getModifiers();
            System.out.println("Access Modifiers of the variable : " + Modifier.toString(guru99AccessModifiers));
            System.out.println("Value of the variable : " + field.get(guru99ClassVar));
            System.out.println();
        }
    }
}
  1. 创建了一个类对象 Guru99VariableMetaData.class。
  2. 获取了字段数组中所有变量的元数据。
  3. 打印出类中的所有变量名 Guru99VariableMetaData.class。
  4. 打印出类中所有变量的数据类型。
  5. 打印出类中所有变量的访问修饰符。
  6. 打印出类中所有变量的值。

获取方法的元数据

获取方法的元数据

示例 3:如何获取方法的元数据

以下示例展示了如何获取方法的元数据。

在这里,我们将创建一个名为 Guru99MethodMetaData.class 包含一些方法:

获取方法的元数据

package guru;
import java.sql.SQLException;
public class Guru99MethodMetaData {

    public void guru99Add(int firstElement, int secondElement, String result)
    throws ClassNotFoundException, ClassCastException {
        System.out.println("Demo method for Reflection API");
    }
    public String guru99Search(String searchString)
    throws ArithmeticException, InterruptedException {
        System.out.println("Demo method for Reflection API");
        return null;
    }
    public void guru99Delete(String deleteString)
    throws SQLException {
        System.out.println("Demo method for Reflection API");
    }
}

获取上述类中方法的元数据的步骤:

  1. 创建上述类的类对象,即: Guru99MethodMetaData.class,如下所示:
    Guru99MethodMetaData guru99ClassVar = new Guru99MethodMetaData();
    Class guru99ClassObjVar = guru99ClassVar.getClass();
  2. 使用 getMethods() 和 getDeclaredMethods() 方法获取 Method 数组中的方法信息,如下所示:
    Method[] guru99Method1 = guru99ClassObjVar.getMethods();
    Method[] guru99Method2 = guru99ClassObjVar.getDeclaredMethods();

    获取方法() 该方法返回指定类及其超类中公共方法的元数据。 获取声明方法() 该方法仅返回指定类中所有方法的元数据。

  3. 使用以下方法获取方法名称 getName() 方法。
  4. 使用以下方法获取方法的返回类型: 获取返回类型() 方法。
  5. 使用以下方法获取访问修饰符 获取修饰符()Modifier.toString(int i) 方法。
  6. 使用以下方式获取方法参数类型 获取参数类型() 该方法返回一个 Class 数组。
  7. 使用以下方式抛出异常 获取异常类型() 该方法返回一个 Class 数组。

这里,我们编写一个类来获取类中存在的方法的元数据。 Guru99MethodMetaData.class:

获取方法的元数据

package guru;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Guru99MethodMetaDataTest {

    public static void main(String[] args) {
        // Create Class object for Guru99MethodMetaData.class
        Class guru99ClassObj = Guru99MethodMetaData.class;

        // Get the metadata of all the methods using getDeclaredMethods()
        Method[] guru99Methods = guru99ClassObj.getDeclaredMethods();

        for (Method method : guru99Methods) {
            System.out.println("Name of the method : " + method.getName());
            System.out.println("Return type of the method : " + method.getReturnType());

            int guru99ModifierList = method.getModifiers();
            System.out.println("Method access modifiers : " + Modifier.toString(guru99ModifierList));

            Class[] guru99ParamList = method.getParameterTypes();
            System.out.print("Method parameter types : ");
            for (Class class1 : guru99ParamList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();

            Class[] guru99ExceptionList = method.getExceptionTypes();
            System.out.print("Exception thrown by method : ");
            for (Class class1 : guru99ExceptionList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();
        }
    }
}
  1. 创建了一个类对象 Guru99MethodMetaData.class。
  2. 获取了 Method 数组中所有方法的元数据。
  3. 打印出类中所有方法的名称。
  4. 打印出类中各方法的返回类型。
  5. 打印出类中所有方法的访问修饰符。
  6. 打印出各方法的参数类型。
  7. 打印出各方法抛出的异常。

获取方法的元数据

获取方法的元数据

示例 4:如何获取构造函数的元数据

以下示例展示了如何获取构造函数的元数据。

在这里,我们将创建一个名为 Guru99.Constructor.class 包含不同的构造函数:

获取构造函数的元数据

package guru;

import java.rmi.RemoteException;
import java.sql.SQLException;

public class Guru99Constructor {

    public Guru99Constructor(int no) throws ClassCastException, ArithmeticException { }
    public Guru99Constructor(int no, String name) throws RemoteException, SQLException { }
    public Guru99Constructor(int no, String name, String address) throws InterruptedException { }
}

这里,我们编写一个类来获取类中存在的构造函数的元数据。 Guru99构造函数类:

获取构造函数的元数据

package guru;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Guru99ConstructorMetaDataTest {

    public static void main(String[] args) {
        // Create Class object for Guru99Constructor.class
        Class guru99Class = Guru99Constructor.class;

        // Get all the constructor information in the Constructor array
        Constructor[] guru99ConstructorList = guru99Class.getConstructors();

        for (Constructor constructor : guru99ConstructorList) {
            System.out.println("Constructor name : " + constructor.getName());

            int guru99Modifiers = constructor.getModifiers();
            System.out.println("Constructor modifier : " + Modifier.toString(guru99Modifiers));

            Class[] guru99ParamList = constructor.getParameterTypes();
            System.out.print("Constructor parameter types : ");
            for (Class class1 : guru99ParamList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();

            Class[] guru99ExceptionList = constructor.getExceptionTypes();
            System.out.print("Exception thrown by constructors : ");
            for (Class class1 : guru99ExceptionList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();
        }
    }
}
  1. 创建了一个类对象 Guru99构造函数.类。
  2. 已将所有构造函数的元数据存储在 Constructor 数组中。
  3. 打印出类中所有构造函数的名称。
  4. 打印出类中所有构造函数的访问修饰符。
  5. 打印出构造函数的参数类型。
  6. 打印出构造函数抛出的异常。

获取构造函数的元数据

获取构造函数的元数据

常见问题

反射机制允许框架和 AI 工具在运行时检查和实例化类。它为依赖注入、序列化和 ORM 映射提供支持。ping以及在编译时不知道确切类的情况下动态加载插件。

AI 可以快速生成反射代码,但您应该仔细审查。反射可能会绕过访问检查,从而引入安全性和性能风险,因此生成的代码需要进行测试和验证。

反射比直接方法调用慢,会因访问私有成员而破坏封装,并可能导致安全性和维护问题。只有在没有更简单的方法可用时才应使用反射。

是的。使用 `setAccessible(true)`,反射可以读取和修改私有字段并调用私有方法。这对于测试和框架来说非常强大,但会破坏封装性并引发安全隐患。

总结一下这篇文章: