关于java的反射

news2024/9/21 12:41:54

❓❓❓反射是啥呀相信许多学java的同学非常困惑在学的时候,总是感觉懂了却又没懂或者直接忽略过去了,那么本文就带大家探讨一下什么是反射在java中以及它的机制和运用。

⭐️什么是反射:

首先我们知道一些知识:

维基百科的解释

在计算机学中,反射式编程(英语:reflective programming)或反射(英语:reflection),是指计算机程序在运行时(runtime)可以访问、检测和修改它本身状态或行为的一种能力.用比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为。
要注意术语“反射”和“内省”(type introspection)的关系。内省(或称“自省”)机制仅指程序在运行时对自身信息(称为元数据)的检测;反射机制不仅包括要能在运行时对程序自身信息进行检测,还要求程序能进一步根据这些信息改变程序状态或结构。

这个解释用在java就是通过jvm创建class示例进行操作反过来又能对对象进行访问和修改。反射(Reflection)是 Java 的一种特性,它可以让程序在运行时获取自身的信息,并且动态地操作类或对象的属性、方法和构造器等。通过反射功能,可以让我们在不知道具体类名的情况下,依然能够实例化对象,调用方法以及设置属性。
首先知道一个加载过程
img
在这里插入图片描述

Java语言的编译过程主要包括以下几个步骤:

词法分析:
词法分析器(Lexer)读取源代码文件,将源代码中的字符序列转换为记号(Token)序列。这些记号是编译器进一步处理的基本单元。
语法分析:
语法分析器(Parser)根据Java语言的语法规则,将词法分析器输出的记号序列组织成语法树(Abstract Syntax Tree, AST)。语法树表示了源代码中的程序结构。
语义分析:
语义分析器检查语法树是否满足语义规则,比如变量是否已经声明、类型是否匹配、表达式是否有意义等。这个阶段还会进行一些类型推断和转换。
字节码生成:
编译器将经过语义分析后的语法树转换成字节码(Bytecode)。字节码是一种平台无关的中间代码,它可以在任何安装了Java虚拟机(JVM)的平台上运行。
具体来说,Java编译过程如下:
源代码到字节码:
使用javac命令或Java编译器API将.java源文件编译成.class字节码文件。这一步包含了上述的词法分析、语法分析、语义分析和字节码生成。
字节码验证:
当.class文件被加载到JVM时,字节码验证器会检查字节码文件,确保其遵循Java语言规范,没有安全问题,比如确保不会发生数组越界、栈溢出等。
类加载:
类加载器(ClassLoader)负责将.class文件加载到JVM中,并为字节码分配内存,将其转换为运行时数据结构。
运行时优化:
JVM可能会对字节码进行即时编译(Just-In-Time, JIT)优化,将字节码转换成本地机器码以提高执行效率。
执行:
最终,在JVM上执行这些字节码,程序开始运行。
这个过程确保了Java语言的“一次编写,到处运行”的特性,因为编译生成的字节码可以在任何有JVM的平台上执行。

然后我们正式开始:
反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释。

一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的。于是我们直接对这个类进行实例化,之后使用这个类对象进行操作。

Apple apple = new Apple(); //直接初始化,「正射」
apple.setPrice(4);

上面这样子进行类对象的初始化,我们可以理解为「正」。

而反射则是一开始并不知道我要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象了。

这时候,我们使用 JDK 提供的反射 API 进行反射调用:

Class clz = Class.forName("com.muggle.reflect.Apple");
Method method = clz.getMethod("setPrice", int.class);
Constructor constructor = clz.getConstructor();
Object object = constructor.newInstance();
method.invoke(object, 4);

上面两段代码的执行结果,其实是完全一样的。但是其思路完全不一样,第一段代码在未运行时就已经确定了要运行的类(Apple),而第二段代码则是在运行时通过字符串值才得知要运行的类(com.chenshuyi.reflect.Apple)。

所以说什么是反射?

反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

⭐️获取Class对象的三种方式

package fanshe;
/**
 * 获取Class对象的三种方式
 * 1 Object ——> getClass();
 * 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
 * 3 通过Class类的静态方法:forName(String  className)(常用)
 *
 */
