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

【什么是反射机制?为什么反射慢?】

在这里插入图片描述

✅ 什么是反射机制?为什么反射慢?

  • ✅典型解析
  • ✅拓展知识仓
    • ✅反射常见的应用场景
    • ✅反射和Class的关系

✅典型解析


反射机制指的是程序在运行时能够获取自身的信息。在iava中,只要给定类的名字,那么就可以通过反射机制来获得类的所有属性和方法。


Java的反射可以:

1.在运行时判断任意一个对象所属的类
2.在运行时判断任意一个类所具有的成员变量和方法
3。在运行时任意调用一个对象的方法
4.在运行时构造任意一个类的对象


看一个Java反射机制代码:


import java.lang.reflect.Field;  
import java.lang.reflect.Method;  public class ComplexReflectionExample {  public static void main(String[] args) throws Exception {  // 获取Person类的Class对象  Class<?> personClass = Class.forName("com.example.Person");  // 创建一个新的Person对象  Object person = personClass.getDeclaredConstructor().newInstance();  // 调用set方法设置属性值  Method setNameMethod = personClass.getMethod("setName", String.class);  setNameMethod.invoke(person, "John Doe");  Method setAgeMethod = personClass.getMethod("setAge", int.class);  setAgeMethod.invoke(person, 30);  // 访问私有字段  Field nameField = personClass.getDeclaredField("name");  nameField.setAccessible(true);  String name = (String) nameField.get(person);  System.out.println("Name: " + name);  Field ageField = personClass.getDeclaredField("age");  ageField.setAccessible(true);  int age = ageField.getInt(person);  System.out.println("Age: " + age);  }  
}

假设我们有一个名为com.example.Person的类,其中包含一个私有字段name和一个私有方法setName和setAge。这个示例中,我们使用反射机制来动态创建Person对象,并调用它的setName和setAge方法来设置属性值。然后,我们使用反射来访问私有字段name和age,并打印它们的值。这个示例演示了如何使用反射机制来动态地创建对象、调用方法和访问字段,即使它们是私有的。


所以,我们应该在业务代码中应该尽量免使用反射,但是,作为一人合格的Java开发,也要能懂中间件,框架中的反射代码。在有些场景下,要知道可以使用反射解决部分问题。


那么,反射为什么慢呢? 主要由以下几个原因:

1、由于反射涉及动态解析的类型,因此不能执行某些Java虚拟机优化,如JIT优化


2、在使用反射时,参数需要包装(boxing)成Obiect[ ] 类型,但是真正方法执行的时候,又需要再拆包(unboxing)成真正的类型,这些动作不仅消耗时间,而且过程中也会产生很多对象,对象一多就容易导致GC,GC也会导致应用变慢。


3、反射调用方法时会从方法数组中遍历查找,并且会检查可见性。这些动作都是群时的


4、不仅方法的可见性要做检查,参数也需要做很多额外的检查


看一段代码:


public class ReflectionPerformanceDemo {  public static void main(String[] args) throws Exception {  // 创建Person对象  Person person = new Person("John Doe", 30);  // 使用反射获取name字段  Field nameField = person.getClass().getDeclaredField("name");  nameField.setAccessible(true);  String name1 = (String) nameField.get(person);  // 使用直接访问获取name字段  String name2 = person.getName();  // 使用反射调用setName方法  Method setNameMethod = person.getClass().getMethod("setName", String.class);  setNameMethod.invoke(person, "Jane Doe");  // 使用直接调用调用setName方法  person.setName("Jane Doe");  // 输出结果  System.out.println("Reflection name: " + name1);  System.out.println("Direct name: " + name2);  }  
}  class Person {  private String name;  private int age;  public Person(String name, int age) {  this.name = name;  this.age = age;  }  public String getName() {  return name;  }  public void setName(String name) {  this.name = name;  }  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  
}

创建了一个Person类,其中包含一个私有字段name和一个私有方法setName。然后,我们在main方法中创建了一个Person对象,并分别使用反射和直接访问来获取name字段的值,以及调用setName方法。最后,我们输出结果。你会发现,使用反射获取字段值和使用反射调用方法的时间都更长。这主要是因为反射机制需要在运行时解析类的元数据,并且需要进行安全检查,而直接访问字段和方法则不需要这些开销。因此,在性能敏感的应用程序中,应该尽量避免使用反射,或者只在必要时使用反射。


✅拓展知识仓


✅反射常见的应用场景


1.动态代理
2.JDBC的class.forName
3.BeanUtils中属性值的拷贝
4.RPC框架
5.ORM框架
6.Spring的IOC/DI


✅反射和Class的关系

Java的Class类是iava反射机制的基础,通过Class类我们可以获得关于一个类的相关信息。


Java.lang.Class是一个比较特殊的类,它用于封装被装入到VM中的类(包括类和接口)的信息。当一个类或接口被装入的JVM时便会产生一个与之关联的iava.lang.Class对象,可以通过这个Class对象对被装入类的详细信息进行访问。


虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时Java虚拟机(VM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。


看一段代码吧。


import java.lang.reflect.Method;  public class ReflectionExample {  public static void main(String[] args) {  try {  // 获取String类的Class对象  Class<?> stringClass = Class.forName("java.lang.String");  // 输出类名  System.out.println("Class Name: " + stringClass.getName());  // 获取所有公共方法  Method[] methods = stringClass.getMethods();  // 输出方法信息  System.out.println("Methods:");  for (Method method : methods) {  System.out.println("  " + method.getName());  }  // 获取并调用特定方法  Object str = stringClass.getDeclaredConstructor().newInstance();  Method charAtMethod = stringClass.getMethod("charAt", int.class);  Character charAtPosition = (Character) charAtMethod.invoke(str, 5);  System.out.println("Character at position 5: " + charAtPosition);  } catch (Exception e) {  e.printStackTrace();  }  }  
}

使用Class.forName()方法获取java.lang.String类的Class对象。然后,我们使用getName()方法获取类名,使用getMethods()方法获取所有的公共方法,使用getDeclaredConstructor()和newInstance()方法创建新的对象,并使用getMethod()和invoke()方法调用特定的方法。

相关文章:

【什么是反射机制?为什么反射慢?】

✅ 什么是反射机制&#xff1f;为什么反射慢&#xff1f; ✅典型解析✅拓展知识仓✅反射常见的应用场景✅反射和Class的关系 ✅典型解析 反射机制指的是程序在运行时能够获取自身的信息。在iava中&#xff0c;只要给定类的名字&#xff0c;那么就可以通过反射机制来获得类的所有…...

PostGreSQL:货币类型

货币类型&#xff1a;money money类型存储固定小数精度的货币数字&#xff0c;小数的精度由数据库的lc_monetary设置决定。windows系统下&#xff0c;该配置项位于/data/postgresql.conf文件中&#xff0c;默认配置如下&#xff0c; lc_monetary Chinese (Simplified)_Chi…...

ESP8266网络相框采用TFT_eSPI库TJpg_Decoder库mixly库UDP库实现图片传送

用ESP8266和TFT_ESPI模块来显示图片数据。具体来说&#xff0c;我们将使用ILI9431显示器作为显示设备&#xff0c;并通过UDP协议将图片数据从发送端传输到ESP8266。最后&#xff0c;我们将解析这些数据并在TFT屏幕上显示出来。在这个过程中&#xff0c;我们将面临一些编程挑战&…...

Go 泛型发展史与基本介绍

Go 泛型发展史与基本介绍 Go 1.18版本增加了对泛型的支持&#xff0c;泛型也是自 Go 语言开源以来所做的最大改变。 文章目录 Go 泛型发展史与基本介绍一、为什么要加入泛型&#xff1f;二、什么是泛型三、泛型的来源四、为什么需要泛型五、Go 泛型设计的简史六、泛型语法6.1 …...

python 解决手机拍的书籍图片发灰的问题

老师给发的作业经常是手机拍的&#xff0c;而不是扫描&#xff0c;背景发灰&#xff0c;如果二次打印就没有看了&#xff0c;象这样&#xff1a; 如果使用photoshop 处理&#xff0c;有些地方还是扣不干净&#xff0c;不如python 做的好&#xff0c;处理后如下&#xff1a; 具体…...

【prompt一】Domain Adaptation via Prompt Learning

1.Motivation 当前的UDA方法通过对齐源和目标特征空间来学习域不变特征。这种对齐是由诸如统计差异最小化或对抗性训练等约束施加的。然而&#xff0c;这些约束可能导致语义特征结构的扭曲和类可辨别性的丧失。 在本文中&#xff0c;引入了一种新的UDA提示学习范式&#xff0…...

视频编辑与制作,添加视频封面的软件

如今&#xff0c;视频已经成为了我们生活中不可或缺的一部分&#xff0c;无论是社交媒体上的短视频&#xff0c;还是电影、电视剧&#xff0c;视频都以其独特的魅力吸引着我们的目光。而在这背后&#xff0c;视频剪辑软件功不可没。今天&#xff0c;我就为大家揭秘一款新一代的…...

Deepin更换仿Mac主题

上一篇博客说了要写一篇deepin系统的美化教程 先看效果图&#xff1a; 准备工作&#xff1a; 1.你自己 嘻嘻嘻 2.能上网的deepin15.11电脑 首先去下载主题 本次需要系统美化3部分&#xff1a;1.图标 2.光标 3.壁纸 开始之前&#xff0c;请先把你的窗口特效打开&#xff0c;…...

【Flink-Kafka-To-ClickHouse】使用 Flink 实现 Kafka 数据写入 ClickHouse

【Flink-Kafka-To-ClickHouse】使用 Flink 实现 Kafka 数据写入 ClickHouse 1&#xff09;导入相关依赖2&#xff09;代码实现2.1.resources2.1.1.appconfig.yml2.1.2.log4j.properties2.1.3.log4j2.xml2.1.4.flink_backup_local.yml 2.2.utils2.2.1.DBConn2.2.2.CommonUtils2.…...

浅谈Redis分布式锁(下)

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 自定义Redis分布式锁的…...

Django Rest Framework框架的安装

Django Rest Framework框架的安装 Django Rest Framework框架的安装 1.DRF简介2.安装依赖3.安装使用pip安装添加rest_framework应用 1.DRF简介 Django REST Framework是Web api的工具包。它是在Django框架基础之上&#xff0c;进行了二次开发。 2.安装依赖 链接python安装 …...

深度学习(七):bert理解之输入形式

传统的预训练方法存在一些问题&#xff0c;如单向语言模型的局限性和无法处理双向上下文的限制。为了解决这些问题&#xff0c;一种新的预训练方法随即被提出&#xff0c;即BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;。通过在大规模…...

如何用Excel制作一张能在网上浏览的动态数据报表

前言 如今各类BI产品大行其道&#xff0c;“数据可视化”成为一个热门词汇。相比价格高昂的各种BI软件&#xff0c;用Excel来制作动态报表就更加经济便捷。今天小编就将为大家介绍一下如何使用葡萄城公司的纯前端表格控件——SpreadJS来实现一个Excel动态报表&#xff1a; 实…...

双向数据绑定是什么

一、什么是双向绑定 我们先从单向绑定切入单向绑定非常简单&#xff0c;就是把Model绑定到View&#xff0c;当我们用JavaScript代码更新Model时&#xff0c;View就会自动更新双向绑定就很容易联想到了&#xff0c;在单向绑定的基础上&#xff0c;用户更新了View&#xff0c;Mo…...

鱼眼标定方式

鱼眼作用 人单眼水平视角最大可达156度&#xff0c;垂直方向150度。为了增加可视范围&#xff0c;摄像头可以通过畸变参数扩大视野&#xff0c;一般100度到200度的fov。所以鱼眼是为了看的视野更大&#xff0c;注意在一定分辨率下&#xff0c;fov边缘的像素点稀疏&#xff0c;…...

详解Keras3.0 KerasNLP Models: GPT2 GPT2Tokenizer

1、GPT2Tokenizer 用于将文本数据转换为适合训练和预测的格式&#xff0c;主要功能是将输入的文本进行分词、编码等操作&#xff0c;以便在神经网络中使用 keras_nlp.models.GPT2Tokenizer(vocabulary, merges, **kwargs) 参数说明 vocabulary&#xff1a;一个字典&#x…...

2016年第五届数学建模国际赛小美赛B题直达地铁线路解题全过程文档及程序

2016年第五届数学建模国际赛小美赛 B题 直达地铁线路 原题再现&#xff1a; 在目前的大都市地铁网络中&#xff0c;在两个相距遥远的车站之间运送乘客通常需要很长时间。我们可以建议在两个长途车站之间设置直达班车&#xff0c;以节省长途乘客的时间。   第一部分&#xf…...

三秦通ETC续航改造

前些天开车时ETC每隔2分钟滴滴响一下&#xff0c;重插卡提示电池电压低 2.8V。看来应该是电池不行了。去银行更换ETC应该是需要费用的。还有一种办法是注销掉&#xff0c;然后去别的银行办一个。不过我想自己更换电池试一下。 首先拆下ETC&#xff0c;我使用的办法是开水烫。烧…...

使用Python实现发送Email电子邮件【第19篇—python发邮件】

文章目录 &#x1f47d;使用Python实现发送Email电子邮件&#x1f3b6;实现原理&#x1f3c3;Python实现发送Email电子邮件-基础版&#x1f46b;实现源码&#x1f646;源码解析 &#x1f487;Python实现发送Email电子邮件-完善版&#x1f46b;实现源码&#x1f646;源码解析&am…...

Docker基本命令和Docker怎么自己制作镜像

基本命令 启动新的容器&#xff08;指定容器名称和端口映射【主机端口&#xff1a;容器端口】) docker run --name 容器名 -p 8080:80 镜像名 启动新的容器&#xff08;交互式&#xff09; docker run -it centos7-with-jdk /bin/bash 特权方式启动容器 docker run -d --…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...