当前位置: 首页 > news >正文

【从零开始学习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程序提供了更大的灵活性和扩展性,使代码编写更加通用且适应动态变化的需求。

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

 

相关文章:

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

目录 前言&#xff1a; ​反射&#xff1a; 使用反射的步骤&#xff1a; 1.获取阶段&#xff1a; 2.使用阶段&#xff1a; 反射的应用场景&#xff1a; 使用反射的优缺点&#xff1a; 总结&#xff1a; 前言&#xff1a; Java中的反射是一项强大而灵活的功能&#xff0…...

顺丰科技数据治理实践

01 顺丰数据治理体系演进路线 顺丰做数据治理十多年&#xff0c;数据治理体系的模块是逐步来建设的。十年前&#xff0c;我们就已经建了数仓&#xff0c;同步做了元数据管理&#xff0c;数据质量管理&#xff0c;以及数据安全的管理。顺丰数据治理的演进路线分 3 个阶段。 第…...

Nginx+Tomcat负载均衡、动静分离实例详细部署

一、反向代理两种模式 四层反向代理 基于四层的iptcp/upd端口的代理 他是http块同一级&#xff0c;一般配置在http块上面。 他是需要用到stream模块的&#xff0c;一般四层里面没有自带&#xff0c;需要编译安装一下。并在stream模块里面添加upstream 服务器名称&#xff0c;…...

Java多线程(3)---锁策略、CAS和JUC

目录 前言 一.锁策略 1.1乐观锁和悲观锁 ⭐ 两者的概念 ⭐实现方法 1.2读写锁 ⭐概念 ⭐实现方法 1.3重量级锁和轻量级锁 1.4自旋锁和挂起等待锁 ⭐概念 ⭐代码实现 1.5公平锁和非公平锁 1.6可重入锁和不可重入锁 二.CAS 2.1为什么需要CAS 2.2CAS是什么 ⭐CAS…...

Linux:Shell编辑之文本处理器(awk)

目录 绪论 1、用法 1.1 格式选项 1.2 awk 常用内置变量 1.3 awk的打印功能 1.4 奇偶打印 1.5 awk运算 1.6 awk的内置函数&#xff1a;getline 1.7 文本过滤打印 1.8 awk条件判断打印 1.9 三元表达式&#xff0c;类似于java 1.10 awk的精确筛选 1.11 awk和tr比较改变…...

探索FSM (有限状态机)应用

有限状态机&#xff08;FSM&#xff09; 是计算机科学中的一种数学模型&#xff0c;可用于表示和控制系统的行为。它由一组状态以及定义在这些状态上的转换函数组成。FSM 被广泛用于计算机程序中的状态机制。 有限状态机&#xff08;FSM&#xff09;应用场景 在各种自动化系统…...

6.continue break

6.1continue 关键字 continue 关键字用于立即跳出本次循环&#xff0c;继续下一次循环&#xff08;本次循环体continue之后的代码会少执行一次&#xff09;。 例如&#xff1a;吃5个包子&#xff0c;第3个有虫子&#xff0c;就扔掉第3个包子&#xff0c;继续吃第4个第5个包子…...

如何在Linux中强制关闭卡住的PyCharm

在使用PyCharm进行Python开发时&#xff0c;有时可能会遇到卡顿或无响应的情况。当PyCharm卡住时&#xff0c;我们需要强制关闭它以恢复正常操作。今天&#xff0c;我们将介绍在Linux系统中如何强制关闭PyCharm的几种方法。 1. 使用键盘快捷键 在PyCharm所在的窗口中&#xf…...

c# Excel数据的导出与导入

搬运:Datagrideview 数据导出Excel , Exel数据导入 //------------------------------------------------------------------------------------- // All Rights Reserved , Copyright (C) 2013 , DZD , Ltd . //----------------------------------------------------------…...

Kotlin~Mediator中介者模式

概念 创建一个中介来降低对象之间的耦合度&#xff0c;关系”多对多“变为“一对多”。 角色介绍 Mediator&#xff1a;抽象中介者&#xff0c;接口或者抽象类。ConcreteMediator&#xff1a;中介者具体实现&#xff0c;实现中介者接口&#xff0c;定义一个List管理Colleagu…...

石子合并问题

