【JavaSE】反射

Java代码的生命周期

Java代码在计算机中经历的阶段:Source源代码阶段、Class类对象阶段、RunTime运行时阶段。

Source源代码阶段: 这个阶段是由程序员编写生成源代码,再由Javac编译器生成class文件。

Class类对象阶段:由类加载器将class文件加载到JVM内存中,并对class文件进行解析生成Class对象。

Runtime运行时阶段:由class对象创建对应的类对象。

反射的概念

正射与反射

正射:一般情况下,我们创建对象时就知道需要创建什么类,所以直接new一个对应类型的对象。

Car car = new Car();

反射:在创建对象时,并不知道对象类型。需要一定的手段(下文中获取class对象的方式)去找到其类型,再将该类型分装成class对象,class对象根据找到的类型再去创建对应类型的对象。

分析Java代码的阶段时,ClassLoader将class文件加载到内存,并且创建class对象,将原本class文件的各个部分都封装成对象。后面在运行时通过class对象及其内部的其他对象去生成最后程序真正所需要的对象。这个过程就是反射。

总结

正射是先创建对象,再访问类信息。

反射是获取信息,再创建对象。

反射的优点

1.可以在程序运行的过程中,动态的获取类信息,并进行操作。比较灵活。

比如Idea的提示功能,Idea之所以能够提示类中的各种信息,就是通过反射获取到了类信息。

2.可实现解耦,增强程序的可扩展性。

通过反射机制,可以动态的获取类信息,并进行操作。在庞大的项目中,面对复杂的需求,利用反射机制可以做到不修改源代码的情况下,就可以实现不同的功能。

比如启动Tomcat服务器时,用户修改了配置文件中的端口号,那么服务器就可以使用用户指定的端口号。这就是将配置文件与Tomcat程序进行解耦。

反射的使用过程

1.查找类信息。

类信息可以是字节码文件、加载到内存中的类信息(解析了字节码文件之后的信息)、对象(对象中包含着类的详细信息)。

2.根据类信息创建Class对象。

3.通过Class对象动态的获取类信息,甚至操作类信息。

Class对象的获取方式

使用反射的核心就是获取到Class对象。Java是面向对象的编程语言,反射根据类信息创建Class对象,而想要动态的将类信息获取出来就属于Class对象的职能了。

1.Class.forName(String className)

这种方式是通过Class类获取的。

这种方式是在Source源代码阶段,根据className找到对应的class文件,在文件中获取到类信息,将其信息的各个组成部分封装成对象。

类的各个组成部分:成员变量、成员方法、构造器、静态资源等。

使用场景:多用于读取配置文件来加载类信息,可以将类名在文件中进行配置。

2.类名.class

这种方式是通过类名的属性来获取的。

这种方式是在Class类对象阶段,根据已经记载到内存中的类信息就能知道类名,再根据类名的class属性获取Class对象。

使用场景:多用于参数传递。

3.对象名.getClass()

这种方式是根据对象的getClass()方法获取的,getClass()方法是Object提供的。

这种方式是在Runtime运行时阶段,根据已经存在的对象实例来获取其Class对象。

使用场景:多用于通过对象来获取字节码的方式。

扩展:不管使用哪一种方式获取class对象,都是同一个对象。

因为字节码文件(*.class)在程序运行过程中只会被加载一次,只会创建一个class对象。

结论验证:

//获取class对象的方法
public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException {
​
        //1.Class.forName(String className)
        Class clazz1 = Class.forName("reflectdemo1.Car");
​
        //2.类名.class
        Class clazz2 = Car.class;
​
        //3.对象名.getClass()
        Class clazz3 = new Car().getClass();
​
        System.out.println(clazz1 == clazz2);
        System.out.println(clazz3 == clazz2);
        System.out.println(clazz1 == clazz3);
​
    }
}
​
输出:
true
true
true

Class对象的功能

Class对象可以让我们获取类的所有信息,包括但不限于类中定义的成员方法、成员变量、静态资源、所属包等等。接下来介绍一下Class的API(主要的)。

1.获取成员变们

Field[] getFields()

Field getField(String name)

Field[] getDeclaredFields()

Field getDeclaredField(String name)

2.获取构造方法们

Constkuctor<?>[] getConstructors()

Constructor<T> getConstructor(Class<?>... parameterTypes)

Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) Constructor<?>[] getDeclaredconstructors()

3.获取成员方法们

Method[] getMethods()

Method getMethod(String name, 类<?>... parameterTypes)

Method[] getDeclaredMethods()

Method getDeclaredMethod(string name, 类<?>... parameterTypes)

