【从零开始学习JAVA | 第四十五篇】反射

目录

前言:

​反射:

 使用反射的步骤:

1.获取阶段:

2.使用阶段:

反射的应用场景:

使用反射的优缺点:

总结:


前言:

Java中的反射是一项强大而灵活的功能,它允许程序在运行时动态地获取、操作和利用类的信息。通过反射,我们可以在运行时检查和修改类的属性、调用类的方法,甚至创建和操作对象实例。这种能力为Java提供了很多灵活性和扩展性,使得我们能够编写更加通用、可插拔和动态的代码。然而,反射也是一种高级特性,需要谨慎使用,因为它可能牺牲了一些性能和类型安全性。在本文中,我们将深入探究Java反射的原理、用法和最佳实践。

反射:

                反射是一种在运行时动态获取、检查和操作类的信息的能力。它允许程序在运行时通过类的名称获取其完整结构,并可以实例化对象、调用方法、访问属性和执行其他与类相关的操作,而无需在编译时明确引用这些类。反射的核心是java.lang.reflect包,它提供了一组类和接口,用于实现反射功能。使用反射,可以实现一些灵活和通用的编程技术,如动态加载类、配置文件解析、框架扩展和代码生成。然而,反射也会带来性能上的开销,并且破坏了编译时类型检查,因此在使用时需要注意适度和合理性。

也就是说:反射可以把类中的成员变量,成员方法和构造方法单独拿出来进行访问,我们是否会好奇我们自定义类之后,idea为什么会有提示功能?

其实这就是通过反射来实现的。 

 使用反射的步骤:

1.获取阶段:

在获取阶段,我们使用反射机制来获取与类、方法、字段等相关的信息。这包括获取类的Class对象构造方法方法字段等,并可以检查类的继承关系、接口实现以及注解等元数据信息。获取阶段提供了对类结构的探索和解析的能力,让我们能够动态地获取类的结构信息。

(1)利用反射获取class对象

public class test01 {public static void main(String[] args) throws ClassNotFoundException {//获取class文件://第一种Class<?> aClass = Class.forName("Myrflect.student");System.out.println(aClass);//第二种:Class<student> studentClass = student.class;System.out.println(studentClass);//第三种:student st = new student();Class<? extends student> aClass1 = st.getClass();System.out.println(aClass1);}
}

(2)利用反射获得构造方法

public class getcontrbute {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {//1.获取字节码文件对象Class<?> aClass = Class.forName("Myrflect.student");//1.获取公共的构造方法:Constructor<?>[] constructors = aClass.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println(constructor);}System.out.println("-------------------------");//2.获取私有的构造方法Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();for (Constructor<?> cons : declaredConstructors) {System.out.println(cons);}System.out.println("-------------------------");//3.获取单个的构造方法Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();System.out.println(declaredConstructor);Constructor<?> declaredConstructor1 = aClass.getDeclaredConstructor(String.class,int.class,String.class);System.out.println(declaredConstructor1);}
}

(3)反射获取成员变量

public class getmember {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {//1.获取Class字节码文件对象Class<?> aClass = Class.forName("Myrflect.student");//1.获取所有公告成员变量对象的数组Field[] fields = aClass.getFields();for (Field field : fields) {System.out.println(field);}System.out.println("---------------");//2.获取所有成员变量对象的数组Field[] declaredFields = aClass.getDeclaredFields();for (Field field : declaredFields) {System.out.println(field);}System.out.println("---------------");//3.获取单个成员变量Field name = aClass.getField("name");System.out.println(name);}
}

