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

news2024/11/26 15:27:01

在这里插入图片描述

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

  • ✅典型解析
  • ✅拓展知识仓
    • ✅反射常见的应用场景
    • ✅反射和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()方法调用特定的方法。

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

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

相关文章

C++笔试训练day_2

文章目录 选择题7. 编程题1.2. 选择题 &#xff08;6&#xff09;因为p2被const修饰所以p2不可以被改变&#xff0c;但是p2的指向可以被改变 &#xff08;7&#xff09;因为指针p3被const修饰&#xff0c;所以p3的指向不能被改变&#xff0c;但是*p3可以被改变 int main() {in…

spring boot集成mybatis和springsecurity实现权限控制功能

上一篇已经实现了登录认证功能&#xff0c;这一篇继续实现权限控制功能&#xff0c;文中代码只贴出来和上一篇不一样的修改的地方&#xff0c;完整代码可结合上一篇一起整理spring boot集成mybatis和springsecurity实现登录认证功能-CSDN博客 数据库建表 权限控制的意思就是根…

前端常用的工具网站

前端常用的工具网站&#x1f516; 文章目录 前端常用的工具网站&#x1f516;1. 图片在线压缩2. iconfont--矢量图标3. JSON在线格式化4. EMOJIALL--表情符号5. removebg--去除图片背景6. FREE API--免费API接口7. Lorem picsum --随机图片8.UU在线工具 -- 聚合工具 1. 图片在线…

Windows系统安装 ffmpeg

下载及解压 ffmpeg官方下载地址&#xff1a;https://ffmpeg.org/download.html 下载好后将其解压至你想保存的位置中。 环境变量设置 打开Windows设置&#xff0c;在搜索框输入&#xff1a;系统高级设置。 新建环境变量&#xff0c;并输入bin目录具体位置。 安装检查 按住 w…

图形处理工具:Photoshop Elements 2020 mac介绍说明

Photoshop Elements 2020 mac简称ps elements 2020&#xff0c;是一款图形处理工具。ps elements 2020 mac可以帮助您自动生成照片和视频作品的功能&#xff0c;采用Sensei AI技术可进行图像组织、编辑和创建等。Photoshop Elements 2020 可以帮助您轻松整理照片和视频&#xf…

【Linux】定时任务

定时任务常用crontab来定期执行程序。 crontab 基本语法 crontab [-u user] -l # 列出用户cron任务 crontab [-u user] -e # 编辑用户cron任务 crontab [-u user] -r # 移除用户cron任务cron 表达式 # 分 时 日 月 周 执行命令 minute hour day month week command # 示例…

Simulink元件

constant 输出常数/标量 这样我们就只输出了一个常数 输出一维数组/矢量 这样我们就输出了1-5一共5个数字 输出二维数组 这样我们就输出了4个数字 选择框Interpret vector parameters as 1-D 如果标量或者矩阵&#xff0c;勾与不勾都一样。 如果是向量&#xff0c;勾选则表…

Keil中文报错提示为: [-Winvalid-source-encoding]问题解决

错误提示&#xff1a; ../User/main.c(67): warning: illegal character encoding in string literal [-Winvalid-source-encoding]67 | printf("全<B2><BF><B4><AB><CA><E4><CD><EA><B3><C9…

java旅游攻略管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web旅游攻略管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql…

2023 第六届安洵杯 writeup

CRYPTO 010101 漏洞点在 p1[random.choice([i for i, c in enumerate(p1) if c 1])] 0p2[random.choice([i for i, c in enumerate(p1) if c 0])] 1 p1只是随机的把1的位置转一个变成0&#xff0c;p2把0的位置随机转一个到1&#xff0c;直接逆回去即可 charonroot:~/D…

Unity使用Rider作为默认编辑器

01.Edit -> Preferences 02.Externel Tools -> Open by file extension 如果界面选项有Rider直接选择&#xff0c;如果没有选择Browse) 03.选择rider64.exe 04.成功关联

Qt的简单游戏实现提供完整代码

文章目录 1 项目简介2 项目基本配置2.1 创建项目2.2 添加资源 3 主场景3.1 设置游戏主场景配置3.2 设置背景图片3.3 创建开始按钮3.4 开始按钮跳跃特效实现3.5 创建选择关卡场景3.6 点击开始按钮进入选择关卡场景 4 选择关卡场景4.1场景基本设置4.2 背景设置4.3 创建返回按钮4.…

C++设计模式 #6 桥模式(Bridge)

动机 由于某些类型的固有的实现逻辑&#xff0c;使得它们具有两个变化的维度&#xff0c;乃至多个变化的维度。 如何应对这种“多维度的变化”&#xff1f;如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化&#xff0c;而不引入额外的复杂度 举个栗子 我们…

JavaOOP篇----第十五篇

系列文章目录 文章目录 系列文章目录前言一、有没有可能两个不相等的对象有相同的hashcode二、拷贝和浅拷贝的区别是什么?三、static都有哪些用法?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通…

基于SSM的双减后初小教育课外学习生活活动平台的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

【零基础入门Docker】如何构建Web服务Dockerfile?

✍面向读者&#xff1a;所有人 ✍所属专栏&#xff1a;零基础入门Docker专栏https://blog.csdn.net/arthas777/category_12455882.html 目录 步骤1&#xff1a;第一步是构建我们的Docker文件&#xff0c;您可以使用vim编辑器。 步骤2&#xff1a;下一步是使用docker build命令…

学习stm32 模电数电需要学哪些?

学习stm32 模电数电需要学哪些&#xff1f; 在开始前我有一些资料&#xff0c;是我根据自己从业十年经验&#xff0c;熬夜搞了几个通宵&#xff0c;精心整理了一份「 stm32的资料从专业入门到高级教程工具包」&#xff0c;点个关注&#xff0c;全部无偿共享给大家&#xff01;&…

帧内预测器的设计:提升视频编码效率的关键技术

随着互联网的迅猛发展&#xff0c;视频应用成为人们日常生活中不可或缺的一部分。然而&#xff0c;视频文件的传输和存储所需要的带宽和空间成本巨大。为了解决这个问题&#xff0c;视频编码技术应运而生。在视频编码中&#xff0c;帧内预测器是一项关键技术&#xff0c;通过利…

Linux-Keepalived(VRRP协议)高可用集群搭建

Linux-Keepalived&#xff08;VRRP协议&#xff09;高可用集群搭建 一、VRRP简介1.1 什么是VRRP&#xff1f;1.2 keepalived是什么&#xff1f;1.3 keepalived工作原理 二、实操配置过程2.1 试验模型2.2. Keepalived监控和维护VRRP集群的步骤2.2.1 安装keepalived2.2.2 配置kee…

力扣算法-Day1

160. 相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 示例 1&#xff1a; 输入&#xff1a;intersectVal 8, listA [4,1,8,4,5], listB [5,6,1,8,4,5], skipA 2, s…