4.获取类名

string getName()

获取到对应的信息可以在根据其API进行操作。

反射使用案例

需求:实现一个框架,使其能够动态的创建指定类型的对象并执行指定类型的方法。

代码实现:

//框架:动态的创建对象,并执行相应的方法;
public class Test {
    public static void main(String[] args) throws Exception {
        //1.读取配置文件
        //1.1创建Properties对象
        Properties properties = new Properties();
        //1.2读取class目录下的配置文件
        ClassLoader classLoader = Test.class.getClassLoader();
        //1.3获取配置文件的输入流
        InputStream is = classLoader.getResourceAsStream("application.properties");
        //1.4将配置文件加载到properties中
        properties.load(is);
        //1.5读取配置文件中的内容
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");
​
        //2.获取需加载类的Class对象
        Class<?> cls = Class.forName(className);
​
        //3.创建对象
        Object obj = cls.newInstance();
​
        //4.执行方法
        //4.1获取需要执行的方法
        Method method = cls.getDeclaredMethod(methodName);
        method.invoke(obj);
​
    }
}

框架中读取的application.properties配置文件如下:

className = model.Student
methodName = sleep

运行结果:

sleep....

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【保姆级教程】如何订阅OnlyFans?如何在OnlyFans上面支付?OnlyFans虚拟卡订阅教程

1. 引言 什么是OnlyFans&#xff1a;OnlyFans是一种内容订阅服务&#xff0c;成立于2016年&#xff0c;允许内容创作者从用户那里获得资金&#xff0c;用户需要支付订阅费用才能查看他们的内容。它在多个领域受到欢迎&#xff0c;包括音乐、健身、摄影&#xff0c;以及成人内容…

C语言之指针(4)使用并模拟实现qsort

冒泡排序有局限性&#xff0c;实现时间长而且只能进行整型数据的排序&#xff0c;接下来介绍模拟实现qsort来方便实现各种数据的排序。 函数基本形式&#xff1a; 可以看到该函数有四个参数&#xff0c;第四个参数是一个函数指针&#xff0c;这个指针指向的函数第一个参数和第…

数据分析——数据规范化

数据规范化是数据分析中的一个重要步骤&#xff0c;其目的在于确保数据的一致性和可比性&#xff0c;提高数据质量和分析结果的准确性。以下是一些数据规范化的常见方法和技术&#xff1a; 数据清洗&#xff1a;此步骤主要清除数据中的重复项、空格、格式错误等&#xff0c;确…

【Oracle】oracle、mysql、sql server三者区别

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Oracle》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识…

Waifu2x:使用深度卷积神经网络的动漫风格艺术的图像超分辨率

Github网址&#xff1a;nagadomi/waifu2x&#xff1a;动漫风格艺术的图像超分辨率 (github.com) 该项目主要讲述的是如何利用预训练的深度学习模型来达到无损扩大收缩和去噪&#xff0c;对于一般训练图像的小伙伴应该很清晰图像经常要通过resize操作固定大小&#xff0c;然后c…

操作系统① —— 进程管理

1. 进程、线程、协程 进程&#xff1a; 是系统进行资源分配的基本单位私有地址空间&#xff0c;私有栈、堆上下⽂切换需要切换虚拟地址空间 线程&#xff1a; 是资源调度的基本单位公有同⼀地址空间&#xff0c;公有堆、私有栈上下⽂切换只需要切换少量寄存器 进程和线程的对比…

Oracle APEX 23.2版本 使用应用程序工作副本进行协作开发

现状描述&#xff1a; 当前APEX协作开发都是在同一应用程序下进行的&#xff0c;这样做有可能因同一时间对同一数据进行操作造成锁表或其他问题&#xff0c;Oracle APEX23.2版本迭代后新增了部分功能&#xff0c;可以创建应用程序的工作副本来修复错误、添加功能&#xff0c;然…

趣学前端 | 综合一波CSS选择器的用法

背景 最近睡前习惯翻会书&#xff0c;重温了《HTML5与CSS 3权威指南》。这本书&#xff0c;分上下两册&#xff0c;之前读完了上册&#xff0c;下册基本没翻过。为了对得起花过的每一分钱&#xff0c;决定拾起来近期读一读。 CSS 选择器 在CSS3中&#xff0c;提倡使用选择器…

大模型生成RAG评估数据集并计算hit_rate 和 mrr

文章目录 背景简介代码实现公开参考资料 背景 最近在做RAG评估的实验&#xff0c;需要一个RAG问答对的评估数据集。在网上没有找到好用的&#xff0c;于是便打算自己构建一个数据集。 简介 本文使用大模型自动生成RAG 问答数据集。使用BM25关键词作为检索器&#xff0c;然后…