 (4)反射获取成员方法

public class getway {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {Class<?> aClass = Class.forName("Myrflect.student");//1.获取所有公共方法对象(包含父类,而每一个类都继承Object类,因此打印会出现很多方法)Method[] methods = aClass.getMethods();for (Method method : methods) {System.out.println(method);}System.out.println("-----------------------------");//2.获取所有方法对象(不包含父类)Method[] declaredMethods = aClass.getDeclaredMethods();for (Method method : declaredMethods) {System.out.println(method);}System.out.println("-----------------------------");//3.获取单个方法Method method = aClass.getMethod("getAge");System.out.println(method);}
}

2.使用阶段:

在获取了类的结构信息后,我们可以使用反射机制来动态地实例化对象、调用方法、访问字段等操作。使用阶段利用获取阶段得到的信息,通过反射来操作类的成员,实现灵活、通用和动态的功能。使用阶段可以根据实际需求来动态地操作类的成员,而无需在编译时提前确定具体的类和成员。

public class ReflectionExample {public static void main(String[] args) {try {// 读取和写入字段MyClass obj = new MyClass();Class<?> clazz = obj.getClass();// 获取公共字段Field publicField = clazz.getField("publicField");System.out.println("Public Field Initial Value: " + publicField.get(obj));// 设置字段的值publicField.set(obj, "New Value");System.out.println("Public Field Updated Value: " + publicField.get(obj));// 获取私有字段Field privateField = clazz.getDeclaredField("privateField");privateField.setAccessible(true); // 设置私有字段可访问System.out.println("Private Field Initial Value: " + privateField.get(obj));// 设置私有字段的值privateField.set(obj, 123);System.out.println("Private Field Updated Value: " + privateField.get(obj));// 调用方法Method method = clazz.getMethod("publicMethod");method.invoke(obj); // 执行公共方法// 创建对象Constructor<?> constructor = clazz.getConstructor();Object newObj = constructor.newInstance();System.out.println("New Object: " + newObj);} catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException | InstantiationException e) {e.printStackTrace();}}
}

反射还提供了许多其他功能,如获取类的构造方法、接口、父类,获取注解信息等。

需要注意的是,使用反射时要注意权限的限制(如私有成员的访问)以及性能问题(反射操作比直接调用性能较差)。另外,运用反射应尽量遵循设计原则,避免滥用反射,保证代码的可读性和可维护性。

反射的应用场景:

  1. 框架开发:反射常被用于框架的开发,通过读取配置文件或注解来动态地加载类、创建对象、调用方法和访问字段,从而实现灵活可扩展的框架结构。

  2. 对象实例化:通过反射可以实现动态地创建对象实例。通过类的Constructor对象可以调用不同的构造方法,为对象传递不同的参数,从而根据需要来创建对象。

  3. 调用方法和访问字段:反射可以用于调用类的方法和访问类的字段。通过方法的Method对象可以调用类的不同方法,通过字段的Field对象可以读取和写入类的字段值。

  4. 探索类的信息:通过反射可以获取类的详细信息,如类名、父类、接口、方法和字段等。这对于编写通用的代码和进行类似于文档生成、序列化和验证等操作非常有用。

  5. 动态代理:反射在实现动态代理时发挥了重要作用。通过反射可以动态地生成代理类,并在代理类的方法调用中添加额外的逻辑,如日志记录、权限验证等。

  6. 单元测试:反射可以用于编写单元测试时的Mock对象。通过反射可以创建假对象并模拟实际对象的行为,从而进行更全面的单元测试。

使用反射的优缺点:

优点:

  1. 动态性:反射提供了在运行时动态获取和操作类的能力。可以动态地创建对象、调用方法和访问字段,这使得代码更具灵活性和可扩展性。

  2. 通用性:通过反射可以编写通用的代码,不依赖于具体的类和接口。可以在不了解类结构的情况下获取类的信息,并根据需要来操作类的成员。

  3. 框架支持:反射被广泛应用于框架的开发,框架可以通过读取配置文件或注解来动态加载类和创建对象,从而实现灵活可配置的框架结构。

  4. 灵活性:反射使得可以在运行时根据条件来动态地选择和执行代码,而不是在编译时进行静态绑定。这在某些特定的业务场景下非常有用。例如,根据配置文件动态选择不同的实现类。

缺点:

  1. 性能开销:反射通常比直接调用代码要慢,因为它需要进行额外的查找、检查和调用。反射调用的性能开销相对较高,可能对性能敏感的应用程序需要谨慎使用。

  2. 安全性问题:使用反射可以绕过类的访问控制和安全检查机制,这可能导致安全漏洞。因此,在使用反射时,需要保证代码的安全性,并确保只有受信任的代码可以访问敏感操作。