public class Fanshe {
	public static void main(String[] args) {
		//第一种方式获取Class对象  
		Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
		Class stuClass = stu1.getClass();//获取Class对象
		System.out.println(stuClass.getName());
		
		//第二种方式获取Class对象
		Class stuClass2 = Student.class;
		System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
		
		//第三种方式获取Class对象
		try {
			Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
			System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
	}
}

⭐️反射的运用

框架:半成品软件。可以在框架的基础上进行软件开发,简化编码
反射:将类的各个组成部分封装为其他对象,这就是反射机制
​ 好处:
​ 可以在程序运行过程中,操作这些对象。
​ 可以解耦,提高程序的可扩展性。
像咱们平时大部分时候都是在写业务代码,很少会接触到直接使用反射机制的场景。但是,这并不代表反射没有用。相反,正是因为反射,你才能这么轻松地使用各种框架。像 Spring/Spring Boot、MyBatis 等等框架中都大量使用了反射机制。这些框架中也大量使用了动态代理,而动态代理的实现也依赖反射。比如下面是通过 JDK 实现动态代理的示例代码,其中就使用了反射类 Method 来调用指定的方法。

public class DebugInvocationHandler implements InvocationHandler {
    /**
     * 代理类中的真实对象
     */
    private final Object target;

    public DebugInvocationHandler(Object target) {
        this.target = target;
    }


