Java反射全面详解
1. 什么是反射?
首先听这个名字就有些疑惑,什么是反射,它能用来干什么呢?
Java官方对反射的解释是 "反射允许对封装类的字段,方法和构造函数进行编程式访问"。这里的字段指的就是成员变量,方法指的就是成员方法,构造函数就是构造方法。
2. 反射有什么用?
我们知道,在类中,常用的有字段,构造方法,成员方法。我们的反射就是可以把一个类中所有的字段,构造方法,成员方法全部都获取出来。那么问题又来了,获取出来有什么用呢?
反射用途还是很多的,我们熟知的IDEA开发工具,他可以在我们编写代码时自动给出提示,提示我们有哪些方法可以用,有哪些构造器可以使用,它是怎么做到的呢?说到这里,不难猜出,它其实就是用的反射。
还有如下所示,我们 new 一个对象,但忘记了它可以传递哪些参数,这个时候我们按键盘上的 Ctrl + P 键,它就会自动弹出提示我们需要传递哪些参数,这个其实也使用反射做到的。
刚才我们说到了, 反射就是可以把一个类中所有的字段,构造方法,成员方法全部都获取出来。
不仅如此,通过反射我们可以获取的非常全面,非常详细,我们甚至可以获取到。
当我们获取字段(变量)时,不仅可以获取到该变量,还能获取到该变量的访问修饰符,名字,类型,并可以为它赋值或者获取初始值;
当我们获取构造方法时,不仅可以获取到构造方法,还能获取到修饰符,名字,形参,还可以创建对象;
当我们获取成员方法时,不仅可以获取到成员方法,也能获取到该方法的修饰符,名字,形参,还能获取方法的返回值,抛出的异常,以及方法上的注解也能获取到,可以说是有什么就能获取到什么,一点不剩的全都可以拿到。
此外有一点要知道,我们获取字段,构造方法,成员方法不是通过Java文件来获取的,而是通过 Class 字节码文件中获取的。
总的来说可以理解为一句话:通过反射我们可以获取到类中的所有信息。
3. 获取 Class 字节码文件对象的三种方式(重中之重,面试会问)
3.1 Class.forName("全类名")方式获取;
其实这种方式应该并不陌生,如果有小伙伴学过JDBC的,应该都大致了解过,通过Class.forName("com.mysql.jdbc.Driver")来获取该类的字节码文件对象。
下面我简单演示一下吧
如下是一个JavaBean类 Account
package cn.itcast.user.pojo;import java.io.Serializable;public class Account implements Serializable {private static final long serialVersionUID = -421643127452356642L;// 账户idprivate Integer accountId;// 账户人名称private String accountName;// 账户密码private transient String accountPassword;public Account(Integer accountId, String accountName, String accountPassword) {this.accountId = accountId;this.accountName = accountName;this.accountPassword = accountPassword;}public Account() {}@Overridepublic String toString() {return "Account{" +"accountId=" + accountId +", accountName='" + accountName + '\'' +", accountPassword='" + accountPassword + '\'' +'}';}public Integer getAccountId() {return accountId;}public void setAccountId(Integer accountId) {this.accountId = accountId;}public String getAccountName() {return accountName;}public void setAccountName(String accountName) {this.accountName = accountName;}public String getAccountPassword() {return accountPassword;}public void setAccountPassword(String accountPassword) {this.accountPassword = accountPassword;}
}
然后我定义一个 main 方法,通过 Class.forName() 的方式来获取,代码如下
public static void main(String[] args) {// 这里可能或出现异常,由于是 main 方法中,最好用 try。。。catch,,,捕获try {System.out.println(Class.forName("cn.itcast.user.pojo.Account"));;} catch (ClassNotFoundException e) {e.printStackTrace();}}
我们直接运行此方法,就可以在控制台得到 Account 类的字节码文件对象,如下所示

3.2 类名.class 方式获取
操作方法如下代码

可以看到也没有任何问题,我就不多做解释了;
3.3 对象.getClass() 方式获取
这里必须是想要反射的类的对象,谁调用getClass,得到的就是谁的类对象。如下代码展示

还有一点可以注意一下,getClass() 方法是定义在 Obeject 类中的,所以所有的对象都可以使用此方法。
3.4 三种方式的通常应用场景
如果我想创建一个类的对象,分为以下三种阶段,每一个阶段都有它适当使用的场景。
阶段一:编写Java文件,将Java文件编写成字节码文件,这个阶段也被称为源代码阶段,可以使用 Class.forName() 的方式来获取;
阶段二:当我们把字节码文件加载到内存中准备运行的时候,可以称为加载阶段,这个阶段通常采用 类名.class 的方式获取字节码文件对象;
阶段三:在内存中运行时,我可以创建类对象,这个阶段也被称为运行阶段,通常采用 对象.getClass() 的方式获取字节码文件对象;
4. 利用反射获取构造方法
获取类的字节码文件之后,我们就可以通过字节码文件对象获取构造方法,我们可以获取单个构造器,可以获取所有构造器,还能创建对象。
如下图所示,即为获取构造方法的方法,我们简单测试一下;

如下代码,实体类 Account,我定义了多个构造器,注释如下
public class Account implements Serializable {private static final long serialVersionUID = -421643127452356642L;// 账户idprivate Integer accountId;// 账户人名称private String accountName;// 账户密码private transient String accountPassword;// 全参构造器public Account(Integer accountId, String accountName, String accountPassword) {this.accountId = accountId;this.accountName = accountName;this.accountPassword = accountPassword;}// 一个参数的构造器public Account(Integer accountId) {this.accountId = accountId;}// 两个参数的构造器public Account(Integer accountId, String accountName) {this.accountId = accountId;this.accountName = accountName;}// 无参构造器public Account() {}
}
然后我们去 main 方法中测试通过反射获取构造器,代码和注释如下
public class Test01{public static void main(String[] args) {// 需要先定义一个 Account 类的对象Account account = new Account();// 根据对象获取类的字节码文件Class clazz = account.getClass();try {// 获取参数类型为 Integer 的构造器Constructor con = clazz.getConstructor(Integer.class);// 打印输出该构造器System.out.println(con);} catch (NoSuchMethodException e) {e.printStackTrace();}System.out.println("----------------------------------------------");// 构造器本身也是一个对象,这里我们获取多个构造器,用列表进行接收Constructor[] constructors = clazz.getConstructors();// 输出获取到的所有构造器System.out.println(constructors);}
}
运行 main 方法,得到如下结果

在获取到类的字节码文件之后,我们不仅可以向上面那样获取到构造方法,还可以获取到更为详细的信息

在上图中可以看到,IDEA给出了大量的提示,我挑几个来说一下可以干什么
getParameterConunt() 获取参数个数;
getParameterTypes() 获取参数类型;
getParameter() 获取所有参数;
getModifiers() 获取该方法的权限修饰符,如 public,private,但返回的值是整数,如果返回1,则说明为public,若返回2,则为private。
看他们的英文名字就能大概了解了,我们的IDEA自动提示功能就是通过这些功能来做到的!
5. 利用反射获取属性
利用反射我们也可以获取到类中的属性,例如刚才的 Account 类,我们可以获取到它的 账户id,账户名称,账户密码等属性,相应方法如下所示

我们还是需要先获取类的字节码文件,再通过字节码文件的方法获取类中的属性,如下所示

我这里是获取所有的,当然也可以获取单个的,将方法的后缀 s 去掉就可调用获取单个属性的方法,它也和刚才的构造方法一样,可以获取属性的修饰符,还可以获取到属性的变量名,这里就不重复演示了。
6. 通过反射获取成员方法
如下图中所示的即为获取成员方法的方法,我们也是要通过字节码文件对象来获取

我们把刚才的 Account 类添加上 get和set方法
通过字节码文件即可获取 get 和 set 方法

还有几个方法我就不一一展示了,也都不难。
其实反射这一章在开发时并不常用,他们主要是应用与框架,如果以后你自己也开发框架的话,会经常用到反射。
另外,获取Class字节码文件的三种方法是面试时常常问到的一个点,各位需要好好记住。
相关文章:
Java反射全面详解
1. 什么是反射? 首先听这个名字就有些疑惑,什么是反射,它能用来干什么呢? Java官方对反射的解释是 "反射允许对封装类的字段,方法和构造函数进行编程式访问"。这里的字段指的就是成员变量,方法…...
助力工业物联网,工业大数据之费用事实指标分析及实现【二十四】
文章目录 1:费用事实指标分析及实现2:差旅事实指标分析及实现3:网点物料事实指标分析及实现 1:费用事实指标分析及实现 目标:实现DWB层费用报销事实指标表的构建 路径 step1:目标需求step2:数据…...
Istio 安全 mTLS认证 PeerAuthentication
这里定义了访问www.ck8s.com可以使用http也可以使用https访问,两种方式都可以访问。 那么是否可以强制使用mtls方式去访问? mTLS认证 PeerAuthentication PeerAuthentication的主要作用是别人在和网格里的pod进行通信的时候,是否要求mTLS mTL…...
【MySQL】数据库基本使用
文章目录 一、数据库介绍二、数据库使用2.1 登录MySQL2.2 基本使用2.2.1 显示当前 MySQL 实例中所有的数据库列表2.2.2 创建数据库2.2.3 创建数据库表2.2.4 在表中插入数据2.2.5 在表中查询数据 三、服务器、数据库、表之间的关系四、SQL语句分类五、存储引擎 一、数据库介绍 …...
计算shell脚本执行的时间
我们在使用shell脚本进行一些批量活动的时候,在有的场景下会需要知道脚本执行用了多长的时间,一谈到这个话题,我们一般的想法就是记录时间再开始阶段,执行完成后再记录时间,然后求时间差,这样是可以的&…...
无网络环境下,如何部署Docker镜像
无网络环境下,如何部署Docker镜像 什么是Docker镜像 Docker镜像是Docker容器的基础构建块。它是一个轻量级、独立且可执行的软件包,其中包含了运行应用程序所需的所有文件系统、代码、依赖关系和配置。 Docker镜像由一系列只读层(Layers&a…...
瑞吉外卖项目----(2)缓存优化
1 缓存优化 1.0 问题说明 1.1 环境搭建 将项目推送到远程仓库里,教程在git 提交远程仓库前建议取消代码检查 创建新的分支v1.0(用于实现缓存优化)并推送到远程仓库 1.1.1 maven坐标 导入spring-data-redis的maven坐标: &l…...
c++ http url encode decode
在C++中,可以使用以下方法对URL进行编码和解码: URL编码:#include <iostream> #include <string> #include <sstream> #include <iomanip>std::string urlEncode...
@vue/composition-api功能介绍
前言 vue/composition-api 是通过一个插件的方式,为 Vue2(2.7自带,2.6及以下可用) 提供类似 Vue3 composition API 的函数式编程能力。它的实现思路主要有: 1、提供组合式函数,在函数内部追踪响应性依赖。 2、将组合产生的响应式状态保存到…...
WebSocket整合直播
由于浏览器不支持对于rtmp协议推拉流,所以需要后台对传输的数据进行处理,将数据转接,为了实现其实时性,使用websocket将数据传输 先使用obs和vlc测试正常的推拉流是否正常 然后在跑本地后台传输视频 使用JavaCV技术传输音视频 …...
【Linux】IO 篇:文件调用原理,文件描述符,FILE的内涵,解析重定向,理解缓冲区
文章目录 一、系统调用接口二、文件调用1. 文件描述符 fd2. 文件调用原理3. FILE 三、重定向dup2 四、缓冲区简易 FILE 的代码实现 文件被加载之前,被存在磁盘上,操作文件,文件的部分内容则会被调度到 内存中。 要分析文件,我们也…...
力扣:47. 全排列 II(Python3)
题目: 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。 来源:力扣(LeetCode) 链接:力扣 示例: 示例 1: 输入:nums [1,1,2] 输出:[…...
Android uart-修改串口节点名
需求: 应客户软件的需求,需要将Android系统里面的/dev/ttyS3节点名称修改为/dev/ttyS9; 实现: 1、判断 driver->name是否为"ttyS",index是否为3,如果是的话替换为ttyS9; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c old mode 100644 new …...
【HarmonyOS】键盘遮挡输入框时,实现输入框显示在键盘上方
【关键字】 harmonyOS、键盘遮挡input,键盘高度监听 【写在前面】 在使用API6、API7开发HarmonyOS应用时,常出现页面中需要输入input,但是若input位置在页面下方,在input获取焦点的时候,会出现软键盘挡住input情况&a…...
day19-二叉树的最大最小深度
二叉树的最大/最小深度 给定一个二叉树 root ,返回其最大/小深度。 二叉树的 最大/小深度 是指从根节点到最远/近叶子节点的最长路径上的节点数。 思路 求最大深度比较简单,我们先解决最大深度。 最大深度 递归 class Solution { public:int maxD…...
Ansible-roles
Ansible-roles 一、roles作用 把playbook剧本里的各个play看作为角色,将各个角色的tasks任务、vars变量、templates模板、files文件等内容放置到角色的目录中统一管理,需要的时候可在playbook中直接使用roles调用,所以roles可以实现playboo…...
NullPointerException导致手机重启案例分析
和你一起终身学习,这里是程序员Android 经典好文推荐,通过阅读本文,您将收获以下知识点: 一、 Framework 层对象 空指针导致手机重启。二、解决方案,规避空指针三、Telecom APK 控制导致的重启举例 一、 Framework 层对象 空指针导…...
JAVA 反编译工具
Releases deathmarine/Luyten GitHub 安装exe 打开拖入文件即可...
(AcWing)分组背包问题
有 N 组物品和一个容量是 V 的背包。 每组物品有若干个,同一组内的物品最多只能选一个。 每件物品的体积是 vij,价值是 wij,其中 i 是组号,j 是组内编号。 求解将哪些物品装入背包,可使物品总体积不超过背包容量&…...
JSP项目国际化词条统计
国际化字条匹配并导出为excel格式 需求 将jsp页面里的key值,就是<spring:message code"gsyezer_Single_crystal"/>里的gsyezer_Single_crystal。和对应的字条对应上,并以excel表格形式输出。 jsp页面key值示例 <label for"&…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...
