Java 反射机制允许在运行时动态地访问和操作类的成员

Java 反射机制允许在运行时动态地访问和操作类的成员。

反射基本步骤

  1. 获取类的 Class 对象

    Class<?> messageHandlerClass = Class.forName("org.example.MsgHandler");
    

    Class.forName 方法根据类名获取相应的 Class 对象。

  2. 获取构造函数并创建实例

    Constructor<?> constructor = messageHandlerClass.getConstructor(String.class);
    Object messageHandlerInstance = constructor.newInstance("Hello, Reflection!");
    

    getConstructor 方法获取指定参数类型的构造函数,newInstance 方法创建类的实例。

  3. 调用方法

    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 方法的工作原理

  1. 获取方法对象
    在使用反射调用方法之前,首先需要通过 getMethodgetDeclaredMethod 获取一个 Method 对象,该对象表示要调用的方法。

    Method printMessageMethod = messageHandlerClass.getMethod("printMessage");
    
  2. 调用 invoke 方法
    invoke 方法用于在指定对象上调用这个 Method 对象表示的方法。它的签名如下:

    Object invoke(Object obj, Object... args)
    
    • obj:要调用方法的对象。
    • args:方法调用时传递的参数,没有参数时可以传递空数组或不传递参数。

    在这个例子中:

    printMessageMethod.invoke(messageHandlerInstance);
    

    这行代码的含义是:在 messageHandlerInstance 对象上调用 printMessage 方法。

详细步骤

  1. 参数检查
    invoke 方法会检查传递的参数是否与方法签名匹配。如果不匹配,会抛出 IllegalArgumentException 异常。

  2. 访问权限检查
    如果要调用的方法是私有的,JVM 会检查当前的访问权限。如果没有适当的权限,会抛出 IllegalAccessException。不过,可以通过 method.setAccessible(true) 绕过这个限制。

  3. 方法调用
    JVM 会通过反射机制在指定对象上实际调用这个方法,传递相应的参数。如果方法是静态的,则 obj 参数可以为 null

  4. 返回值处理
    如果方法有返回值,invoke 会返回这个值。如果方法的返回类型是 voidinvoke 返回 null

  5. 异常处理
    如果方法调用过程中抛出了异常,invoke 会捕获并包装在一个 InvocationTargetException 中抛出。

示例解释

在以下代码中:

printMessageMethod.invoke(messageHandlerInstance);
  • printMessageMethod 是表示 MsgHandler 类中的 printMessage 方法的 Method 对象。
  • messageHandlerInstanceMsgHandler 类的一个实例。
  • invoke 调用在 messageHandlerInstance 对象上执行 printMessage 方法,该方法没有参数,因此 invoke 只传递了对象实例。

完整流程如下:

  • JVM 检查 printMessageMethod 是否可以在 messageHandlerInstance 上调用。
  • JVM 确认方法签名匹配并且具有访问权限。
  • JVM 在 messageHandlerInstance 上调用 printMessage 方法。
  • 方法执行完毕,没有返回值,因此 invoke 返回 null

通过这些步骤,反射机制在运行时动态调用了对象的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/40756.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt 使用QJsonModel的问题

项目场景&#xff1a; 需要表格记录json数据&#xff0c;使用Qtreeview显示并修改&#xff0c;使用开源的第三方类QJsonModel,即可快速完成。 问题描述&#xff1a; 使用中发现一个问题&#xff1a;当Qtreeview修改完毕&#xff0c;从Model获取保存后的Json数据时&#xff0c…

mac|Mysql WorkBench导入文件失败(修改编码)

⚠️&#xff1a;表格中有中文的不适用表格中有中文的不适用表格中有中文的不适用表格中有中文的不适用 我有一个excel表&#xff0c;想导入到mysql数据库中&#xff0c;但是Workbench的导入格式只支持csv&#xff0c;通过excel、wps将excel另存为csv文件进行导入 导入会因为编…

【软件测试】之自动化测试

&#x1f3c0;&#x1f3c0;&#x1f3c0;来都来了&#xff0c;不妨点个关注&#xff01; &#x1f3a7;&#x1f3a7;&#x1f3a7;博客主页&#xff1a;欢迎各位大佬! 文章目录 什么是自动化测试Selenium介绍什么是SeleniumSelenium的特点工作原理 SeleniumJava环境搭建下载…

第1章 信息系统综合知识

第1章 信息系统综合知识 本章主要介绍信息系统综合知识&#xff0c;介绍信息、信息系统的基本概念&#xff0c;概述两化融合和国家信息化战略&#xff0c;讲解电子政务、电子商务的典型应用&#xff0c;描述信息化整体总体规划以及IT战略的主要内容。 1.1 信息的定义和属性 …

数据结构底层之HashMap(面经篇1)

1 . 讲一下hashmap的数据结构 HashMap是一种基于哈希表实现的数据结构&#xff0c;通常用于关联键值对&#xff0c;其中键是唯一的&#xff0c;而值可以重复。在Java中&#xff0c;HashMap是java.util.Map接口的一个实现&#xff0c;它提供了快速的查找、插入和删除操作。 数据…

【TB作品】矩阵键盘电话拨号,ATMEGA16单片机,Proteus仿真 atmega16矩阵键盘电话拨号

atmega16矩阵键盘电话拨号 c代码和仿真图&#xff1a; 使用ATmega16实现矩阵键盘电话拨号功能 项目背景 在电子设计和嵌入式系统开发中&#xff0c;矩阵键盘是常见的人机交互方式。它可以实现较多按键的输入&#xff0c;同时节省单片机的I/O资源。结合LCD显示和蜂鸣器&am…