一&#xff0e;试题 在一个园形操场的四周摆放N堆石子&#xff08;N≤100&#xff09;&#xff0c;现要将石子有次序地合并成一堆。规定 每次只能选相邻的两堆合并成新的一堆&#xff0c;并将新的一堆的石子数&#xff0c;记为该次合并的得分。 编一程序&#xff0c;由文件读入…...

剑指Offer-搜索与回溯算法

文章目录 剑指 Offer 32 - I. 从上到下打印二叉树题意&#xff1a;解&#xff1a;代码&#xff1a; 剑指 Offer 32 - II. 从上到下打印二叉树 II题意&#xff1a;解&#xff1a;代码&#xff1a; 剑指 Offer 32 - III. 从上到下打印二叉树 III题意&#xff1a;解&#xff1a;代…...

【云原生】Docker 详解(三):Docker 镜像管理基础

Docker 详解&#xff08;三&#xff09;&#xff1a;Docker 镜像管理基础 1.镜像的概念 镜像可以理解为应用程序的集装箱&#xff0c;而 Docker 用来装卸集装箱。 Docker 镜像含有启动容器所需要的文件系统及其内容&#xff0c;因此&#xff0c;其用于创建并启动容器。 Dock…...

SD-MTSP:蜘蛛蜂优化算法SWO求解单仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)

一、蜘蛛蜂优化算法SWO 蜘蛛蜂优化算法&#xff08;Spider wasp optimizer&#xff0c;SWO&#xff09;由Mohamed Abdel-Basset等人于2023年提出&#xff0c;该算法模型雌性蜘蛛蜂的狩猎、筑巢和交配行为&#xff0c;具有搜索速度快&#xff0c;求解精度高的优势。蜘蛛蜂优化算…...

【ARM 嵌入式 编译系列 3.1 -- GCC __attribute__((used)) 使用】

文章目录 __attribute__((used)) 属性介绍代码演示编译与输出GCC 编译选项 上篇文章&#xff1a;ARM 嵌入式 编译系列 3 – GCC attribute((weak)) 弱符号使用 下篇文章&#xff1a;ARM 嵌入式 编译系列 3.2 – glibc 学习 __attribute__((used)) 属性介绍 在普通的 C/C 程序中…...

C++ ModBUS TCP客户端工具 qModMaster 介绍及使用

qModMaster工具介绍 QModMaster是一个基于Qt的Modbus主站&#xff08;Master&#xff09;模拟器&#xff0c;用于模拟和测试Modbus TCP和RTU通信。它提供了一个直观的图形界面&#xff0c;使用户能够轻松设置和发送Modbus请求&#xff0c;并查看和分析响应数据。 以下是QModM…...

笔记本电脑如何把sd卡数据恢复

在使用笔记本电脑过程中&#xff0c;如果不小心将SD卡里面的重要数据弄丢怎么办呢&#xff1f;别着急&#xff0c;本文将向您介绍SD卡数据丢失常见原因和恢复方法。 ▌一、SD卡数据丢失常见原因 - 意外删除&#xff1a;误操作或不小心将文件或文件夹删除。 - 误格式化&#…...

【2023 华数杯全国大学生数学建模竞赛】 B题 不透明制品最优配色方案设计 39页论文及python代码

【2023 华数杯全国大学生数学建模竞赛】 B题 不透明制品最优配色方案设计 39页论文及python代码 1 题目 B 题 不透明制品最优配色方案设计 日常生活中五彩缤纷的不透明有色制品是由着色剂染色而成。因此&#xff0c;不透明制品的配色对其外观美观度和市场竞争力起着重要作用。…...

Exams/ece241 2013 q4

蓄水池问题 S3 S2 S1 例如&#xff1a;000 代表 无水 &#xff0c;需要使FR3, FR2, FR1 都打开&#xff08;111&#xff09; S3 S2 S1 FR3 FR2 FR1 000 111 001 011 011 001 111 000 fr代表水变深为…...

Android OkHttp源码分析--分发器

OkHttp是当下Android使用最频繁的网络请求框架&#xff0c;由Square公司开源。Google在Android4.4以后开始将源码中 的HttpURLConnection底层实现替换为OKHttp&#xff0c;同时现在流行的Retrofit框架底层同样是使用OKHttp的。 OKHttp优点: 1、支持Http1、Http2、Quic以及Web…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...