反射的底层实现原理?

Java 反射机制详解

在这里插入图片描述

目录

  1. 什么是反射?
  2. 反射的应用
  3. 反射的实现
  4. 反射的底层实现原理
  5. 反射的优缺点分析

一、什么是反射?

反射是 Java 编程语言中的一个强大特性,它允许程序在运行期间动态获取类和操纵类。通过反射机制,可以在运行时动态地创建对象、调用方法、访问和修改属性,以及获取类的信息。反射提供了极大的灵活性,但也带来了运行时性能损耗和安全隐患。

二、反射的应用

反射在日常开发中使用的地方有很多,以下是一些常见的应用场景:

2.1 动态代理

反射是动态代理的底层实现。在运行时动态地创建代理对象,并拦截和增强方法调用。这常用于实现 AOP(面向切面编程)功能,如日志记录、事务管理等。例如,Spring 框架中的 AOP 功能就是通过反射实现的。

2.2 Bean 创建

在 Spring/Spring Boot 项目中,Bean 对象的创建是通过反射实现的。项目启动时,Spring 会通过反射动态地创建 Bean 对象,并进行依赖注入。

2.3 JDBC 连接

JDBC 中的 DriverManager 类通过反射加载并注册数据库驱动。这是 Java 数据库连接的标准做法。例如,通过 Class.forName("com.mysql.cj.jdbc.Driver") 加载 MySQL 驱动。

三、反射的实现

反射的关键实现方法有以下几个:

3.1 得到类

Class<?> clazz = Class.forName("com.example.User");

3.2 得到所有字段

Field[] fields = clazz.getDeclaredFields();

3.3 得到所有方法

Method[] methods = clazz.getDeclaredMethods();

3.4 得到构造方法

Constructor<?> constructor = clazz.getDeclaredConstructor();

3.5 得到实例

Object instance = clazz.getDeclaredConstructor().newInstance();

3.6 调用方法

Method method = clazz.getDeclaredMethod("publicMethod");
method.invoke(instance);

3.7 具体使用示例

3.7.1 调用普通方法
// 1. 反射得到对象
Class<?> clazz = Class.forName("com.example.User");// 2. 得到方法
Method method = clazz.getDeclaredMethod("publicMethod");// 3. 得到实例
Object user = clazz.getDeclaredConstructor().newInstance();// 4. 执行方法
method.invoke(user);
3.7.2 调用静态方法
// 1. 反射得到对象
Class<?> clazz = Class.forName("com.example.User");// 2. 得到静态方法
Method staticMethod = clazz.getDeclaredMethod("staticMethod");// 3. 执行静态方法
staticMethod.invoke(null); // 静态方法不需要实例
3.7.3 调用私有方法
// 1. 反射得到对象
Class<?> clazz = Class.forName("com.example.User");// 2. 得到私有方法
Method privateMethod = clazz.getDeclaredMethod("privateMethod");// 3. 设置私有方法可访问
privateMethod.setAccessible(true);// 4. 得到实例
Object user = clazz.getDeclaredConstructor().newInstance();// 5. 执行私有方法
privateMethod.invoke(user);

四、反射的底层实现原理

反射的核心方法是 invoke,理解了 invoke 方法的实现,也就理解了反射的底层实现原理。invoke 方法的执行流程如下:

4.1 查找方法

当通过 java.lang.reflect.Method 对象调用 invoke 方法时,Java 虚拟机(JVM)首先确认该方法是否存在并可以访问。这包括检查方法的访问权限、方法签名是否匹配等。

4.2 安全检查

如果方法是私有的或受保护的,还需要进行访问权限的安全检查。如果当前调用者没有足够的权限访问这个方法,将抛出 IllegalAccessException

4.3 参数转换和适配

invoke 方法接受一个对象实例和一组参数,需要将这些参数转换成对应方法签名所需要的类型,并且进行必要的类型检查和装箱拆箱操作。

4.4 方法调用

对于非私有方法,Java 反射实际上是通过 JNI(Java Native Interface,Java 本地接口)调用到 JVM 内部的 native 方法,例如 java.lang.reflect.Method.invoke0()。这个 native 方法负责完成真正的动态方法调用。对于 Java 方法,JVM 会通过方法表、虚方法表(vtable)进行查找和调用;对于非虚方法或者静态方法,JVM 会直接调用相应的方法实现。

4.5 异常处理

在执行方法的过程中,如果出现任何异常,JVM 会捕获并将异常包装成 InvocationTargetException 抛出,应用程序可以通过这个异常获取到原始异常信息。

