【Java反射详解】

Java反射详解

🎊专栏【Java】 🍔喜欢的诗句:关山难越,谁悲失路之人。
萍水相逢,尽是他乡之客。
🎆音乐分享【Counting Stars 】
欢迎并且感谢大家指出问题🥰
在这里插入图片描述

1.什么是反射

所谓的反射就是java语言在运行时拥有的一种自观的能力,反射使您的程序代码能够得到装载到JVM中的
类的内部信息,允许您执行程序时才得到需要类的内部信息,而不是在编写代码的时候就必须要知道所需
类的内部信息;也可以通俗的将这种动态获取信息以及动态调用对象的方法称为Java的反射机制.
通过Java的反射机制,程序猿们可以更深入的控制程序的运行过程,如在程序运行时对用户输入的信息进行
验证,还可以逆向控制程序的执行过程,这也使反射成为构建灵活的应用的主要工具。

2. 反射原理大解析

2.1 反射的常用类和函数

  • Java反射机制的实现要借助于4个类:
  • Class 类对象
  • Constructor 类的构造器对象
  • Field 类的属性对象
  • Method 类的方法对象

2.2 Class 类包含的方法

通过这四个对象我们可以粗略的看到一个类的各个组成部分。其中最核心的就是Class类,它是实现反射
的基础,Class类包含的方法主要有
在这里插入图片描述

2.3 反射的主要方法

应用反射时我们最关心的一般是一个类的构造器、属性和方法,下面我们主要介绍Class类中针对这三个
元素的方法:

2.3.1 得到构造器的方法

在这里插入图片描述

2.3.2 获得字段信息的方法

在这里插入图片描述

2.3.3 获得方法信息的方法

在这里插入图片描述

2.4 反射实战的基本步骤

在这里插入图片描述
上面就是最常见的反射使用的例子,前两行实现了类的装载、链接和初始化(newInstance方法实际上也是使用反射调用了 方法),后两行实现了从class对象中获取到method对象然后执行反射调用。下面简单分析一下该代码的具体原理。上就是最常见的反射使用的例子,前两行实现了类的装载、链接和初始化(newInstance方法实际上也是使用反射调用了 法),后两行实现了从class对象中获取到method对象然后执行反射调用。下面简单分析一下该代码的具体原理。

2.4.1 获得类的Class对象

通常有三种不同的方法:
1)Class c = Class.forName(“java.lang.String”)
2)Class c = MyClass.class
3)对于基本数据类型可以用Class c = int.class 或 Class c = Integer.TYPE这样的语句.
举个小栗子:先通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例
PS:反射的原理之一其实就是动态的生成类似于上述的字节码,加载到jvm中运行。
设想一下,上面的代码中,如果想要实现 method.invoke(action,null) 调用action对象的 myMethod
方法,只需要实现这样一个Method类即可
在这里插入图片描述

2.4.2 获取 Method 对象

首先来看一下Method对象是如何生成的:
使用Method m =myclass.getMethod(“myMethod”)获得了一个Class对象
接着对其进行判断,如果没有对应的cache,那么JVM就会为其创建一个并放入缓冲空间
处理器再判断Cache中是否存在"myMethod"
如果没有则返回NoSuchMethodException
如果存在那么就Copy一份"myMethod"对象并返回

上面的Class对象是在加载类时由JVM构造的,JVM为每个类管理一个独一无二的Class对象,这份Class对
象里维护着该类的所有Method,Field,Constructor的cache,这份cache也可以被称作根对象。每次
getMethod获取到的Method对象都持有对根对象的引用,因为一些重量级的Method的成员变量(主要
是MethodAccessor),我们不希望每次创建Method对象都要重新初始化,于是所有代表同一个方法的
Method对象都共享着根对象的MethodAccessor,每一次创建都会调用根对象的copy方法复制一份:
在这里插入图片描述

2.4.3 调用invoke()方法