AI图片智能选区抠像解决方案

高质量的图片处理往往依赖于繁琐的手动操作&#xff0c;耗费大量时间与精力。美摄科技推出了一款革命性的AI图片智能选区抠像解决方案&#xff0c;旨在帮助企业轻松实现图片的高效处理&#xff0c;提升内容创作效率与质量。 美摄科技的AI图片智能选区抠像解决方案&#xff0c;…

An Aspect-Based Engine

GPU Pro 译&#xff1a; By 王钰涵 2024 4.14 10.1 Introduction&#xff08;简介&#xff09; 引擎的定义在整个行业中有所不同。在最基本的层面上&#xff0c;该术语描述了一个代码库&#xff0c;它在多个项目中提供共同的功能。其目的是分享开发这些功能所需的资源成本…

知网参考文献引用格式转latex中BibTex-Python操作

处理思路 参考 处理步骤&#xff1a; &#xff08;单条处理&#xff1a;&#xff09; 1、选知网NoteExpress格式的2-7行复制信息 2、新建一个文本文件&#xff0c;命名为cite.txt&#xff0c;把知网所复制信息粘贴进来 &#xff08;txt文件保存编码ANSI可行&#xff09; 3、…

GD32F470_TTP224 4路 电容式 触摸开关 数字触摸传感器模块移植

2.8 TTP224触摸传感器 该模块是一个基于触摸检测IC(TTP223B)的电容式点动型触摸开关模块。常态下&#xff0c;模块输出低电平&#xff0c;模式为低功耗模式&#xff1b;当用手指触摸相应位置时&#xff0c;模块会输出高电平&#xff0c;模式切换为快速模式;当持续12秒没有触摸时…

C#智慧手麻系统源码 医院手术麻醉系统源码 支持三甲医院评级需求 可提供演示

C#智慧手麻系统源码 医院手术麻醉系统源码 支持三甲医院评级需求 可提供演示 手术麻醉管理系统是应用于医院手术室、麻醉科室的计算机软件系统。该系统针对整个围术期&#xff0c;对病人进行全程跟踪与信息管理&#xff0c;自动集成病人HIS、LIS、RIS、PACS信息&#xff0c;采…

吃豆豆 经典的区间DP 好题典题

这里很巧妙的注意一点是&#xff0c;你最后要把所有的豆子都吃掉&#xff0c;所以你只要看你多增加的尽量的少就好了 然后维护一段区间&#xff0c;表示的是吃掉这段区间里面的所有豆子的最小代价&#xff0c;然后发现最后一个是左端点或者右端点 你吃一段新的区间的同时会把…

c++的学习之路:11、string(3)

昨天写string的时候没有说全&#xff0c;这里就开始接着讲。 目录 一、resize 二、insert 三、erase 一、resize 昨天说这个的时候没有考虑到缩小范围时咋处理&#xff0c;然后发现报错了&#xff0c;接着我调试发现缩小就不能正常执行了&#xff0c;因为用的是strcap所以…

有关字符串算法

例题一 解法&#xff1a; 算法思路&#xff08;两两⽐较&#xff09;&#xff1a; 我们可以先找出前两个的最⻓公共前缀&#xff0c;然后拿这个最⻓公共前缀依次与后⾯的字符串⽐较&#xff0c;这样就可以找出所有字符串的最⻓公共前缀。 例题二 解法&#xff08;中⼼扩散&am…

UNIAPP(小程序)每十个文章中间一个广告

三十秒刷新一次广告 ad-intervals"30" <template><view style"margin: 30rpx;"><view class"" v-for"(item,index) in 100"><!-- 广告 --><view style"margin-bottom: 20rpx;" v-if"(inde…

win10电脑无线网卡优化

近期win10会频繁断网&#xff0c;无任何规律。目前整理搜索后使用以下两种方法优化网卡&#xff0c;更改配置后断网问题得到有效改善。 方法一&#xff1a;在【电源管理】中取消勾选【允许计算机关闭此设备以节约电源】 方法二&#xff1a;【Preferred enable】修改为prefer 5…

R语言数据操纵:常用函数

这篇文章主要介绍R语言中处理循环&#xff0c;排序&#xff0c;总结重要信息的常用函数。 处理循环的函数 lapply函数 这个函数就是俗称的一句话循环函数&#xff0c;不同于while循环或者for循环&#xff0c;这个函数可以实现一句话就是一个循环的效果。 具体格式为lapply(…