Java 反射机制允许在运行时动态地访问和操作类的成员。
反射基本步骤
-
获取类的
Class
对象:Class<?> messageHandlerClass = Class.forName("org.example.MsgHandler");
Class.forName
方法根据类名获取相应的Class
对象。 -
获取构造函数并创建实例:
Constructor<?> constructor = messageHandlerClass.getConstructor(String.class); Object messageHandlerInstance = constructor.newInstance("Hello, Reflection!");
getConstructor
方法获取指定参数类型的构造函数,newInstance
方法创建类的实例。 -
调用方法:
Method printMessageMethod = messageHandlerClass.getMethod("printMessage"); printMessageMethod.invoke(messageHandlerInstance);
getMethod
方法获取指定名称的方法,invoke
方法调用该方法。
代码中的具体操作
- 创建实例:通过
MsgHandler
类的带参构造函数创建实例,传入初始消息 “Hello, Reflection!”。 - 调用
printMessage
方法:打印当前消息。 - 调用
updateMessage
方法:更新消息为 “Updated Message via Reflection”。 - 再次调用
printMessage
方法:打印更新后的消息。 - 调用
retrieveMessage
方法:获取当前消息并打印。
完整代码示例
package org.example;import java.lang.reflect.Constructor;
import java.lang.reflect.Method;class MsgHandler {private String message;public MsgHandler() {this.message = "Default Message";}public MsgHandler(String message) {this.message = message;}public void printMessage() {System.out.println(this.message);}public void updateMessage(String newMessage) {this.message = newMessage;}public String retrieveMessage() {return this.message;}
}public class ReflectionDemo {public static void main(String[] args) {try {// 获取类的 Class 对象Class<?> messageHandlerClass = Class.forName("org.example.MsgHandler");// 获取构造函数并创建实例Constructor<?> constructor = messageHandlerClass.getConstructor(String.class);Object messageHandlerInstance = constructor.newInstance("Hello, Reflection!");// 调用 printMessage 方法Method printMessageMethod = messageHandlerClass.getMethod("printMessage");printMessageMethod.invoke(messageHandlerInstance);// 调用 updateMessage 方法,传递参数Method updateMessageMethod = messageHandlerClass.getMethod("updateMessage", String.class);updateMessageMethod.invoke(messageHandlerInstance, "Updated Message via Reflection");// 再次调用 printMessage 方法,查看更新后的消息printMessageMethod.invoke(messageHandlerInstance);// 获取 retrieveMessage 方法的返回值Method retrieveMessageMethod = messageHandlerClass.getMethod("retrieveMessage");String message = (String) retrieveMessageMethod.invoke(messageHandlerInstance);System.out.println("Returned message: " + message);} catch (Exception e) {e.printStackTrace();}}
}
通过这种方式,反射提供了在运行时动态地访问和操作类成员的强大功能。
联系我
下面聊一聊invoke
,
invoke
方法是 Java 反射 API 中的一个核心方法,它允许在运行时调用对象的方法。以下是 invoke
方法的工作原理及其步骤:
invoke
方法的工作原理
-
获取方法对象:
在使用反射调用方法之前,首先需要通过getMethod
或getDeclaredMethod
获取一个Method
对象,该对象表示要调用的方法。Method printMessageMethod = messageHandlerClass.getMethod("printMessage");
-
调用
invoke
方法:
invoke
方法用于在指定对象上调用这个Method
对象表示的方法。它的签名如下:Object invoke(Object obj, Object... args)
obj
:要调用方法的对象。args
:方法调用时传递的参数,没有参数时可以传递空数组或不传递参数。
在这个例子中:
printMessageMethod.invoke(messageHandlerInstance);
这行代码的含义是:在
messageHandlerInstance
对象上调用printMessage
方法。
详细步骤
-
参数检查:
invoke
方法会检查传递的参数是否与方法签名匹配。如果不匹配,会抛出IllegalArgumentException
异常。 -
访问权限检查:
如果要调用的方法是私有的,JVM 会检查当前的访问权限。如果没有适当的权限,会抛出IllegalAccessException
。不过,可以通过method.setAccessible(true)
绕过这个限制。 -
方法调用:
JVM 会通过反射机制在指定对象上实际调用这个方法,传递相应的参数。如果方法是静态的,则obj
参数可以为null
。 -
返回值处理:
如果方法有返回值,invoke
会返回这个值。如果方法的返回类型是void
,invoke
返回null
。 -
异常处理:
如果方法调用过程中抛出了异常,invoke
会捕获并包装在一个InvocationTargetException
中抛出。
示例解释
在以下代码中:
printMessageMethod.invoke(messageHandlerInstance);
printMessageMethod
是表示MsgHandler
类中的printMessage
方法的Method
对象。messageHandlerInstance
是MsgHandler
类的一个实例。invoke
调用在messageHandlerInstance
对象上执行printMessage
方法,该方法没有参数,因此invoke
只传递了对象实例。
完整流程如下:
- JVM 检查
printMessageMethod
是否可以在messageHandlerInstance
上调用。 - JVM 确认方法签名匹配并且具有访问权限。
- JVM 在
messageHandlerInstance
上调用printMessage
方法。 - 方法执行完毕,没有返回值,因此
invoke
返回null
。
通过这些步骤,反射机制在运行时动态调用了对象的方法。