获取到Method对象之后,调用invoke方法的流程如下:
m.invoke(obj,param);
首先调用MethodAccess.invoke
如果该方法的累计调用次数<=15,会创建出NativeMethodAccessorImp
如果该方法的累计调用次数>15,会由java代码创建出字节码组装而成的
MethodAccessorImpl
我们可以看到,调用Method.invoke之后,会直接去调 MethodAccessor.invoke 。MethodAccessor就
是上面提到的所有同名method共享的一个实例,由ReflectionFactory创建。创建机制采用了一种名为
inflation的方式(JDK1.4之后):如果该方法的累计调用次数<=15,会创建出
NativeMethodAccessorImpl,它的实现就是直接调用native方法实现反射;如果该方法的累计调用次数>15,会由java代码建出字节码组装而成的MethodAccessorImpl。(是否采用inflation和15这个数字都可以在jvm参数中调整)以调用MyClass.myMethod(String s) 为例,生成出的MethodAccessorImpl字节码翻译成Java代码大
致如下
在这里插入图片描述
通过对java运行过程的详细分析,我们可以发现其中第1次和第16次调用是最耗时的(初始化
NativeMethodAccessorImpl和字节码拼装MethodAccessorImpl)。初始化不可避免,因而native方式的
初始化会更快,所以前几次的调用会采用native方法。
随着调用次数的增加,每次反射都使用JNI跨越native边界会对优化有阻碍作用,相对来说使用拼装出的
字节码可以直接以Java调用的形式实现反射,发挥了JIT优化的作用,避免了JNI为了维护OopMap
(HotSpot用来实现准确式GC的数据结构)进行封装/解封装的性能损耗。
在已经创建了MethodAccessor的情况下,使用Java版本的实现会比native版本更快。所以当调用次数到
达一定次数(15次)后,会切换成Java实现的版本,来优化未来可能的更频繁的反射调用。

3 Java反射的应用(Hibernate框架)

前面我们已经知道,Java 反射机制提供了一种动态链接程序组件的多功能方法,它允许程序创建和控制
任何类的对象(根据安全性限制)之前,无需提前硬编码目标类。这些特性使得反射特别适用于创建以非常
普通的方式与对象协作的库。例如,反射经常在持续存储对象为数据库、XML或其它外部格式的框架中
使用。下面就已Hibernate框架为例像大家阐述一下反射的重要意义。
Hibernate是一个屏蔽了JDBC,实现了ORM的java框架,利用该框架我们可以抛弃掉繁琐的sql语句而是
利用Hibernate中Session类的save()方法直接将某个类的对象存到数据库当中,也就是所涉及到sql语句的
那些代码Hibernate帮我们做了。这时候就出现了一个问题,Hibernate怎样知道他要存的某个对象都有什
么属性呢?这些属性都是什么类型呢?想一想,它在向数据库中存储该对象属性时的sql语句该怎么构造
呢?OK,反射的作用此刻就体现出来了!
下面我们以一个例子来进行阐述,比如我们定义了一个User类,这个User类中有20个属性和这些属性的
get和set方法,相应的在数据库中有一个User表,这个User表中对应着20个字段。假设我们从User表中
提取了一条记录,现在需要将这条记录的20个字段的内容分别赋给一个User对象myUser的20个属性,
而Hibernate框架在编译的时候并不知道这个User类,他无法直接调用myUser.getXXX或者
myUser.setXXX方法,此时就用到了反射,具体处理过程如下:

  1. 根据查询条件构造PreparedStament语句,该语句返回20个字段的值;
  2. Hibernate通过读取配置文件得到User类的属性列表list(是一个String数组)以及这些属性的类型;
  3. 创建myUser所属类的Class对象c;c = myUser.getClass();
  4. 构造一个for循环,循环的次数为list列表的长度; 读取list[i]的值,然后构造对应该属性的set方法;

判断list[i]的类型XXX,调用PreparedStament语句中的getXXX(i),进而得到i出字段的值;
将4.2中得到的值作为4.1中得到的set方法的参数,这样就完成了一个字段像一个属性的赋值,
如此循环直至程序运行结束;
如果没有反射难以想象实现这么复杂的功能将会有多么难!

话说回来,反射给我们带来便利的同时也有它自身的缺点,比如性能较低、安全性较低、过程比较复杂等
等,感兴趣的读者也可以在实际工作中再深入研究哦!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