Flume集群部署(手把手部署图文详细版)

前景概要&#xff1a; Kafka消息订阅系统在大数据业务中有着重要运用&#xff0c;尤其在实时业务中&#xff0c;kafka是必不可少的组件之一。 Flume是大数据组件中重要的数据采集工具&#xff0c;我们常利用Flume采集各种数据源的数据供其他组件分析使用。例如在实时业务中&…

清华镜像源

python在安装各种库的时候为了下载速度快&#xff0c;经常使用镜像源&#xff0c;下面是使用清华镜像源案例。其中的 xxx 表示要安装的库&#xff0c;如 requests。 pip install xxx -i https://pypi.tuna.tsinghua.edu.cn/simple 安装requests案例&#xff1a;pip install r…

Java房屋租赁管理系统附论文

作者介绍&#xff1a;计算机专业研究生&#xff0c;现企业打工人&#xff0c;从事Java全栈开发 主要内容&#xff1a;技术学习笔记、Java实战项目、项目问题解决记录、AI、简历模板、简历指导、技术交流、论文交流&#xff08;SCI论文两篇&#xff09; 上点关注下点赞 生活越过…

【Java09】方法(下)

1. 形参个数可变的方法 Java允许方法指定数量不确定的形参。如果在定义方法是&#xff0c;在最后一个形参的类型后加...&#xff0c;则表明该形参可以接受多个参数值。多个参数值作为数组传入&#xff1a; public class Varargs {public static void test(int a, String... b…

以智能化为舵手,引领现代计算机系统架构新航向

编者按&#xff1a;如今计算机系统承载的服务和算法逻辑日益复杂&#xff0c;理解、设计并改进计算机系统已成为核心挑战。面对系统复杂度和规模的指数级增长&#xff0c;以及新的大模型驱动场景下的分布式系统形态的涌现&#xff0c;人们亟需创新方法与技术来应对。在计算机系…

Linux 下c++ 的ssh服务端验证代码示例

telnet 是明文传输,别人可能用抓包软件就能截获通信内容,所以现代通信方式多用ssh。 在Linux下编写一个基本的SSH服务端验证代码示例,涉及到C++编程和使用OpenSSH库。以下是一个简单的示例,展示了如何建立一个基本的SSH服务端,并进行用户名和密码的验证。 环境准备 确保…

vue动态组件与插件到底是什么?

background: yellow; } 子组件1 <ul><li v-for"item of items" :key"item"><input type"checkbox" />{{ item }}</li></ul>子组件2 PostMail 子组件3 RecycleBin ![在这里插入图片描述](https://img-blog.csdni…

光明领鲜物流荣膺“2023中国冷链物流百强企业”荣誉称号

近日&#xff0c;以“全球链接跨界融合”为主题的2024第十六届全球食品冷链大会举行&#xff0c;光明乳业旗下光明领鲜物流受邀参加。 作为光明乳业全产业链中重要组成部分&#xff0c;光明领鲜物流始终保持高标准严要求&#xff0c;专注于冷链质量和服务持续完善&#xff0c;并…

【SQL】索引过多的缺点

索引并不是建得越多越好。虽然索引可以提高查询性能&#xff0c;但它们也带来了一些负面影响&#xff0c;特别是在数据修改操作&#xff08;插入、更新、删除&#xff09;和存储空间方面。以下是一些需要考虑的因素和权衡&#xff1a; 1. 写操作的性能影响 每个索引在数据修改…

1.英语中的从句学习

名词性从句&#xff1a; 1.最常见的连接词是that在宾语从句中的运用&#xff0c;如&#xff1a;I know that you will come. 句中的that 就是连接词&#xff0c;作用就是连接主句和从句&#xff0c;不充当成分也没有含义&#xff0c;只起风向标的作用&#xff0c;告诉你接下来…

Python基础语法(与C++对比)(持续更新ing)

代码块 Python在统一缩进体系内&#xff0c;为同一代码块C{...}内部的为同一代码块 注释 Python 单行注释&#xff1a;#... 多行注释&#xff1a;... C 单行注释&#xff1a;//... 多行注释: /*...*/ 数据类型 1. Python数据类型 Python中支持数字之间使用下划线 _ 分割…

[笔记] 卷积 - 01 变速箱需要放置多少个加速度传感器?

1.讨论范围 本帖主要对卷积运算的过程和物理意义进行基本的展开&#xff0c;不涉及具体的验算过程。 最终所要达成的目标是&#xff0c;能够自然地判断某种物理现象或者某个测量目标是否与卷积运算有关&#xff0c;以及如何进行测量&#xff0c;搜集数据&#xff0c;调用三方…

【0292】Postgres内核源码之dynahash 查找实现

0. 前言 在【0291】Postgres内核之dynahash table 创建 一文中&#xff0c;从内核源码的实现角度讲解了Postgres创建dynahash的底层实现机制&#xff1b;本文将继续从内核角度分析Postgres dynahash find的实现原理。 1. dynahash find

DB2数据库日常维护

一、DB2系统结构 创建实例 db2icrt 实例名 删除实例 db2idrop 实例名 查询实例 db2ilist 实例名 启动实例 db2start 停止实例 db2stop 创建数据库 create database 库名 [on 存储路径] [using codeset 字符集] [TERRITORY 区域码] [pagesize 页大小] 删除数据库 drop database…