4.6 返回结果

如果方法正常执行完毕,invoke 方法会返回方法的执行结果,或者如果方法返回类型是 void,则不返回任何值。

通过这种方式,Java 反射的 invoke 方法能够打破编译时的绑定,实现运行时动态调用对象的方法,提供了极大的灵活性,但也带来了运行时性能损耗和安全隐患(如破坏封装性、违反访问控制等)。

五、反射的优缺点分析

5.1 优点

  • 灵活性:使用反射可以在运行时动态加载类,而不需要在编译时就将类加载到程序中。这对于需要动态扩展程序功能的情况非常有用。
  • 可扩展性:使用反射可以使程序更加灵活和可扩展,同时也可以提高程序的可维护性和可测试性。
  • 实现更多功能:许多框架都使用反射来实现自动化配置和依赖注入等功能。例如,Spring 框架就使用反射来实现依赖注入。

5.2 缺点

  • 性能问题:使用反射会带来一定的性能问题,因为反射需要在运行时动态获取类的信息,这比在编译时就获取信息要慢。
  • 安全问题:使用反射可以访问和修改类的字段和方法,这可能会导致安全问题。因此,在使用反射时需要格外小心,确保不会对程序的安全性造成影响。

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

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

相关文章

【技术支持】安卓无线adb调试连接方式

Android 10 及更低版本&#xff0c;需要借助 USB 手机和电脑需连接在同一 WiFi 下&#xff1b;手机开启开发者选项和 USB 调试模式&#xff0c;并通过 USB 连接电脑&#xff08;即adb devices可以查看到手机&#xff09;&#xff1b;设置手机的监听adb tcpip 5555;拔掉 USB 线…

Golang学习历程【第六篇 复合数据类型map函数初识】

Golang学习历程【第六篇 复合数据类型map&函数初识】 1. Map数据类型1.1. Map声明和初始化1.2. Map 遍历1.3 Map增删改查 2. function (函数)2.1 函数各种定义方式 1. Map数据类型 Map结构是键值对的集合&#xff0c;其中每个键都是唯一的&#xff0c;并且每个键都映射到一…

《框架程序设计》期末复习

目录 Maven 简介 工作机制&#xff08;★&#xff09; 依赖配置&#xff08;★&#xff09; Maven命令 MyBatis 入门 单参数查询&#xff08;★&#xff09; 多参数查询&#xff08;★★★&#xff09; 自定义映射关系&#xff08;★★★&#xff09; 基本增删改查操…

于交错的路径间:分支结构与逻辑判断的思维协奏

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。* 这一节内容很多&#xff0c;文章字数达到了史无前例的一万一&#xff0c;我们要来学习分支与循环结构中…

ffplay 命令行 从视频第N帧开始读取 ffmpeg 命令行 提取第N帧图片

ffmpeg中没有直接的命令读取第N帧 但是可以通过 t N/framerate 来获取到具体第N帧的时间 然后用 -ss t进行跳转。 比如帧率&#xff08;frame rate&#xff09;为24fps的视频G:/1/1.mp4文件从第1000帧开始进行播放&#xff0c;先计算出时间为 t 41.66666 ffplay -i G:/1/1.…

计算机图形学【绘制立方体和正六边形】

工具介绍 OpenGL&#xff1a;一个跨语言的图形API&#xff0c;用于渲染2D和3D图形。它提供了绘制图形所需的底层功能。 GLUT&#xff1a;OpenGL的一个工具库&#xff0c;简化了窗口创建、输入处理和其他与图形环境相关的任务。 使用的函数 1. glClear(GL_COLOR_BUFFER_BIT |…

探秘block原理

01 概述 在iOS开发中&#xff0c;block大家用的都很熟悉了&#xff0c;是iOS开发中闭包的一种实现方式&#xff0c;可以对一段代码逻辑进行封装&#xff0c;使其可以像数据一样被传递、存储、调用&#xff0c;并且可以保存相关的上下文状态。 很多block原理性的文章都比较老&am…

科大讯飞前端面试题及参考答案 (下)

除了 echarts 还了解其它画图工具吗? 除了 Echarts,还有不少优秀的画图工具可供选择使用。 Highcharts:它是一款功能强大且应用广泛的图表绘制工具,支持多种常见的图表类型,像柱状图、折线图、饼图、散点图等,同时也能创建较为复杂的图表,比如仪表盘图表、极坐标图等。H…

