【从零开始学习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();}}
}
反射还提供了许多其他功能,如获取类的构造方法、接口、父类,获取注解信息等。
需要注意的是,使用反射时要注意权限的限制(如私有成员的访问)以及性能问题(反射操作比直接调用性能较差)。另外,运用反射应尽量遵循设计原则,避免滥用反射,保证代码的可读性和可维护性。
反射的应用场景:
-
框架开发:反射常被用于框架的开发,通过读取配置文件或注解来动态地加载类、创建对象、调用方法和访问字段,从而实现灵活可扩展的框架结构。
-
对象实例化:通过反射可以实现动态地创建对象实例。通过类的
Constructor
对象可以调用不同的构造方法,为对象传递不同的参数,从而根据需要来创建对象。 -
调用方法和访问字段:反射可以用于调用类的方法和访问类的字段。通过方法的
Method
对象可以调用类的不同方法,通过字段的Field
对象可以读取和写入类的字段值。 -
探索类的信息:通过反射可以获取类的详细信息,如类名、父类、接口、方法和字段等。这对于编写通用的代码和进行类似于文档生成、序列化和验证等操作非常有用。
-
动态代理:反射在实现动态代理时发挥了重要作用。通过反射可以动态地生成代理类,并在代理类的方法调用中添加额外的逻辑,如日志记录、权限验证等。
-
单元测试:反射可以用于编写单元测试时的Mock对象。通过反射可以创建假对象并模拟实际对象的行为,从而进行更全面的单元测试。
使用反射的优缺点:
优点:
-
动态性:反射提供了在运行时动态获取和操作类的能力。可以动态地创建对象、调用方法和访问字段,这使得代码更具灵活性和可扩展性。
-
通用性:通过反射可以编写通用的代码,不依赖于具体的类和接口。可以在不了解类结构的情况下获取类的信息,并根据需要来操作类的成员。
-
框架支持:反射被广泛应用于框架的开发,框架可以通过读取配置文件或注解来动态加载类和创建对象,从而实现灵活可配置的框架结构。
-
灵活性:反射使得可以在运行时根据条件来动态地选择和执行代码,而不是在编译时进行静态绑定。这在某些特定的业务场景下非常有用。例如,根据配置文件动态选择不同的实现类。
缺点:
-
性能开销:反射通常比直接调用代码要慢,因为它需要进行额外的查找、检查和调用。反射调用的性能开销相对较高,可能对性能敏感的应用程序需要谨慎使用。
-
安全性问题:使用反射可以绕过类的访问控制和安全检查机制,这可能导致安全漏洞。因此,在使用反射时,需要保证代码的安全性,并确保只有受信任的代码可以访问敏感操作。
-
编译器检查缺失:反射可以让代码更加动态,但也会失去编译器在代码编译阶段进行错误检查的能力。一些错误可能在运行时才能被发现,增加了调试的困难性。
总结:
反射是Java中的一项强大功能,通过它我们可以在运行时动态地获取和操作类的成员。使用反射可以实现灵活性、通用性和动态性,提供了诸如创建对象、调用方法和访问字段等功能。然而,反射也有一些缺点,如性能开销和安全性问题。因此,在使用反射时需要权衡利弊,确保使用安全可靠,并遵循最佳实践。总之,反射为Java程序提供了更大的灵活性和扩展性,使代码编写更加通用且适应动态变化的需求。
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!
相关文章:

【从零开始学习JAVA | 第四十五篇】反射
目录 前言: 反射: 使用反射的步骤: 1.获取阶段: 2.使用阶段: 反射的应用场景: 使用反射的优缺点: 总结: 前言: Java中的反射是一项强大而灵活的功能࿰…...
顺丰科技数据治理实践
01 顺丰数据治理体系演进路线 顺丰做数据治理十多年,数据治理体系的模块是逐步来建设的。十年前,我们就已经建了数仓,同步做了元数据管理,数据质量管理,以及数据安全的管理。顺丰数据治理的演进路线分 3 个阶段。 第…...