    public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
        System.out.println("before method " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("after method " + method.getName());
        return result;
    }
}


另外,像 Java 中的一大利器 注解 的实现也用到了反射。为什么你使用 Spring 的时候 ,一个@Component注解就声明了一个类为 Spring Bean 呢?为什么你通过一个 @Value注解就读取到配置文件中的值呢?究竟是怎么起作用的呢?这些都是因为你可以基于反射分析类,然后获取到类/属性/方法/方法的参数上的注解。你获取到注解之后,就可以做进一步的处理。谈谈反射机制的优缺点优点:可以让咱们的代码更加灵活、为各种框架提供开箱即用的功能提供了便利缺点:让我们在运行时有了分析操作类的能力,这同样也增加了安全问题。比如可以无视泛型参数的安全检查(泛型参数的安全检查发生在编译时)。
在使用 JDBC 连接数据库时使用 Class.forName()通过反射加载数据库的驱动程序,如果是mysql则传入mysql的驱动类,而如果是oracle则传入的参数就变成另一个了。

Spring 框架的 IOC(动态加载管理 Bean),Spring通过配置文件配置各种各样的bean,你需要用到哪些bean就配哪些,spring容器就会根据你的需求去动态加载,你的程序就能健壮地运行。

还有Spring AOP(动态代理)功能都和反射有关系。

除此之外还有很多框架:mybatis、dubbo、rocketmq等等都会用到反射机制。


参考

反射的作用
大白话说反射
javaguide
java非常重要的基础概念之一
反射

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

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

相关文章

2024-07-15 Unity插件 Odin Inspector4 —— Collection Attributes

文章目录 1 说明2 集合相关特性2.1 DictionaryDrawerSettings2.2 ListDrawerSettings2.3 TableColumnWidth2.4 TableList2.5 TableMatrix 1 说明 ​ 本文介绍 Odin Inspector 插件中集合(Dictionary、List)相关特性的使用方法。 2 集合相关特性 2.1 D…

《Programming from the Ground Up》阅读笔记:p49-p74

《Programming from the Ground Up》学习第3天,p49-p74总结,总计26页。 一、技术总结 1.function (1)定义 p49, Functions are unit of code that do a defined piece of work on specified types of data。 函数是在指定类型的数据上完成所定义的某…

【Qt 常用控件】

文章目录 1. Push Button 1. Push Button 🐧给按钮设置图标

供应链管理(SCM):如何在颜值和体验上发力

要在供应链管理系统(SCM)中在颜值和体验上发力,让用户感觉耳目一新,可以采取以下措施: 界面设计优化: 对供应链管理系统的界面进行优化,注重界面的美观、简洁和易用性。采用现代化的设计风格、…

Catena-x标准解读:CX-0001 EDC Discovery API v1.0.2 EDC发现API

随着Catena-X网络的扩展,大量数据资产将通过EDC连接技术提供。在网络中有效地识别正确的EDC端点可能很困难。 为了符合GAIA-X标准,每个EDC端点必须提供ServiceOffering类型的自我描述(SD)。基于这些SD,必须提供数据和…

可视化作品集(14)智慧旅游和智慧景区,洞悉一切。

智慧旅游和智慧景区的可视化大屏可以带来以下几个方面的好处: 1. 提升游客体验: 通过可视化大屏,游客可以方便地获取到景区地图、交通信息、景点介绍、活动安排等信息,帮助游客更好地规划行程,提升游览体验。 2. 提供…

手写new

手写new new是什么执行new会发生什么实现new new是什么 new 操作符是可以创建一个用户定义的对象的实例或具有构造函数的内置对象的实例 function Car (make, model, year) {this.make makethis.model modelthis.year year } Car.prototype.running function () {return …

Zynq系列FPGA实现SDI编解码转SFP光口传输(光端机),基于GTX高速接口,提供6套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本方案在Xilinx-Kintex7上的应用 3、详细设计方案设计原理框图输入Sensor之-->OV5640摄像头输入Sensor之-->HDMIVDMA图像缓存RGB转BT1120GTX 解串与串化SMPTE SD/HD/3G SDI IP核BT1120转RGBHDMI输…

实习随笔【iviews的Select实现‘与全部互斥’的多选】

在实习中,遇到了如下需求,要求如下: 上面提到了一个需求为,选择全部与选择一个或者多个互斥,我们来看一下如何解决 核心代码 监听value的变化,如果含有‘全部’,且数组长度>1,则删…

Redis面试问题一

Redis在面试中有很大的概率会问到,因此我们一定要学会回答此方面的问题。 Redis主要涉及到使用场景已经一些其他方面的问题。 下面是有可能涉及到的问题。 问题一:你最近的项目中那些场景用到了Redis呢? 需要结合简历项目上的业务进行具体…

Rust 通过 Deref trait 将智能指针当作常规引用处理

通过 Deref trait 将智能指针当作常规引用处理 实现 Deref trait 允许我们重载 解引用运算符(dereference operator)*(与乘法运算符或通配符相区别)。通过这种方式实现 Deref trait 的智能指针可以被当作常规引用来对待&#xff…

WPF+MvvmLight 项目入门完整教程(一)

WPF+MvvmLight入门完整教程一 创建项目MvvmLight框架安装完善整个项目的目录结构创建自定义的字体资源下载更新和使用字体资源创建项目 打开VS2022,点击创建新项目,选择**WPF应用(.NET Framework)** 创建一个名称为 CommonProject_DeskTop 的项目,如下图所示:MvvmLight框架…

SQL Server 2019安装详细教程(图文详解,非常靠谱)

Microsoft SQL Server 是一种关系数据库管理系统 (RDBMS)。 应用程序和工具连接到 SQL Server 实例或数据库,并使用 Transact-SQL (T-SQL) 进行通信。 SQL Server Management Studio (SSMS) 是一种集成环境,用于管理任何 SQL 基础结构。 使用 SSMS 访问、…

AutoGen实战AI Agent开发

最近,关于 AI 智能体或AI代理(AI Agent)的讨论很多。受这种炒作的影响,我阅读了一些资料,偶然发现了 AutoGen,这是一个构建 AI 代理的很棒的库。但 AI 代理到底是什么?为什么它们很重要&#xf…

移动UI:表单美观易操作的十大准则,非常实用。

移动端表单设计需要遵循一些原则,以确保美观和易操作: 1.简洁明了: 在移动端表单设计中,要尽量简化内容,避免过多的文字和元素,保持简洁明了的布局,以便用户能够快速理解并填写表单。 2.响应式…

在 PostgreSQL 中如何优化涉及多个视图嵌套和函数调用的复杂查询?

🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!📚领书:PostgreSQL 入门到精通.pdf 文章目录 在 PostgreSQL 中如何优化涉及多个视图嵌套和函数调用的复杂查询一、理解问题的本质二、优化的基本原则…

直播美颜工具开发教学:视频美颜SDK集成详解

本篇文章,笔者将详细介绍如何在直播应用中集成视频美颜SDK,让你的直播画面焕然一新。 一、什么是视频美颜SDK? 视频美颜SDK是一种软件开发工具包,提供了视频处理和图像增强功能。通过集成视频美颜SDK,开发者可以轻松…

【postgresql】角色(Role)

PostgreSQL 中,角色(Role)是一个重要的概念,用于管理数据库的访问权限和用户身份。角色可以被视为用户或组,具体取决于它们的配置方。 角色属性 角色可以具有多种属性: LOGIN:允许角色登录数据…

Apple Vision Pro 和其商业未来

机器人、人工智能相关领域 news/events (专栏目录) 本文目录 一、Vision Pro 生态系统二、Apple Vision Pro 的营销用例 随着苹果公司备受期待的进军可穿戴计算领域,新款 Apple Vision Pro 承载着巨大的期望。 苹果公司推出的 Vision Pro 售…

2024.7.12单片机PWM

遇到了一个光标变成下划线的问题: Keil5光标变下划线,变回来的方法_keil5光标是下划线-CSDN博客 这里是用了输入捕获(IC:input capture),输出比较(OC:Output Compare)区别 学到这…