【HarmonyOS Next NAPI 深度探索2】N-API 的工作机制与架构

【HarmonyOS Next NAPI 深度探索2】N-API 的工作机制与架构 如果你听说过 N-API&#xff0c;但还不太了解它的作用和背后的工作机制&#xff0c;那这篇文章会帮你捋清楚它的结构和原理。N-API 是 Node.js 提供的一个强大工具&#xff0c;专门用于开发高性能、可维护的原生模块…

vue3+ts+element-plus 对话框el-dialog设置圆角

对话框el-dialog设置圆角&#xff0c;实现的需求效果&#xff1a; 目前只能通过行内样式&#xff08;style"border-radius: 20px"&#xff09;来实现圆角效果&#xff1a;

14综合面试篇(综合面试题)

目录 一、关于null的问题 二、springboot jar启动参数的配置linux Xms Xmx 三、java -jar 启动参数问题 四、 java打一个jar包放到linux服务器上&#xff0c;这种默认参数的启动&#xff0c;是怎么知道分配原则和配置原则? 五、Linux系统下jar包自启动 六、i&#xff0c;…

机器学习算法(三):K近邻(k-nearest neighbors)

1 KNN的介绍和应用 1.1 KNN的介绍 kNN(k-nearest neighbors)&#xff0c;中文翻译K近邻。我们常常听到一个故事&#xff1a;如果要了解一个人的经济水平&#xff0c;只需要知道他最好的5个朋友的经济能力&#xff0c; 对他的这五个人的经济水平求平均就是这个人的经济水平。这…

大语言模型兵马未动,数据准备粮草先行

​从OpenAI正式发布ChatGPT开始&#xff0c;大型语言模型&#xff08;LLM&#xff09;就变得风靡一时。对业界和吃瓜群众来说&#xff0c;这种技术最大的吸引力来自于理解、解释和生成人类语言的能力&#xff0c;毕竟这曾被认为是人类独有的技能。类似CoPilot这样的工具正在迅速…

Network Compression(李宏毅)机器学习 2023 Spring HW13 (Boss Baseline)

1. Introduction to Network Compression 深度学习中的网络压缩是指在保持神经网络性能的同时,减少其规模的过程。这非常重要,因为深度学习模型,尤其是用于自然语言处理或计算机视觉的大型模型,训练和部署的计算成本可能非常高。网络压缩通过降低内存占用并加快推理速度,…

UnityDots学习(二)

在一里已经概述了什么是Dots&#xff0c;已经如果使用它&#xff0c;我们要做的思维转变。 简单总结下&#xff1a; Dots使用了计算器多核&#xff0c;已经3级缓存的优势&#xff0c;在此基础上使用Brust编译器对各个平台实现了代码优化。从而达到了加速提升的效果。 我们要…

Linux (CentOS) 安装 Docker 和 Docker Compose

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …

c++ 预备

目录 前言 一&#xff0c;知识点的补充 二&#xff0c;c语言与c 三&#xff0c;面向对象的三大特点 前言 将进入c的学习&#xff0c;接下来是对于c的预备和c的一些预习 一&#xff0c;知识点的补充 1 标识符 标识符不能为关键字 标识符只能由下划线&#xff0c;数字&#xf…

SpringBoot项目实战(41)--Beetl网页使用自定义函数获取新闻列表

在Beetl页面中可以使用自定义的函数从后台新闻列表中获取新闻数据展示到页面上。例如我们可以从后台新闻表中获取新闻按照下面的格式展示&#xff1a; <li><a href"#">东亚非遗展即将盛妆亮相 揭起盖头先睹为快</a></li><li><a hre…

从零开始开发纯血鸿蒙应用之多签名证书管理

从零开始开发纯血鸿蒙应用 一、前言二、鸿蒙应用配置签名证书的方式1、自动获取签名证书2、手动配置签名证书 三、多签名证书配置和使用四、多证书使用 一、前言 由于手机操作系统&#xff0c;比电脑操作系统脆弱很多&#xff0c;同时&#xff0c;由于手机的便携性&#xff0c…

写个自己的vue-cli

写个自己的vue-cli 1.插件代码2. 发布流程3. 模板代码讲解3.1 vue2模板的运行流程:3.2 vue3模板的运行流程: 1.插件代码 写一个自己的vue-cli插件 插件地址&#xff1a;插件地址 流程&#xff1a; 实现简单版 vue-cli 步骤文档1. 项目初始化 - 创建项目文件夹 qsl-vue-cli - …