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

关于Java 反射的简单易懂的介绍

目录

#0.总览

#1. 类的反射

①介绍

②获取

③作用

获取构造函数:

创建实例:

字段操作:      

方法操作:

获取修饰符:

#2.总结 


#0.总览

反射,官方是这样介绍它的:

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program.

翻译过来就是:反射是 Java 编程语言中的一项功能。它允许正在执行的 Java 程序检查或“内省”自身,并作程序的内部属性。

再翻译成人话就是:反射可以让程序可以把本身的各种方法,参数当作变量来使用。 

为什么翻译成“反射”?因为这个过程就像是照镜子:程序通过照镜子知道自己有什么方法和参数。

详细的说,有:

  • 获取类的信息(类名、方法、字段、构造方法等)。
  • 创建类的实例。
  • 调用类的方法、修改字段的值。
  • 动态地加载类和进行方法调用。
  • 与代理息息相关

#1. 类的反射

①介绍

        首先得介绍一下Class类

Class类是反射的核心部分

Class类和真实的类对象不是一个东西!Class类只是包含了对应类关于其涉及反射的一系列操作的类。每个类都会有属于自己的Class对象:

列如 String.class             Integer.class等

尝试输出:

System.out.println(String.class);

会得到 class java.lang.String

这是类的全限定类名,可以看成是类的标识。

②获取

通过一些方法,我们能获得一个类的Class对象:

Class ex1 = Class.forName("java.lang.String");

Class ex2 = String.class;

String string = new String();
Class ex3 = string.getClass();

那获取到Class类有什么用呢? 

③作用

获取构造函数:

拿这个类来举例:

public class Temp {public int a;public int b;private int c = 10;public Temp() {}public Temp(int a) {this.a = a;}private Temp(int a, int b) {this.a = a;this.b = b;}public void sing(){System.out.println("ahhhhhh!");}private void dance(){System.out.println("haaaaaa!");}
}
Class ex = Temp.class;

ex.getConstructor();    ex.getConstructor(int.class);         

这会获得其一个指定的公共构造方法,注意!括号中的参数要这样写上对应的Class类才能获取到!

ex.getDeclaredConstructor();则可以获取到所有构造方法

相对的,Constructor<?>[] constructors = ex.getConstructors();则会获取所有公用构造方法

getDeclaredConstructors同理

       


创建实例:

Constructor constructor = ex.getConstructor(int.class);
Temp obj = (Temp) constructor.newInstance( 30);

这样就根据指定的构造方法创建出了一个指定的实例

       


字段操作: 

Temp obj = (Temp) constructor.newInstance( 30);
Field field = ex.getField("a");
System.out.println(field);
int value = field.getInt(obj); 
System.out.println(value);

这里会输出 30

注意!除了getInt还有getchar等对应基本数据类型,其他的统一为get()

但其实get()也能处理基本数据类型

格式为 Field.get(已实例化的对象)

对于私有变量,无独有偶:getDeclaredField(“c”)即可

但是只能System.out.println(field);,即获取全限定字段名,无法获得具体值!

解决方法在下:

但是对于字段修改: 

如果是公共字段:

field.set(obj, 666); 

就可以完成修改

私有字段是无法修改的!

必须先取消限制:

field.setAccessible(true);

这样才可以让私有字段像公共字段一样可以被查看,修改。


         

方法操作:

对于方法,有了前面的铺垫则简单得多:

对于公共方法:

Class ex = Temp.class;
Constructor constructor = ex.getConstructor();
Temp obj = (Temp) constructor.newInstance();

Method greetMethod = ex.getMethod("sing");
greetMethod.invoke(obj); 

这样就成功执行了sing方法

如果想要获取所有方法

Method[] methods = ex.getMethods();即可

但是必须要有一个已经实例化的对象obj才能正常的通过invoke操作来执行方法!

实际上,执行的方法实际上是已经实例化的obj里面对应的方法!

对于一些函数,可能名字相同但是参数不同,可以仿照构造函数那样加以区分:

Method greetMethod = ex.getMethod("sing",int.class);

Method greetMethod = ex.getMethod("sing",String.class);类似这样来区分

对于私有方法: 

和字段一模一样

在方法名上加上Declared

getDeclaredMethod,getDeclaredMethods

然后得加上greetMethod.setAccessible(true);才能正常操作


获取修饰符:

可以通过类似于:

int x = greetMethod.getModifiers();

来获取任何方法/字段的修饰符,也许你会疑惑为什么是int类型,原因是JAVA中的确是用数字来存储修饰符的,比如说:

public = 1, private = 2protected = 3,default= 4


 获取接口:

获取接口相对来说非常简单:

Class<?>[] interfaces = ex.getInterfaces();

这样便可获取所有ex类所实现的接口


获取注释:

Annotation[] annotations = ex.getAnnotations();

这样就获取了ex类所有的注释内容!

如果想获取方法的注释也非常简单:

Annotation[] annotations = ex.getMethod("xxx").getAnnotations();

(提一句,对于每个注释都是一个单独的类型,假如你需要@CY注释,改成
CY annotation = ex.getMethod("xxx").getAnnotation();也行)

接下来想要提取注释变量什么的就随你了

这种方法可以用来实现公共字段补全


#2.总结 

        归功于反射机制,程序得以对本身进行修改而不依赖于人工修改,也提供了更多的灵活性,

更是为实现动态代理提供了可能。

(我也写了一篇介绍代理的文章,欢迎捧场!)

你也许会发现,这种获取参数,接口,方法是不是很熟悉?是不是我们用的IDE就有点用了这种方式的意思?不然为什么我们写了一个函数就能提示要放什么参数进去?

这的确很像,但实际上IDE是会实时构造一个抽象语法树(AST),它是代码结构的表示。这使得 IDE 能够理解类、方法、字段和参数的存在及其类型。

尽管如此,反射非常重要,java,spring框架里面反射无处不在,

但是,反射的性能开销很大,因为它要在运行中实时解析类,方法,字段,这些原本是在编译时完成的,而且反射无法被编译器进行优化!

所以谨慎使用!

相关文章:

关于Java 反射的简单易懂的介绍

目录 #0.总览 #1. 类的反射 ①介绍 ②获取 ③作用 获取构造函数&#xff1a; 创建实例&#xff1a; 字段操作&#xff1a; 方法操作&#xff1a; 获取修饰符&#xff1a; #2.总结 #0.总览 反射&#xff0c;官方是这样介绍它的&#xff1a; Reflection is a …...

市场趋势中突破确认的多维度判断方法

波动率突破策略是众多交易者广泛采用的重要交易策略之一。而在这一策略中&#xff0c;准确判断突破是否有效&#xff0c;是决定交易成败的关键环节。仅仅依据单一因素来确认突破&#xff0c;往往会使交易者陷入误判的困境&#xff0c;导致不必要的损失。因此&#xff0c;采用多…...

网络空间安全(2)应用程序安全

前言 应用程序安全&#xff08;Application Security&#xff0c;简称AppSec&#xff09;是一个综合性的概念&#xff0c;它涵盖了应用程序从开发到部署&#xff0c;再到后续维护的整个过程中的安全措施。 一、定义与重要性 定义&#xff1a;应用程序安全是指识别和修复应用程序…...

【MyBatis】CRUD、配置解析、ResultMap、分页实现

目录标题 1、Mybatis简介1.1、什么是MyBatis1.2、持久化1.3、持久层1.4、为什么需要MybatisMyBatis的优点 2.1、代码演示搭建实验数据库导入MyBatis相关 jar 包 03、CRUD操作3.1、namespace3.2、select3.3、insert3.4、update3.5、delete 04、MyBatis配置解析4、配置解析4.3、m…...

Linux系统编程之高级信号处理

概述 在前一篇文章中&#xff0c;我们介绍了signal函数、sigaction函数等基本的信号处理方法。在本篇中&#xff0c;我们将介绍信号处理的一些高级用法&#xff0c;包括&#xff1a;阻塞与解除阻塞、定时器等。 阻塞与解除阻塞 有时候&#xff0c;我们不希望某个信号立即被处理…...

深度学习驱动的车牌识别:技术演进与未来挑战

一、引言 1.1 研究背景 在当今社会&#xff0c;智能交通系统的发展日益重要&#xff0c;而车牌识别作为其关键组成部分&#xff0c;发挥着至关重要的作用。车牌识别技术广泛应用于交通管理、停车场管理、安防监控等领域。在交通管理中&#xff0c;它可以用于车辆识别、交通违…...

钉钉快捷免登录 通过浏览器打开第三方系统,

一、钉钉内跳转至浏览器的实现 使用钉钉JSAPI的跳转接口 在钉钉内通过dd.biz.navigation.openLink方法强制在系统浏览器中打开链接。此方法需在钉钉开发者后台配置应用权限&#xff0c;确保应用具备调用该API的资格37。 示例代码&#xff1a; dd.ready(() > {dd.biz.navigat…...

力扣——杨辉三角

题目链接&#xff1a; 链接 题目描述&#xff1a; 思路&#xff1a; 直接找规律&#xff0c;按照数学的思路来 每一行的列最大索引 < 行索引 实现代码&#xff1a; class Solution {public List<List<Integer>> generate(int numRows) {List<List<In…...

stm32108键C-B全调性_动态可视化乐谱钢琴

108键全调性钢琴 一 基本介绍1 项目简介2 实现方式3 项目构成 二 实现过程0 前置基本外设驱动1 声音控制2 乐谱录入&基础乐理3 点阵屏谱点动态刷新4 项目交互控制5 录入新曲子过程 三 展示&#xff0c;与链接视频地址1 主要功能函数一览2 下载链接3 视频效果 一 基本介绍 …...