  3. 编译器检查缺失:反射可以让代码更加动态,但也会失去编译器在代码编译阶段进行错误检查的能力。一些错误可能在运行时才能被发现,增加了调试的困难性。

总结:

反射是Java中的一项强大功能,通过它我们可以在运行时动态地获取和操作类的成员。使用反射可以实现灵活性、通用性和动态性,提供了诸如创建对象、调用方法和访问字段等功能。然而,反射也有一些缺点,如性能开销和安全性问题。因此,在使用反射时需要权衡利弊,确保使用安全可靠,并遵循最佳实践。总之,反射为Java程序提供了更大的灵活性和扩展性,使代码编写更加通用且适应动态变化的需求。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

 

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

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

相关文章

Android Framework工具——EA画图

EA 是一个著名的企业架构(Enterprise Architecture)工具,用于绘制和管理企业的架构图和过程模型。该工具提供了多种功能,包括建立业务流程图、数据流图、组织结构图、应用架构图等。EA工具可帮助企业进行战略规划、业务流程改进和系统开发等活动。 一、用例图 1、创建项目…

SAP从入门到放弃系列之BOM组-Part1

目录 BOM组两种模式&#xff1a; 创建BOM的方式 方式一&#xff1a;直接在每个工厂分别创建BOM。 方式二&#xff1a;创建BOM组&#xff0c;然后每个工厂参考创建 方式三&#xff1a;创建BOM组&#xff0c;每个工厂参考创建&#xff0c;针对有特殊的工厂复制BOM组后进行调…

Hadoop Hbase Hive 版本对照一览

这里写目录标题 一、Hadoop 与 Hbase 版本对照二、Hadoop 与 Hive 版本对照 官网内容记录&#xff0c;仅供参考 一、Hadoop 与 Hbase 版本对照 二、Hadoop 与 Hive 版本对照

基于Java+SpringMVC+Mybaties+layui+Vue+elememt基于协同过滤的电影推荐系统的设计与实现

一.项目介绍 基于协调过滤的电影推荐系统的设计与实现 本系统分为普通用户以及管理员两类 普通用户&#xff1a; 登录系统查看最新推荐电影、收藏、评论、查看电影信息、 对电影进行评分、浏览电影资讯信息、查看个人信息以及浏览收藏…

Arcgis中影像图切片有白斑或者白点

效果 步骤 1、3dmax渲染或者其它原片 2、Arcgis中加载图片 原数据效果 3、定义投影和转换坐标系等等 我这边测试数据是EPSG:4326的坐标系 4、导出jp2(JPG2000)格式 转换后效果 5、发布服务 6、效果对比

嗅探抓包工具,解决线上偶现问题来不及抓包的情况阅读目录

目录 背景 实现思路 具体实现 Python 抓包 总结 资料获取方法 背景 测试群里经常看到客户端的同学反馈发现了偶现Bug&#xff0c;但是来不及抓包&#xff0c;最后不了了之&#xff0c;最近出现得比较频繁&#xff0c;所以写个小脚本解决这个问题。 实现思路 之前写过一个…

02Mysql之多表查询--例题讲解

一、题目详情&#xff0c;以及表的建立 新增员工表emp和部门表deptcreate table dept (dept1 int ,dept_name varchar(11));create table emp (sid int ,name varchar(11),age int,worktime_start date,incoming int,dept2 int);insert into dept values(101,财务),(102,销售)…

IntelliJ IDEA快捷键大全

文章目录 1、构建/编译2、文本编辑3、光标操作4、文本选择5、代码折叠6、辅助编码7、上下文导航8、查找操作9、符号导航10、代码分析11、运行和调试12、代码重构13、全局 CVS 操作14、差异查看器15、工具窗口 本文参考了 IntelliJ IDEA 的官网&#xff0c;列举了IntelliJ IDEA&…

Jmeter 配置环境变量,简明教程专享

通过给 JMeter 配置环境变量&#xff0c;可以快捷的打开 JMeter&#xff1a; 打开终端。执行 jmeter。 配置环境变量的方法如下。 Mac 和 Linux 系统 在 ~/.bashrc 中加如下内容&#xff1a; export JMETER_HOMEJMeter所在目录 export PATH$JAVA_HOME/bin:$PATH:.:$JMETER…

记录一下shardingsphere-jdbc查询分表使用union all的低级错误

使用shardingsphere-jdbc查询犯的低级错误&#xff0c;union all 字段没对齐&#xff0c;导致分片值有空值或数据不对&#xff0c;分片结果不对 有个数据同步的功能&#xff0c;对应的表使用到了shardingsphere-jdbc进行分表&#xff0c;所以想着是用shardingsphere-jdbc取数据…

Unity3D高级编程:主程手记学习1

第一章 软件架构 Untiy 分层设计 分层后再分治

leetcode经典算法——快速幂

实现 pow(x, n) &#xff0c;即计算 x 的整数 n 次幂函数&#xff08;即&#xff0c;xn &#xff09;。 暴力方法肯定是循环循环n次&#xff0c; 每一次*x 显然此方法遇到大的数字会超时 那么我们要引进一个思想&#xff0c;快速幂算法 例如&#xff1a; x^97 我们可以看出&a…

23款奔驰C260升级原厂香氛负离子系统,清香宜人,久闻不腻

奔驰原厂香氛合理性可通过车内空气调节组件营造芳香四溢的怡人氛围。通过更换手套箱内香氛喷雾发生器所用的香水瓶&#xff0c;可轻松选择其他香氛。香氛的浓度和持续时间可调。淡雅的香氛缓缓喷出&#xff0c;并且在关闭后能够立刻散去。车内气味不会永久改变&#xff0c;香氛…

【网络】高级IO

目录 一、五种IO模型 1、阻塞IO 2、非阻塞IO 3、信号驱动 4、IO多路转接 5、异步IO 6、总结 二、高级IO重要概念 1、同步通信与异步通信 2、阻塞 vs 非阻塞 三、非阻塞IO 1、fcntl 2、实现函数SetNoBlock 四、IO多路转接select 1、select 1.1、参数解释 1.2、…

PCL 计算外接圆的半径

目录 一、算法原理1、计算公式2、主要函数3、源码解析二、代码实现三、结果展示四、参考链接本文由CSDN点云侠原创,原文链接。爬虫自重。 一、算法原理 1、计算公式

机器学习笔记:李宏毅chatgpt 大模型 大资料

1 大模型 1.1 大模型的顿悟时刻 Emergent Abilities of Large Language Models&#xff0c;Transactions on Machine Learning Research 2022 模型的效果不是随着模型参数量变多而慢慢变好&#xff0c;而是在某一个瞬间&#xff0c;模型“顿悟”了 这边举的一个例子是&#…

PHP利用PCRE回溯次数限制绕过某些安全限制实战案例

目录 一、正则表达式概述 有限状态自动机 匹配输入的过程分别是&#xff1a; DFA&#xff08;确定性有限状态自动机&#xff09; NFA&#xff08;非确定性有限状态自动机&#xff09; 二、回溯的过程 三、 PHP 的 pcre.backtrack_limit 限制利用 例题一 回溯绕过步骤 &…

谱包络之pysptk和pyworld

谱包络之pysptk和pyworld 谱包络可以直接用于语音的合成&#xff0c;常用的两个计算谱包络的库pysptk和pyword。 先看看代码&#xff1a; 一段语音x&#xff0c;采样率16000Hz pysptk import pysptkframe_length 1024 hop_length 80 order 25 alpha 0.41 frames libro…

ubuntu python 查看系统是否可用 cuda

ubuntu python 查看系统是否可用 cuda 初环境与设备查看环境演示效果 本篇文章将介绍ubuntu python 查看系统是否可用 cuda 初 希望能写一些简单的教程和案例分享给需要的人 环境与设备 系统&#xff1a;ubuntu 22.04 工具&#xff1a;python 3.10.6 设备&#xff1a;Nvidi…

哪些人会看作业指导书?作业指导书怎样才能发挥作用?

一般人普遍人为&#xff0c;作业指导书就是给操作人员看的。其实不然&#xff0c;那么哪些人会看作业指导书&#xff1f;大致可以分为: 第一类&#xff1a;新到工作岗位的员工。其中包括新进员工和新转岗位的员工&#xff0c;他们都会在师傅或领班组长的带领指导下&#xff0c;…