365锦鲤助手 砍价小程序源码 流量主引流裂变

源码介绍 修改版365锦鲤 助手&#xff0c; 砍价小程序源码 流量主引流裂变 拼多多商品快速丰富产品内容满足广大用户需求&#xff1b;流量矩阵让流量都进你的圈子飞起来&#xff1b;长期盈利、项目稳定 1.后台安装微擎 2安装应用 后台打包上传

PPINN Parareal physics-informed neural network for time-dependent PDEs

论文阅读&#xff1a;PPINN Parareal physics-informed neural network for time-dependent PDEs PPINN Parareal physics-informed neural network for time-dependent PDEs简介方法PPINN加速分析 实验确定性常微分方程随机常微分方程Burgers 方程扩散反应方程 总结 PPINN Par…

Npm安装vue3报错(node:25436) MaxListenersExceededWarning:

运行命令安装vue3时 npm create vuelatest 报了错误(node:25436) MaxListenersExceededWarning: (忘记截报错的图了&#xff0c;后面还有一大串英文) 搞了很久发现是网络的原因&#xff0c;我没有修改镜像地址&#xff0c;导致访问很慢&#xff0c;于是去npmmirror 镜像站 …

字符雨canvas

整体思路&#xff1a; 确定好字符雨的具体字符是什么&#xff0c;需要多少行多少列这里是写死的其实也可以用循环加随机的方式生成不一样的字符雨&#xff0c;行列也可以读一下宽度然后做一下出发算一下也行首先得有一张画布搞起&#xff0c;然后循环列数去绘画字符定时器循环…

泰森多边形半平面求交 - 洛谷 - P3297 [SDOI2013] 逃考

欢迎关注更多精彩 关注我&#xff0c;学习常用算法与数据结构&#xff0c;一题多解&#xff0c;降维打击。 往期相关背景半平面求交 点击前往 voronoi 图求解点击前往 题目大意 题目链接 https://www.luogu.com.cn/problem/P3297 小杨家是一个矩阵&#xff0c;所有亲戚都在…

Monkey工具之fastbot-iOS实践

背景 目前移动端App上线后 crash 率比较高&#xff0c; 尤其在iOS端。我们需要一款Monkey工具测试App的稳定性&#xff0c;更早的发现crash问题并修复。 去年移动开发者大会上有参加 fastbot 的分享&#xff0c;所以很自然的就想到Fastbot工具。 Fastbot-iOS安装配置 准备工…

变电站蓄电池在线监测系统(论文+源码)

1. 系统设计 本次课题为变电站蓄电池在线监测系统的设计&#xff0c;其系统架构如图3.1所示&#xff0c;包括了主控制器STC89C52单片机&#xff0c;液晶显示器LCD1602,模数转换器ADC0832&#xff0c;电流传感器ACS712&#xff0c;分压电阻&#xff0c;蜂鸣器以及温度传感器。在…

实用篇 | 3D建模中Blender软件的下载及使用[图文详情]

本文基于数字人系列的3D建模工具Blender软件的安装及使用&#xff0c;还介绍了图片生成3D模型的AI工具~ 目录 1.Blender的下载 2.Blender的使用 3.安装插件(通过压缩包安装) 4.实例 4.1.Blender使用MB-Lab插件快速人体模型建构 4.1.1.点击官网&#xff0c;进行下载 4.1.…

消息可靠性保证

回顾RabbitMQ的消息传递过程 如图所示&#xff0c;发生消息丢失的可能阶段也就是生产者发送消息&#xff0c;时rabbitmq存储消息时&#xff0c;消费者消费消息时。项目源码&#xff1a;gitee 生产者发送消息阶段 生产者发送消息时把交换机名写错生产者发送消息时把routingK…

推荐一款好用的包含表格识别的OCR网站

在当今数字化的时代&#xff0c;文字和表格识别已经成为了许多行业的关键技术。无论是处理大量的纸质文档&#xff0c;还是从网络上收集数据&#xff0c;OCR&#xff08;光学字符识别&#xff09;技术都扮演着重要的角色。然而&#xff0c;对于许多用户来说&#xff0c;OCR软件…

Infobright列存数据库原理介绍

简介 Infobright 是一个面向 OLAP 场景的开源列存数据库。比较容易找到代码的版本是 Infobright Community Edition 4.0.7&#xff0c;大概是 2006 年前后的代码。2016 年6 月&#xff0c;Infobright 决定停止开源1。由于它同时提供企业版和社区版&#xff0c;开源版本的功能相…

斑马zebra目标检测数据集VOC+YOLO格式2300张

斑马是由四百万年前的原马进化出来的&#xff0c;最早出现的斑马可能是细纹斑马。有关史前马科动物的化石现存于美国爱达荷州克文的克文化石床国家博物馆。斑马的史前马为“克文马”&#xff08;美洲斑马或者克文斑马&#xff09;&#xff0c;学名为“Equussimplicidens”&…

WordPress VIP收费下载插件Erphpdown v17.0.1 开心版

会员推广下载专业版 WordPress插件&#xff08;erphpdown&#xff09;是模板兔开发的一款针对虚拟资源收费下载/付费下载/付费视频/收费查看/付费阅读/付费查看/VIP下载查看的插件&#xff0c;经过完美测试运行于wordpress 3.x-5.x版本。后续模板兔会增加更多实用的功能。 模板…

docker部署go gin框架 Linux环境

目录 文章目的是什么 环境介绍 Linux 环境下 docker 部署 go gin 详细步骤 部署 gin 文章目的是什么 假设我们学习了 go 语言&#xff0c;在 Linux 上安装了 go 相关的程序&#xff0c;也能直接运行&#xff0c;使用以下命令&#xff1a; go run main.go 假如代码是这样的…

跟着我学Python基础篇:08.集合和字典

往期文章 跟着我学Python基础篇&#xff1a;01.初露端倪 跟着我学Python基础篇&#xff1a;02.数字与字符串编程 跟着我学Python基础篇&#xff1a;03.选择结构 跟着我学Python基础篇&#xff1a;04.循环 跟着我学Python基础篇&#xff1a;05.函数 跟着我学Python基础篇&#…

java设计模式学习之【代理模式】

文章目录 引言代理模式简介定义与用途实现方式 使用场景优势与劣势在Spring框架中的应用图片加载示例代码地址 引言 在现实生活中&#xff0c;我们经常使用代理来处理我们不想直接参与或无法直接参与的事务&#xff0c;例如&#xff0c;使用律师来代表法庭上的案件。在软件开发…

计算机网络——网络层——OSPF协议的介绍

什么是 OSPF &#xff1f; OSPF 是一个基于链路状态的自治系统内部路由协议&#xff0c;在 TCP/IP 的网络层中进行路由选择&#xff0c;常用于构建大型企业网络或者服务上的骨干网络。在互联网核心路由器之间也可以使用。 OSPF 概述 OSPF 使用的是 Dijkstra&#xff08;最短…

Vue 实现一个弹出框,允许用户输入信息,并在确认时将输入的信息进行输出到控制台

父组件用来点击按钮弹出弹出框 <!--ParentComponent.vue--> <template><div><button click"showPopupV">点我会有个弹出框&#xff01;&#xff01;&#xff01;</button><PopupComponent v-if"showPopup" :data"p…

【退订】阿里云产品

之前因为学习需要使用了阿里云上的产品服务&#xff0c;项目结束后给忘记了&#xff0c;直到最近阿里云发短信我才知道&#xff1a; 我使用的是datawork的服务&#xff0c;现在先登录阿里云官网&#xff1a; 阿里云-计算&#xff0c;为了无法计算的价值 (aliyun.com) 之后点…

【毕业设计】基于STM32的智能衣柜设计

1、功能说明 功能如下: 1、用stm32控制ds18b20采集温度 2、然后按键可以设置上下限温度&#xff0c; 3、采集的温度低于下限温度时候 打开加热片开始加热&#xff0c; 4、加热到上限温度关闭加热片停止加热&#xff0c; 5、采集的温度可以在oled显示&#xff0c; 6、然后弄个按…
最新文章