Nginx+Tomcat负载均衡、动静分离实例详细部署
一、反向代理两种模式 四层反向代理 基于四层的iptcp/upd端口的代理 他是http块同一级,一般配置在http块上面。 他是需要用到stream模块的,一般四层里面没有自带,需要编译安装一下。并在stream模块里面添加upstream 服务器名称,…...

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的内置函数:getline 1.7 文本过滤打印 1.8 awk条件判断打印 1.9 三元表达式,类似于java 1.10 awk的精确筛选 1.11 awk和tr比较改变…...

探索FSM (有限状态机)应用
有限状态机(FSM) 是计算机科学中的一种数学模型,可用于表示和控制系统的行为。它由一组状态以及定义在这些状态上的转换函数组成。FSM 被广泛用于计算机程序中的状态机制。 有限状态机(FSM)应用场景 在各种自动化系统…...
6.continue break
6.1continue 关键字 continue 关键字用于立即跳出本次循环,继续下一次循环(本次循环体continue之后的代码会少执行一次)。 例如:吃5个包子,第3个有虫子,就扔掉第3个包子,继续吃第4个第5个包子…...
如何在Linux中强制关闭卡住的PyCharm
在使用PyCharm进行Python开发时,有时可能会遇到卡顿或无响应的情况。当PyCharm卡住时,我们需要强制关闭它以恢复正常操作。今天,我们将介绍在Linux系统中如何强制关闭PyCharm的几种方法。 1. 使用键盘快捷键 在PyCharm所在的窗口中…...
c# Excel数据的导出与导入
搬运:Datagrideview 数据导出Excel , Exel数据导入 //------------------------------------------------------------------------------------- // All Rights Reserved , Copyright (C) 2013 , DZD , Ltd . //----------------------------------------------------------…...

Kotlin~Mediator中介者模式
概念 创建一个中介来降低对象之间的耦合度,关系”多对多“变为“一对多”。 角色介绍 Mediator:抽象中介者,接口或者抽象类。ConcreteMediator:中介者具体实现,实现中介者接口,定义一个List管理Colleagu…...
石子合并问题
一.试题 在一个园形操场的四周摆放N堆石子(N≤100),现要将石子有次序地合并成一堆。规定 每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 编一程序,由文件读入…...
剑指Offer-搜索与回溯算法
文章目录 剑指 Offer 32 - I. 从上到下打印二叉树题意:解:代码: 剑指 Offer 32 - II. 从上到下打印二叉树 II题意:解:代码: 剑指 Offer 32 - III. 从上到下打印二叉树 III题意:解:代…...

【云原生】Docker 详解(三):Docker 镜像管理基础
Docker 详解(三):Docker 镜像管理基础 1.镜像的概念 镜像可以理解为应用程序的集装箱,而 Docker 用来装卸集装箱。 Docker 镜像含有启动容器所需要的文件系统及其内容,因此,其用于创建并启动容器。 Dock…...

SD-MTSP:蜘蛛蜂优化算法SWO求解单仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)
一、蜘蛛蜂优化算法SWO 蜘蛛蜂优化算法(Spider wasp optimizer,SWO)由Mohamed Abdel-Basset等人于2023年提出,该算法模型雌性蜘蛛蜂的狩猎、筑巢和交配行为,具有搜索速度快,求解精度高的优势。蜘蛛蜂优化算…...
【ARM 嵌入式 编译系列 3.1 -- GCC __attribute__((used)) 使用】
文章目录 __attribute__((used)) 属性介绍代码演示编译与输出GCC 编译选项 上篇文章:ARM 嵌入式 编译系列 3 – GCC attribute((weak)) 弱符号使用 下篇文章:ARM 嵌入式 编译系列 3.2 – glibc 学习 __attribute__((used)) 属性介绍 在普通的 C/C 程序中…...

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

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

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

Exams/ece241 2013 q4
蓄水池问题 S3 S2 S1 例如:000 代表 无水 ,需要使FR3, FR2, FR1 都打开(111) S3 S2 S1 FR3 FR2 FR1 000 111 001 011 011 001 111 000 fr代表水变深为…...

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

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...