mysql之规则优化器RBO

文章目录 MySQL 基于规则的优化 (RBO)&#xff1a;RBO 的核心思想&#xff1a;模式匹配与规则应用RBO 的主要优化规则查询重写 (Query Rewrite) / 查询转换 (Query Transformation)子查询优化 (Subquery Optimization) - RBO 的重中之重非相关子查询 (Non-Correlated Subquery)…...

MySQL数据库——表的约束

1.空属性&#xff08;null/not null&#xff09; 两个值&#xff1a;null&#xff08;默认的&#xff09;和not null&#xff08;不为空&#xff09; 数据库默认字段基本都是字段为空&#xff0c;但是实际开发时&#xff0c;尽可能保证字段不为空&#xff0c;因为数据为空没办法…...

vue2.x 中子组件向父组件传递数据主要通过 $emit 方法触发自定义事件方式实现

在 Vue 2.x 中&#xff0c;子组件向父组件传递数据主要通过 自定义事件 的方式实现。具体步骤如下&#xff1a; 1. 子组件通过 $emit 触发事件 子组件可以使用 $emit 方法触发一个自定义事件&#xff0c;并将数据作为参数传递给父组件。 语法&#xff1a; this.$emit(事件名…...

洛谷 P1102 A-B 数对(详解)c++

题目链接&#xff1a;P1102 A-B 数对 - 洛谷 1.题目分析 2.算法原理 解法一&#xff1a;暴力 - 两层for循环 因为这道题需要你在数组中找出来两个数&#xff0c;让这两个数的差等于定值C就可以了&#xff0c;一层for循环枚举A第二层for循环枚举B&#xff0c;求一下看是否等于…...

python用 PythonNet 从 Python 调用 WPF 类库 UI 用XAML

pythonnet 是pythonhe.net通用的神器不多介绍了. 这次这基本上跟python没有关系了. 和winform一样先导包 import clr clr.AddReference("PresentationFramework.Classic, Version3.0.0.0, Cultureneutral, PublicKeyToken31bf3856ad364e35") clr.AddReference(&…...

C++——list模拟实现

目录 前言 一、list的结构 二、默认成员函数 构造函数 析构函数 clear 拷贝构造 赋值重载 swap 三、容量相关 empty size 四、数据访问 front/back 五、普通迭代器 begin/end 六、const迭代器 begin/end 七、插入数据 insert push_back push_front 八、…...

YOLOv11-ultralytics-8.3.67部分代码阅读笔记-utils.py

utils.py ultralytics\data\utils.py 目录 utils.py 1.所需的库和模块 2.def img2label_paths(img_paths): 3.def get_hash(paths): 4.def exif_size(img: Image.Image): 5.def verify_image(args): 6.def verify_image_label(args): 7.def visualize_image_ann…...

Linux 内核 RDMA CM 模块分析:drivers/infiniband/core/cma.c

一、引言 随着高性能计算和大数据处理需求的不断增长,远程直接内存访问(RDMA)技术在数据中心和高性能计算领域得到了广泛应用。RDMA 允许数据直接在不同系统的内存之间传输,而无需经过 CPU 和操作系统的干预,从而显著提高了数据传输效率和系统性能。Linux 内核中的 RDMA …...

Flask flash() 消息示例

目录 安装 Flask 入门:Flask flash() 基本示例 进阶:使用 Flask-WTF Flash 登录结果消息 详解:get_flashed_messages() 详解:flash() 消息的完整生命周期 Flask 提供 flash() 用于向 用户传递临时消息,通常用于: • 表单提交成功或失败 • 用户登录、注册、退出提…...

ImGui 学习笔记(三)—— 隐藏主窗口窗口关闭检测

ImGui 的主窗口是平台窗口&#xff0c;默认是可见的&#xff0c;这会影响视觉效果。那么怎么隐藏 ImGui 的主窗口呢&#xff1f; 这很简单&#xff0c;但是需要针对后端做一些修改。 本文仅介绍在 glfwopengl3 和 win32dx11 两种实现上如何修改。 在 win32dx11 实现上&#…...

ubuntu磁盘清理垃圾文件

大头文件排查 #先查看是否是内存满了&#xff0c;USER 很高即是满了 du -f#抓大头思想&#xff0c;优先删除大文件#查看文件目录 内存占用量并排序&#xff0c;不断文件递归下去 du --max-depth1 -h /home/ -h | sort du --max-depth1 -h /home/big/ -h | sort 缓存文件清理…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...

前端调试HTTP状态码

1xx&#xff08;信息类状态码&#xff09; 这类状态码表示临时响应&#xff0c;需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分&#xff0c;客户端应继续发送剩余部分。 2xx&#xff08;成功类状态码&#xff09; 表示请求已成功被服务器接收、理解并处…...

goreplay

1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具&#xff0c;可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长&#xff0c;测试它所需的工作量也会呈指数级增长。GoRepl…...