反射讲解(有图有真相)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、反射是什么?
  • 二、反射有啥好处?
      • 1. 没反射
      • 2. 有反射
  • 三、反射的常用方法
      • 1. 获取 Class 对象:
      • 2. 获取类的构造方法:
      • 3. 获取类的字段信息:
      • 4. 获取类的方法信息:
      • 5. 创建对象和调用方法:
  • 四、总结


前言

提示:小车车🚗准备出发。。。。。

今天咋们来搂一搂反射是啥?有啥用?各位请上车,系好安全带。。。。


提示:路途颠簸系好安全带!!!!

一、反射是什么?

当我们写Java程序时,通常情况下,我们会在编译时确定所有的类、方法和属性。但是有些时候,我们希望在程序运行时动态地获取和操作类的信息,这就是反射。

反射是指在运行时动态地获取类的信息并操作类的成员。

在Java中,每个类都有一个对应的Class对象,这个对象包含了类的信息,如类的名称、属性、方法等。反射机制允许我们在运行时获取这个Class对象,进而获取和操作类的信息。

⚠️这里给大家提个小问题:为什么Java只能在程序运行阶段才能动态获取类的信息并操作类的成员呢?

原因如下:

  1. 类加载: 在 Java 程序运行时,JVM 负责加载类的字节码文件。这个过程称为类加载。类加载器将字节码加载到内存中,并创建对应的 Class 对象,该对象包含了类的信息。
  2. 实例化对象: 通过 Class 对象,可以实例化类的对象。反射允许在运行时创建类的对象,而不需要在编译时知道类的确切类型。
  3. 动态获取信息: 通过 Class 对象,可以获取类的各种信息,包括类的名称、构造方法、字段、方法等。这使得程序在运行时能够根据需要动态地获取和操作类的信息。

总而言之,当一个类(.class文件)被classloader加载到内存后,它会将.class文件里面的内容加载到Metaspace中,并且会生成一个类对象。这个类对象存储在Metaspace中,它充当了访问类的结构和内容的入口,包括静态字段、方法等。
在这里插入图片描述
有兴趣的同学可以去学学JVM的相关知识。

二、反射有啥好处?

对于干干净净的小白同学,先绕道去第三部分了解一下反射的常用方法再来品味好吃的🌰,会更有感觉哦。
反射的好处咱们就举个有反射和没反射的例子对比说明一下子。
首先,定义一个支付接口 Mtwm

// Mtwm.java
public interface Mtwm {void payOnline();
}

然后,实现两个支付方式类,分别是 WeChatAliPay

// WeChat.java
public class WeChat implements Mtwm {@Overridepublic void payOnline() {System.out.println("我已经点了外卖,正在使用微信支付");}
}public class AliPay implements Mtwm {@Overridepublic void payOnline() {System.out.println("我已经点了外卖,正在使用支付宝支付");}
}

1. 没反射

接下来,创建一个测试类 Test,用于模拟前台选择支付方式:

// Test.java
public class Test {public static void main(String[] args) {String str = "微信";  // 模拟前台支付方式选择if ("微信".equals(str)) {pay(new WeChat());}if ("支付宝".equals(str)) {pay(new AliPay());}}public static void pay(Mtwm paymentMethod) {paymentMethod.payOnline();}
}

以上是使用多态的方式,已经不错了哦。但在实际应用中,若是我又增加了一个 “银行卡支付” 诸君又该如何应对 ? 我举手🙋,我回答。
无非就两步嘛:

1、创建一个新类,implement Mtwm,重写payOnline方法
2、在多加一个if的判断分支。

但是当我们引入反射机制,会发生什么神奇的事情呢?

2. 有反射

// Demo.java
import java.lang.reflect.Method;public class Demo {public static void main(String[] args) throws Exception {// 模拟前台支付方式选择String str = "com.zhaoss.test01.AliPay";  // 实际上是支付类的全限定路径// 利用反射Class<?> cls = Class.forName(str);Object instance = cls.newInstance();// 获取 payOnline 方法并调用Method method = cls.getMethod("payOnline");method.invoke(instance);}
}

各位有没有发现,通过使用反射,可以在不修改测试类的情况下引入新的支付方式。这样我们就只要创建一个新类(implement Mtwm,重写payOnline方法),然后提供新支付方式的实现类并传入其全路径名,而无需修改测试类。是不是很哇塞!!!

三、反射的常用方法

哥哥们,原谅我懒。我把输出写到注释里了,不好看的话可以直接搞到本地跑一下子。

1. 获取 Class 对象:

通过对象的 getClass() 方法或者类名的 .class 字面量可以获取类的 Class 对象。

public class Example {public static void main(String[] args) {// 通过对象的getClass()方法获取Class对象String str = "Hello, Reflect!";Class<?> classObj1 = str.getClass();System.out.println(classObj1.getName());  // 输出:java.lang.String// 通过类名的.class字面量获取Class对象Class<?> classObj2 = String.class;System.out.println(classObj2.getName());  // 输出:java.lang.String}
}

2. 获取类的构造方法:

通过 getConstructors() 方法获取类的所有公共构造方法,通过 getDeclaredConstructors() 获取所有构造方法(包括私有的)。

import java.lang.reflect.Constructor;public class Example {public Example(String message) {System.out.println("Constructor with message: " + message);}public static void main(String[] args) throws Exception {Class<?> clazz = Example.class;// 获取所有公共构造方法Constructor<?>[] constructors = clazz.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println("Public Constructor: " + constructor);//输出:Public Constructor: public SystemStudy.Example(java.lang.String)}// 获取所有构造方法(包括私有的)Constructor<?>[] allConstructors = clazz.getDeclaredConstructors();for (Constructor<?> constructor : allConstructors) {System.out.println("All Constructor: " + constructor);//输出://All Constructor: public SystemStudy.Example(java.lang.String)//All Constructor: private SystemStudy.Example(java.lang.String,java.lang.Integer)}}
}

3. 获取类的字段信息:

通过 getFields() 方法获取类的所有公共字段,通过 getDeclaredFields() 获取所有字段(包括私有的)。

import java.lang.reflect.Field;public class Example {public int publicField;private String privateField;public static void main(String[] args) {Class<?> clazz = Example.class;// 获取所有公共字段Field[] fields = clazz.getFields();for (Field field : fields) {//输出:Public Field: public int SystemStudy.Example.publicFieldSystem.out.println("Public Field: " + field);}// 获取所有字段(包括私有的)Field[] allFields = clazz.getDeclaredFields();for (Field field : allFields) {//输出://All Field: public int SystemStudy.Example.publicField//All Field: private java.lang.String SystemStudy.Example.privateFieldSystem.out.println("All Field: " + field);}}
}

4. 获取类的方法信息:

通过 getMethods() 方法获取类的所有公共方法,通过 getDeclaredMethods() 获取所有方法(包括私有的)。
这里还有好多的Object包含的方法(wait、equals、hashCode等),太多了,我就写了两个关键的。

import java.lang.reflect.Field;
import java.lang.reflect.Method;public class Example {public void publicMethod() {System.out.println("Public Method");}private void privateMethod() {System.out.println("Private Method");}public static void main(String[] args) {Class<?> clazz = Example.class;// 获取所有公共方法Method[] methods = clazz.getMethods();for (Method method : methods) {//输出:Public Method: public void SystemStudy.Example.publicMethod()System.out.println("Public Method: " + method);}// 获取所有方法(包括私有的)Method[] allMethods = clazz.getDeclaredMethods();for (Method method : allMethods) {//输出//All Method: public void SystemStudy.Example.publicMethod()//All Method: private void SystemStudy.Example.privateMethod()System.out.println("All Method: " + method);}}
}

5. 创建对象和调用方法:

通过 newInstance() 方法创建类的实例,并通过 invoke() 方法调用类的方法。

import java.lang.reflect.Method;public class Example {public void sayHello(String name) {System.out.println("Hello, " + name + "!");}public static void main(String[] args) throws Exception {Class<?> clazz = Example.class;// 创建类的实例Object obj = clazz.newInstance();// 获取方法并调用Method method = clazz.getMethod("sayHello", String.class);method.invoke(obj, "Reflect");  // 输出:Hello, Reflect!}
}

这些是反射中常用的方法,通过这些方法,可以在运行时获取并操作类的信息,使得代码更加灵活和动态。还有很多方法啊,我就不挨个列举了。

四、总结

好啦,以上就是本次对于反射的讲解。安全到站,下车!!!对于我的驾驶技术苟同的兄弟姐妹们,点点赞👍。祝各位身体健康、吃嘛嘛香!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/584220.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数组的声明

概要&#xff1a; 数组的声明分为三个部分 第一部分&#xff1a;数组中元素的数据类型 第二部分&#xff1a;数组名 第三部分&#xff1a;数组标识符(方括号)和数组大小 一、测试代码 #include<stdio.h> int main() {int arr_int[10];char* arr_str[10];arr_in…

软件测试/测试开发丨Selenium环境安装配置

一、selenium 环境配置 1、下载浏览器 目前比较常用的浏览器是 Google Chrome 浏览器&#xff0c;所以本教程以 chrome 为主&#xff0c;后面简介一下其他浏览器的环境配置。 chrome 下载: www.google.cn/chrome/ 2、chromedriver 环境配置 chromedriver 是chromedriver提…

【C++】引用详解

前言 在学习C语言时&#xff0c;我们通常会遇到两个数交换的问题&#xff0c;为了实现这一功能&#xff0c;我们会编写一个经典的Swap函数&#xff0c;如下所示&#xff1a; void Swap(int *a, int *b) {int tmp *a;*a *b;*b tmp; } 然而&#xff0c;这个Swap函数看起来可…

CEC2017(Python):五种算法(SSA、RFO、OOA、PSO、GWO)求解CEC2017

一、5种算法简介 1、麻雀搜索算法SSA 2、红狐优化算法RFO 3、鱼鹰优化算法OOA 4、粒子群优化算法PSO 5、灰狼优化算法GWO 二、CEC2017简介 参考文献&#xff1a; [1]Awad, N. H., Ali, M. Z., Liang, J. J., Qu, B. Y., & Suganthan, P. N. (2016). “Problem defin…

Kubernetes 学习总结(43)—— Kubernetes 从提交 deployment 到 pod 运行的全过程

当用户向 Kubernetes 提交了一个创建 deployment 的请求后&#xff0c;Kubernetes 从接收请求直至创建对应的 pod 运行这整个过程中都发生了什么呢&#xff1f; kubernetes 架构简述 在搞清楚从 deployment 提交到 pod 运行整个过程之前&#xff0c;我们有先来看看 Kubernete…

Ubuntu 20.04使用Livox Mid-360

参考文章&#xff1a; Ubuntu 20.04使用Livox mid 360 测试 FAST_LIO-CSDN博客 一&#xff1a;Livox mid 360驱动安装与测试 前言&#xff1a; Livox mid360需要使用Livox-SDK2&#xff0c;而非Livox-SDK&#xff0c;以及对应的livox_ros_driver2 。 1. 安装Livox-SDK2 参…

RabbitMQ是做什么的

rabbitMQ是做异步通讯的。用于解决同步同讯的拓展性差&#xff0c;级联失败的问题。 异步调用方式其实就是基于消息通知的方式&#xff0c;一般包含三个角色:。 消息发送者:投递消息的人&#xff0c;就是原来的调用方 消息代理:管理、暂存、转发消息&#xff0c;你可以把它理…

软件测试/测试开发丨Python常用数据结构-列表list

列表的定义 列表是有序的可变元素的集合&#xff0c;使用中括号[ ]包围&#xff0c;元素之间用逗号分隔&#xff1b;列表是动态的&#xff0c;可以随时扩展和收缩&#xff1b;列表是异构的&#xff0c;可以同时存放不同类型的对象&#xff1b;列表允许出现重复的元素。 列表的…

六、从0开始卷出一个新项目瑞萨RZN2L之loader app分离工程优化

六、loader app分离工程 6.1 概述 6.2 官方资料与不足 6.3 loader app分离工程的优化 6.3.1 自动调节合并appsection 6.3.2 loader中使用外设 6.3.3 app使用sram mirror 6.3.4 sram atcm同时使用 六、从0开始卷出一个新项目之瑞萨RZN2L loader…

深入浅出理解转置卷积Conv2DTranspose

温故而知新&#xff0c;可以为师矣&#xff01; 一、参考资料 论文&#xff1a;A guide to convolution arithmetic for deep learning github源码&#xff1a;Convolution arithmetic bilibili视频&#xff1a;转置卷积&#xff08;transposed convolution&#xff09; 转置…

STM32入门教程-2023版【3-2】点亮LED灯之库函数介绍

关注 点赞 不错过精彩内容 大家好&#xff0c;我是硬核王同学&#xff0c;最近在做免费的嵌入式知识分享&#xff0c;帮助对嵌入式感兴趣的同学学习嵌入式、做项目、找工作! 二、正式点亮一个LED灯 操作STM32的GPIO需要三个步骤&#xff1a; 1.使用RCC打开GPIO的时钟&#…

基于策略模式和简单工厂模式实现zip、tar、rar、7z四种压缩文件格式的解压

推荐语 这篇技术文章深入探讨了基于策略模式和简单工厂模式实现四种常见压缩文件格式的解压方法。通过阅读该文章&#xff0c;你将了解到如何利用这两种设计模式来实现灵活、可扩展的解压功能&#xff0c;同时适应不同的压缩文件格式。如果你对设计模式和文件处理感兴趣或刚好…

Springboot配置http-Only

项目框架 jdk1.8、springboot2.5.10 情况一 项目中未使用&#xff08;权限认证框架&#xff1a;Sa-Token&#xff09; application.yml文件内增加配置 server.servlet.session.cookie.http-onlytrueserver.servlet.session.cookie.securetrue (此条配置建议也加上) 情况二…

课题学习(十八)----捷联测试电路设计与代码实现(基于MPU6050和QMC5883L)

一、 电路设计 本周主要工作是在项目上&#xff0c;抽空做了一个跟本课题相关的电路板&#xff0c;之前用开发板来做测试&#xff0c;MPU6050和QMC5883L都是用杜邦线连接的&#xff0c;导致接线很乱&#xff0c;也不美观&#xff0c;当然也不符合“捷联”的定义。   下面是电…

【领域驱动设计】模式--通用语言(Ubiquitous language)

一.前言 有道无术术可求&#xff0c;有术无道止于术。方法论的形成都是为了让我们能够更高效&#xff0c;系统的解决问题&#xff0c;而不至于遇到问题不知所措。 二.通用语言的必要性 相信大家在实际的软件开发流程过程中&#xff0c;经常会遇到参照 Prd原型 编码出的系统与实…

SSM驾校预约管理系统----计算机毕业设计

项目介绍 本项目分为管理员、教练、学员三种角色&#xff0c; 管理员角色包含以下功能&#xff1a; 学员管理、教练管理、车辆管理、关系管理、车辆维修管理、个人中心等功能。 教练角色包含以下功能&#xff1a; 我的课程、我的学员、车辆中心、个人中心等功能。 学员角色包…

zabbix添加监控主机(agent)并告警

一、添加监控主机 总体来说&#xff0c;在被监控主机上安装部署zabbix-agent&#xff0c;并修改配置文件&#xff08;zabbix_agentd.conf&#xff09;的参数。然后在zabbix 服务端zabbix-get检查是否可以监控。如果可以了&#xff0c;就可以在web页面添加了&#xff0c;要监控…

Ubuntu16.04 安装Anaconda

步骤 1&#xff1a; 去官网下载安装包,链接如下: https://repo.anaconda.com/archive/ 找到对应版本下载至本地电脑&#xff0c;并上传至服务器。 步骤2: 通过命令解压 sh Anaconda3-2023.03-0-Linux-x86_64.sh 一路选择yes或则回车&#xff0c;直到安装成功出现下面画面&…

Spring高手之路-@Autowired和@Resource注解异同点

目录 相同点 不同点 1.来源不同。 2.包含的属性不同 3.匹配方式&#xff08;装配顺序&#xff09;不同。 ​编辑 4.支持的注入对象类型不同 5.应用地方不同 相同点 都可以实现依赖注入&#xff0c;通过注解将需要的Bean自动注入到目标类中。都可以用于注入任意类型的Bean…

vue如何实现局部刷新?

应用场景&#xff1a; 比如你要切换tap栏实现刷新下面form表单等&#xff0c;相当于刷新页面。 如何使用如下&#xff1a; <div v-if"isReloadData"> 比如你想刷新那个位置就把 v-if"isReloadData"写到那个标签上 </div> 在data中定义刷新标…