【从零到Offer】反射那些事

news2024/9/24 15:22:48

什么是反射?

​ 反射简单来说,就是在代码运行期间,通过动态指定任意一个类,从而构建对象,并了解该类的成员变量和方法,甚至可以调用任意一个对象的属性和方法。以String对象为例子,传统构造方式和反射的实现方式如下:

//new 构造方法
String s = new String();

//反射
Class<?> forName = Class.forName("java.lang.String");

​ 从代码中不难看到,第一种通过构造函数构造出来的对象,是在编译前就确定好了的。由此编译程序可以明确的知道当前操作的类是哪个,包含哪些属性、有什么方法。

​ 然而对于第二种实现方式来说,通过反射映射出来的对象完全取决于你给定的字符串是什么。如果我们将这个字符串抽取成配置,那么生产出来的对象自然就会是动态的了。

为什么需要反射?

​ 那么,你可能想问了,好好的new 对象不好吗?为啥还要设计出来一个反射呀?他有什么好处呢?其实,直白来讲,反射牺牲掉了安全、效率,更多的是为了提供更多的灵活性。

​ 假设当前你所负责的代码,要处理两个不同的对象,那么为了完成工作,你可能需要通过多次的if-else判断、处理,哪怕两个对象内的字段名称、类型都是一样的,受限于编译器的限制,你也没法共用同一段代码。

if (i==1){
    // ....执行针对ObjectA的处理方法
    ObjectA o = (ObjectA) input;
    o.setData(xxx);
} else if (i==2) {
    // ....执行针对ObjectB的处理方法
    ObjectB o = (ObjectB) input; 
    o.setData(xxx);
}

​ 但是如果借助于反射,我们就可以将代码充分利用起来,从而最大程度减少代码开发,提升日常效率

if (i==1){
    // ....执行针对ObjectA的处理方法
    Class<?> forName = Class.forName("com.example.demo.base.dto.ObjectA");
} else if (i==2) {
    // ....执行针对ObjectB的处理方法
    Class<?> forName = Class.forName("com.example.demo.base.dto.ObjectB");
}       
Object o = (Object) input;

//同一段处理逻辑,无需再写两次
Field resultStr = forName.getDeclaredField("resultStr");
resultStr.set(o, "1");

​ 在日常代码开发中,也有很多组件无形之中使用到了反射的设计原理。如我们熟悉的Bean拷贝组件BeanUtils,其方便的实现对象间的拷贝逻辑就是基于反射实现的。

如何实现反射?

​ 首先我们知道,我们日常所编写的代码,最后都是会变成.java格式的文档。而.java格式的文档是不可能被机器直接执行的,因为机器只能够看懂二进制的文件。

​ 因此,从.java文件到jvm中可执行的对象,它其实经过了如下的过程:

​ 首先,我们的.java文件会被编译器编译成.class文件,对于每个.class文件,又会被JVM调用类加载的方式,加载到JVM内存中并生成为一个Class对象。这里我们简单看一下Class对象长什么模样:

​ 可以看到Class类对象中包含了许多用于描述类的属性,如类名、所使用的类加载器等。包括通过Class类对象也可以搜索到当前类的构造器、特定的属性域等。

​ 而且对于这个特殊的类来说,我们是不能够对其进行初始化的。可以看到,它只提供了一个私有的构造方法,且需要传入的是类加载器。而且在方法的注释上,也很明确的标注出来,这个构造方法只是提供给JVM创建实例用的,不应该作为默认的类构造器。

​ 通常来说,如果我们需要调用一个Class对象,那么通常只能通过以下的方式:

Class<?> clz = Class.forName("xxx.class");
Class<?> clz = Object.class;
Class<?> clz = Object.getClass();

​ 而且通过不断的往下搜索,我们也可以看到,这个方法的底层实现是通过native方法实现的。(部分java代码通过c等语言实现的,此时会被标记为native方法,是不可以直接调用的。)

​ 虽然我们不能调用,但是本质上这个方法就是通过类加载器获取的过程。了解了这些之后,我们再将咱们的日常使用java类的过程梳理一下:

​ 所以可以看到,反射本质上,维护实例的流程同正常的new创建对象并无过多的差异,他们本质都是基于class对象生成的实例,只是通过new的方式,用户是能够明确知道所需要使用的类的,因此编译器也能方便的对代码进行检查。

​ 而使用反射的方式,则是利用了Class对象,创造出了编码的灵活性。本质思想就是:“你可以是任何类,但我的逻辑对任何类都适配。”通过这样的牺牲掉一些安全性,从而获得编码的灵活性。

参考文献

学习java应该如何理解反射?

java的反射到底是有什么用处?怎么用?

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

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

相关文章

Go语言开发者的Apache Arrow使用指南:数据操作

在前面的Arrow系列文章中&#xff0c;我们介绍了Arrow的基础数据类型[1]以及高级数据类型[2]&#xff0c;这让我们具备了在内存中建立起一个immutable数据集的能力。但这并非我们的目标&#xff0c;我们最终是要对建立起来的数据集进行查询和分析等操作(manipulation)的。 在这…

RecycleView闪屏问题(java和ktolin解决)

问题案例&#xff1a;图库搜索界面点击空格&#xff0c;图片会闪烁两次显示 复现概率 通过布局看是通过RecycleView加载的&#xff0c;通过打印log并无异常闪烁是 notifyDataSetChange 造成的。由于适配器不知道整个数据集中的哪些内容已经存在&#xff0c;在重新匹配 ViewHol…

vscode remote-ssh配置

使用vscode的插件remote-ssh进行linux的远程控制。 在vscode上安装完remote-ssh插件后&#xff0c;还需要安装openssh-client。 openssh-client安装 先win R打开cmd&#xff0c;输入ssh&#xff0c;查看是否已经安装了。 如果没有安装&#xff0c;用管理员权限打开powershe…

LabVIEW将彩色图像转换到灰度图像

LabVIEW将彩色图像转换到灰度图像 在LabVIEW中使用许多图像处理工具的必要步骤之一是将其从彩色转换为单色。介绍一个开发的应用程序&#xff0c;用于基于LabVIEW软件环境&#xff0c;在所有支持的色彩空间&#xff08;RGB、HSI、HSV和HSL&#xff09;中自动将彩色图像转换为灰…

Shi-Tomas角点检测、亚像素级别角点位置优化、ORB特征点、特征点匹配、RANSAC优化特征点匹配、相机模型与投影

目录 1、Shi-Tomas角点检测 2、亚像素级别角点位置优化 3、ORB特征点 4、特征点匹配 5、RANSAC优化特征点匹配 6、相机模型与投影 1、Shi-Tomas角点检测 //Shi-Tomas角点检测 int test1() {Mat img imread("F:/testMap/lena.png");if (!img.data){cout <<…

Python结巴中文分词笔记

&#x1f4da; jieba库基本介绍 &#x1f310; jieba库概述 Jieba是一个流行的中文分词库&#xff0c;它能够将中文文本切分成词语&#xff0c;并对每个词语进行词性标注。中文分词是自然语言处理的重要步骤之一&#xff0c;它对于文本挖掘、信息检索、情感分析等任务具有重要…

2023年Java最新面试题

由【后端面试题宝典】提供 和 equals 的区别是什么&#xff1f; 对于基本类型&#xff0c;比较的是值&#xff1b;对于引用类型&#xff0c;比较的是地址&#xff1b;equals不能用于基本类型的比较&#xff1b;如果没有重写equals&#xff0c;equals就相当于&#xff1b;如果重…

带记忆的Transformer模块

MEMORIZING TRANSFORMERS 返回论文和资料目录 论文地址 1.导读 谷歌去年做的一个工作。内容很简单&#xff0c;在Transformer模块中加入了一层记忆层&#xff0c;结果表明这个方法可以帮助模型提高在NLP任务上的表现&#xff1a;generic webtext (C4), math papers (arXiv),…

C# IEnumerator 用法

