2023.12.12 关于 Java 反射详解
目录
基本概念
定义
用途
反射相关的类
反射基本原理
Class 类中的相关方法
常用获得类相关的方法
常用获得类中属性相关的方法
常用获得类中构造器相关的方法
常用获得类中方法相关的方法
实例理解
反射优缺点
基本概念
定义
- Java 的反射(reflection)机制是一种强大功能,它可以让我们在运行时动态地获取和操作 类 或 对象 的信息
实例理解
- 我们可以通过反射机制来创建一个类的对象,而不需要使用 new 关键字
- 我们也可以通过反射机制来访问或修改一个对象的私有属性或方法,而不需要遵循封装原则
- 我们还可以通过反射机制来调用一个对象的任意方法,而不需要知道它的参数类型或返回值类型
用途
典型用途一:
- 在开发第三方应用时,我们可能会遇到一些类的成员变量、方法或属性是私有的,或者只对系统应用开放,这就意味着我们不能直接访问这些成员或方法
- 这时我们便可以在运行时 通过 Java 的反射机制 来动态地访问和操作类的内部成员,包括私有成员和方法
典型用途二:
- 反射在开发通用框架 Spring 中起着重要的作用
- 在Spring 框架中,所有类(Bean)都由 Spring 容器进行管理,这些 Bean 可以通过 XML 配置或注解来配置
- 当我们从容器中获取Bean 以进行依赖注入时,容器会读取配置信息,这些配置信息包含了类的信息,比如类的名称、属性、方法等
- Spring根据这些信息 动态地创建这些类的实例,这个过程就是所谓的 依赖注入,该过程中,反射起到了关键作用
- Spring 使用反射来动态地创建类的实例,调用方法,以及设置属性值
反射相关的类
反射基本原理
- Java 的反射机制是基于 java.lang.Class 类实现的
- 当我们编译一个 Java 文件时,会生成一个 .class 文件
- 当 JVM 加载这个 .class 文件时,会将其解析为一个 java.lang.Class 类的对象
- 在程序运行时,每个 Java 文件都会被 JVM 解析为一个 Class 类的实例
- 这个 Class 类的实例包含了该 Java 文件中所定义类的所有信息,包括类的名称、属性、方法等
- 我们可以通过 Java 的反射机制来操作这个 Class 类的实例
- 具体来说,我们可以使用反射来获取类的属性和方法,甚至可以添加或修改类的属性和方法
- 这使得我们可以在运行时动态地操作类,使其成为一个 动态的类
类名 用途 Class 类 代表类的实体,在运行的 Java 应用程序中表示类和接口 Field 类 代表类的成员变量、类的属性 Method 类 代表类的方法 Constructor 类 代表类的构造方法
Class 类中的相关方法
常用获得类相关的方法
方法 用途 getClassLoader() 获得类的加载器 getDeclaredClasses() 返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有的) forName(String className) 根据类名返回类的对象 newInstance() 创建类的实例 getName() 获得类的完整路径名字 常用获得类中属性相关的方法
方法 用途 getField(String name) 获得某个公有的属性对象 getFields() 获得所有公有的属性对象 getDeclaredField(String name) 获得某个属性对象 getDeclaredFields() 获得所有属性对象 常用获得类中构造器相关的方法
方法 用途 getConstructor(Class <?> parameterTypes) 获得该类中与参数类型匹配的公有构造方法 getConstructors() 获得该类的所有公有构造方法 getDeclaredConstructor(Class <?> parameterTypes) 获得该类中与参数类型匹配的构造方法 getDeclaredConstructors() 获得该类所有构造方法 常用获得类中方法相关的方法
方法 用途 getMethod(String name, Class <?> parameterTypes) 获得该类某个公有的方法 getMethods() 获得该类所有公有的方法 getDeclaredMethod(String name, Class <?> parameterTypes) 获得该类某个方法 getDeclaredMethods() 获得该类所有方法
实例理解
- 此处我们先创建一个 Student 类
class Student{//私有属性nameprivate String name = "master";//公有属性agepublic int age = 18;//不带参数的构造方法public Student(){System.out.println("Student()");}private Student(String name,int age) {this.name = name;this.age = age;System.out.println("Student(String,name)");}private void eat(){System.out.println("make hamburger!");}public void sleep(){System.out.println("go to bed!");}private void function(String str) {System.out.println(str);}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';} }
- 此处介绍三种方式来获取 Student 的 Class 对象
public class Demo1 {public static void main(String[] args) { // 有三种方式可以获取 Class 对象Student student1 = new Student(); // 1、通过对象的 getClass() 方法Class<?> c1 = student1.getClass(); // 2、通过类名 .class 获取Class<?> c2 = Student.class; // 3、通过调用 Class.forName() 方法获取了 Student 类的 Class 对象 // Class.forName() 方法需要一个类的全限定名(包括 包名和类名) 作为参数 // 此处的 ? 是一个通配符,用于表示未知类型 // 当我们声明一个泛型变量时,如果我们不确定或不关心实际的类型参数,我们可以使用 ? 来表示Class<?> c3 = null;try {c3 = Class.forName("Student");} catch (ClassNotFoundException e) {throw new RuntimeException(e);} // 此处证明通过上述三种方式所获取的 Class 对象 都是同一个System.out.println((c1.equals(c2) && c1.equals(c3) && c2.equals(c3)) ? "true" : "false");} }
- 此处我们通过反射机制创建一个对象
import java.lang.reflect.InvocationTargetException;public class ReflectClassDemo {// 通过反射创建一个对象public static void reflectNewInstance() throws InstantiationException, IllegalAccessException, ClassNotFoundException {Class<?> c3 = Class.forName("Student"); // 通过调用 Class 类的 newInstance() 方法来创建一个 c3 对应类的新实例 // newInstance() 方法调用的是这个类的无参构造函数 // 如果这个类没有无参构造函数,或者无参构造函数是私有的,那么 newInstance 会抛出一个异常 // 因为 newInstance() 方法返回的类型为 Object 类 所以需要类型转换,此处转换为 Student 类Student student = (Student) c3.newInstance();System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectNewInstance();} }运行结果:
- 此处我们通过反射机制获取私有的构造方法
import java.lang.reflect.Constructor;public class ReflectClassDemo {// 通过反射获取私有的构造方法public static void reflectPrivateConstructor() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class<?> c3 = Class.forName("Student");Constructor<?> constructor = c3.getDeclaredConstructor(String.class,int.class); // 注意只要是涉及到 private 都要使用 setAccessible(true) 来打开权限,此处的构造方法为私有的constructor.setAccessible(true); // 此处利用构造方法 修改年龄和性别Student student = (Student)constructor.newInstance("xiaolin",20);System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateConstructor();} }运行结果:
- 此处我们通过反射机制获取私有属性
import java.lang.reflect.Field;public class ReflectClassDemo {// 通过反射获取私有属性public static void reflectPrivateField() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {Class<?> c3 = Class.forName("Student");Field field = c3.getDeclaredField("name"); // 注意只要是涉及到 private 都要使用 setAccessible(true) 来打开权限,此处的 name 属性是私有的field.setAccessible(true);Student student = (Student) c3.newInstance(); // 此处修改私有属性field.set(student,"haoran");System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateField();} }运行结果:
- 此处我们通过反射机制获取私有方法
import java.lang.reflect.Method;public class ReflectClassDemo {// 通过反射获取私有方法public static void reflectPrivateMethod() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {Class<?> c3 = Class.forName("Student");Method method1 = c3.getDeclaredMethod("function", String.class);Method method2 = c3.getDeclaredMethod("sleep"); // 注意只要是涉及到 private 都要使用 setAccessible(true) 来打开权限,此处的 function 方法是私有的method1.setAccessible(true);Student student = (Student) c3.newInstance(); // 此处给 function 方法传参method1.invoke(student,"此处利用反射机制给 function 方法传个字符串参数"); // 此处调用 sleep 方法,该方法为 public 无需额外打开权限,直接调用即可method2.invoke(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateMethod();} }运行结果:
反射优缺点
优点
- 对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个类都能调用它的任意一个方法
- 增加程序的灵活性和扩展性,降低耦合性,提高自适应性
- 反射已经运用在很多流行框架,典型代表为 Spring
缺点
- 使用反射会有效率问题,会导致程序效率降低
- 反射技术绕过了源代码的技术,因而会带来维护问题
- 反射代码比相应的直接代码更复杂
总结:
- 虽然反射非常强大,但也需要谨慎使用
- 我们需要在反射带来的灵活性和可扩展性与其带来的性能开销、维护问题和代码复杂性之间找到一个平衡
- 某些情况下,比如开发通用的框架,使用反射式非常有价值的
- 但在其他情况下,我们可能更倾向于使用更简单、更直接的代码
相关文章:
2023.12.12 关于 Java 反射详解
目录 基本概念 定义 用途 反射相关的类 反射基本原理 Class 类中的相关方法 常用获得类相关的方法 常用获得类中属性相关的方法 常用获得类中构造器相关的方法 常用获得类中方法相关的方法 实例理解 反射优缺点 基本概念 定义 Java 的反射(reflection&a…...
【Qt QML入门】Image
Image类型显示一个图像。 使用source属性将图像的源指定为URL。图像可以以Qt支持的任何标准图像格式提供,包括位图格式,如PNG和JPEG,以及矢量图形格式,如SVG。 如果没有指定宽度和高度属性,图像将自动使用加载图像的大…...
Spark编程入门
1.8 Spark编程入门 1.8.1 通过IDEA创建Spark工程 ps:工程创建之前步骤省略,在scala中已经讲解,直接默认是创建好工程的 导入Pom文件依赖 <!-- 声明公有的属性 --><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler…...
JVM 内存分析工具 Memory Analyzer Tool(MAT)的深度讲解
目录 一. 前言 二. MAT 使用场景及主要解决问题 三. MAT 基础概念 3.1. Heap Dump 3.2. Shallow Heap 3.3. Retained Set 3.4. Retained Heap 3.5. Dominator Tree 3.6. OQL 3.7. references 四. MAT 功能概述 4.1. 内存分布 4.2. 对象间依赖 4.3. 对象状态 4.4…...
浅谈 USB Bulk 深入浅出 (3) - USB Bulk 装置传输的注意事项
来源:大大通 作者:冷氣團 1 USB Bulk 是什么 USB 是即插即用使用差动信号的装置界面,是以 端点 ( Endpoint ),做为传输装置的输出入端,透过不同的端点 ( Endpoint ) 和模式,来进行与装置的沟通ÿ…...
c语言结构体调用格式与对齐
1.声明形式: struct 结构体名字 { 结构体成员 }结构体变量名; 2.赋值方法 3.结构体对齐: 1.起始偏移量:默认结构体第一个元素对齐0起始偏移量,第一个元素占一个字节,此时偏移量为1. 2.标准数ÿ…...
服务器常用命令介绍和负载监控的工具插件推荐
先赞后看,养成习惯!!!❤️ ❤️ ❤️ 码字不易,如果喜欢可以关注我哦! 如果本篇文章对你有所启发,欢迎访问我的个人博客 命令 服务器相关 5个常用命令 top Top命令不仅显示了当前内核服务的…...
linux 防火墙systemctl (个人笔记)
查看 systemctl status firewalld 开启 systemctl start firewalld 关闭 systemctl stop firewalld.service 查看所有 firewall-cmd --zonepublic --list-ports 开放端口:// --permanent 永久生效,没有此参数重启后失效 firewall-cmd --zonepublic --add-port9527/…...
处理器中store指令的处理
对于向存储器中保存数据的store指令来说,它在顺利离开流水线之前是不允许改变处理器状态的,只有等到它退休(retire)的时候,才允许将它携带的数据写到D-Cache中在此之前,store指令即使计算完毕,也会将结果暂存在一个缓存中…...
杨辉三角形-第11届蓝桥杯选拔赛Python真题精选
[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第17讲。 杨辉三角形&#…...
我们一起做过的SPA——Nuxt.js介绍
Nuxt.js 1 我们一起做过的SPA SPA(single page web application)单页 Web 应用,Web 不再是一张张页面,而是一个整体的应用,一个由路由系统、数据系统、页面(组件)系统等等,组成的应…...
java导出word使用模版与自定义联合出击解决复杂表格!
1. 看一下需要导出什么样子的表格 如图所示,这里的所有数据行都是动态的,需要根据查询出来的数据循环展示。 如果只是这样的话,使用freemarker应该都可以搞定,但是他一列中内容相同的单元格,需要合并。 这对于表格样式…...
GO设计模式——9、过滤器模式(结构型)
目录 过滤器模式(Filter/Criteria Pattern) 代码实现 过滤器模式(Filter/Criteria Pattern) 过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,…...
fastadmin 导出
php 接收数据 set_time_limit(0);ini_set(memory_limit, -1);$ids $this->request->post(ids);$filter $this->request->post(filter);$op $this->request->post(op);$search $this->request->post(search);$whereIds $ids all ? 11 : [id >…...
六、CM4树莓派USBRS转485串口通讯
一、串行通讯接口 串行通讯接口简称串口(UART) 采用串行通信方式的扩展接口,数据位一位一位的按照顺序传送 优点:通信线路简单,只要一对传输线就可以实现双向通信能够大大降低成本,适合远距离通信。 缺点…...
c++知识总结
一 细碎知识 1.27 # 1.27.1 # pragma once 参考 C++学习笔记之pragma once的理解_pragma once什么意思-CSDN博客https://blog.csdn.net/lynnlee_36/article/details/105322937作用 保证只被编译一次,和#ifndef,#define,#endif功能相同 1.27.2 #if defined(__cplusplus…...
python-爬取壁纸
代理池的,防止IP 被封 找到图片真实地址 现在看到的只是图片的预览地址 (previews) 1.检查: 2.鼠标变为箭头时查看网页源代码 关于怎样在源代码中找到图片的真实地址 ??? 为什么在源代码界面 ctrl f 时候搜索的是 .png ??? 首先图片地址是以 .j…...
第31期 | GPTSecurity周报
GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区,集成了生成预训练Transformer(GPT)、人工智能生成内容(AIGC)以及大型语言模型(LLM)等安全领域应用的知识。在这里,您可以…...
湖仓一体架构理论与实践汇总
湖仓一体架构理论与实践汇总 软件研发本质上属于“手工业”。软件研发在很大程度上还是依赖于个人的能力。当软件规模较小时,依赖“手工业”可以解决问题,但是当软件规模大了之后再依赖“手工业”就不行了。 软件的复杂度包含两个层面:软件…...
Redission从入门到入门
1. Redisson简介 Redisson 是一个在 Java 环境中使用的 Redis 客户端库。它提供了丰富的功能,使得在 Java 应用中与 Redis 交互变得更加简单和高效。Redisson 不仅提供了基本的 Redis 操作,还提供了许多高级功能,使其成为在 Java 项目中实现…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...