一、概述 IEnumerator 是所有非泛型枚举器的基接口。 其泛型等效项是 System.Collections.Generic.IEnumerator<T> 接口。 C# 语言的 foreach 语句&#xff08;在 Visual Basic 中为 for each&#xff09;隐藏了枚举数的复杂性。 因此&#xff0c;建议使用 foreach 而不…

掘金量化—Python SDK文档—1.快速开始

掘金量化终端是一款为专业量化投资打造的功能齐备的落地式终端&#xff0c;集成了策略开发到实盘的模块化功能&#xff0c;打通研究、仿真和绩效链路、兼容多种编程语言&#xff0c;易于使用、性能可靠&#xff0c;能够帮助量化投资者提高策略开发效率、减少 IT 投入。 掘金量…

AI 智能对话 - 基于 ChatGLM2-6B 训练对话知识库

前情提要 怎么将 AI 应用到工作中呢&#xff1f;比如让 AI 帮忙写代码&#xff0c;自己通过工程上的思维将代码整合排版&#xff0c;我挺烦什么代码逻辑严谨性的问题&#xff0c;但是我又不得不承认这样的好处&#xff0c;我们要开始将角色转换出来&#xff0c;不应该是一个工…

Understanding Cascade Left Joins and Writing Complex Queries

文章目录 a left join b left join cuser casesql query execution order In SQL, the left join is a powerful tool for combining data from multiple tables based on a common column. In this blog post, we will explore the concept of cascade left joins, providing …

面试之MySQL中的mvcc

首先需要知道什么是 MVCC? MVCC 多版本并发控制。MVCC就是通过数据行的多个版本管理来实现数据库的并发控制。这项技术是的InnoDB的事务隔离级别下执行一致性读 有了保证。换言之&#xff0c;就是为了查询一些正在被一个事务更新的行。并且可以看到他们被更新之前的值。查询在…

【excel细碎小知识点】

目录索引 &符号的用法&#xff1a;实例演示&#xff1a; 数字显示和位数的区别&#xff1a;分列功能的妙用&#xff1a;什么叫做常规类型&#xff1a; &符号的用法&#xff1a; **连接字符串:**转化后都是文本字符串类型。你可以通过修改数据类型进行更多可能的操作 实…

高等数学❤️第一章~第二节~极限❤️极限的概念与性质~极限的性质详解

【精讲】高等数学中极限的性质解析 博主&#xff1a;命运之光的主页 专栏&#xff1a;高等数学 目录 【精讲】高等数学中极限的性质解析 导言 一、基本性质 二、四则运算 三、极限存在性 四、唯一性 五、其他性质 必需记忆知识点 例题&#xff08;用于熟悉高等数学中…

wordpress怎么更改主题自带的页脚或设置不显示?

本文直接提供改原主题代码的方式进行修改 首先我们进入站点的后台&#xff0c;依次点击外观---->主题文件编辑器 然后确定自己的主题是不是想要更改的&#xff0c;之后找到footer.php文件进行修改 可以自己去找一些合适的主题代码复制进去 如果想要不显示&#xff0c;可以…

《面试1v1》大厂的Kafka使用场景

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

按键控制led变化

文章目录 按键控制led变化一、简介二、代码三、仿真代码四、仿真结果五、总结 按键控制led变化 一、简介 使用按键控制开发板上一个led灯的亮灭&#xff0c;当按键按下的时候led灯就亮&#xff0c;当再一次按下按键的时候led就不亮了。由于按键存在抖动&#xff0c;按键松开的…

linux中常见命令(1)

目录 1. less命令 2. cut 命令 3. head和tail命令 4. awk命令 5. tr命令 6. sed 命令 7. uniq 命令 1. less命令 用法&#xff1a;less [option]<filename>##同时打开多个文件 less <filename1> <filename2> <filename3> 点按“q”退出less。利…

再开源一款轻量内存池

前两天已开源线程池&#xff0c;开源一款轻量线程池项目&#xff0c;本节继续开源另一个孪生兄弟&#xff1a;内存池。 本节的线程池与内存池代码解析会在我的星球详细讲解。 内存池&#xff1a;https://github.com/Light-City/light-memory-pool 线程池&#xff1a;https://gi…