【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.类名.classClass 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....

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

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

相关文章

动规训练3

一、按摩师 1、题目解析 简而言之就是&#xff0c;找到一个按摩师的预约总是长的最长方案&#xff0c;还有一个限制条件&#xff0c;选取的预约两两不相邻。 2、算法原理 a状态表示方程 小技巧&#xff1a;经验题目要求 dp[i]表示以这个节点为结尾&#xff0c;最长的预约时…

Calico IPIP和BGP TOR的数据包走向

IPIP Mesh全网互联 文字描述 APOD eth0 10.7.75.132 -----> APOD 网关 -----> A宿主机 cali76174826315网卡 -----> Atunl0 10.7.75.128 封装 ----> Aeth0 10.120.181.20 -----> 通过网关 10.120.181.254 -----> 下一跳 BNODE eth0 10.120.179.8 解封装 --…

哈佛大学商业评论 --- 第四篇:一家公司的AR经验

AR将全面融入公司发展战略&#xff01; AR将成为人类和机器之间的新接口&#xff01; AR将成为人类的关键技术之一&#xff01; 请将此文转发给您的老板&#xff01; --- 专题作者&#xff1a;Michael E.Porter和James E.Heppelmann 虽然物理世界是三维的&#xff0c;但大多…

LeetCode每日一题之专题一:双指针 ——快乐数

快乐数OJ链接&#xff1a;202. 快乐数 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 题目分析: 为了房便叙述&#xff0c;将「对于⼀个正整数&#xff0c;每⼀次将该数替换为它每个位置上的数字的平方和」这⼀个 操作记为 x 操作&#xff1b; 题目告诉我们&#…

什么是原生IP?原生IP的作用是什么?

原生IP&#xff08;Native IP&#xff09;是指直接从互联网服务提供商&#xff08;ISP&#xff09;获得的IP地址&#xff0c;而非通过代理服务器、VPN或其他中间层方式获取。这种IP地址直接与用户的设备或网络关联&#xff0c;无需经过任何中间服务器或代理的转发或隐藏&#x…

如何才能实现基坑自动化监测?

基坑自动化监测是一个系统性的过程&#xff0c;它涉及对基坑整体情况的全面了解和分析&#xff0c;确定监测指标&#xff0c;选择合适的监测传感器并进行安装和调试&#xff0c;配置相应的数据采集、传输和管理软件系统&#xff0c;以及进行系统的调试、定期维护和数据分析。以…

uni-app调用苹果登录,并获取用户信息

效果 模块配置 dev中的配置 需要开启登录的权限&#xff0c;然后重新下载配置文件&#xff0c;发布打包基座&#xff0c;再运行程序 代码 <button click"appleLogin">苹果登录</button>function appleLogin() {uni.login({provider: apple,success: …

免版权素材库:在营销和宣传中的重要性与应用

title: 免版权素材库&#xff1a;在营销和宣传中的重要性与应用 date: 2024/4/5 18:21:43 updated: 2024/4/5 18:21:43 tags: 免版权素材库营销宣传高质量素材节省成本避免侵权创意启发数字营销 免版权素材库在宣传和营销中的重要性不言而喻。在当今数字化时代&#xff0c;图片…

html5如何在使用原生开发的情况下实现组件化

我们知道如何在vue/react中使用组件化开发&#xff0c;那么如果只是一个简单的界面&#xff0c;一个HTML就搞定的事情&#xff0c;你还会去新建一个vue/react项目吗&#xff1f; 在使用原生HTML开发时&#xff0c;我们也会遇到一些常见的功能、模块&#xff0c;那么如何在原生…

Flask-RESTful 分析

Flask-RESTful 是一个 Flask 扩展&#xff0c;它为构建 RESTful API 提供了方便的工具和资源。它简化了创建 RESTful 服务的过程&#xff0c;允许开发者专注于业务逻辑而不是 HTTP 协议的细节。 资源&#xff08;Resources&#xff09;&#xff1a; Resource 类&#xff1a;是…

WIFI|软体 茶凳浅谈 高通WIN QSDK - IPQ6000 与 88Q2112 的相遇

Qualcomm IPQ 系列的Ethernet IC 搭配的有 QCA8075, QCA8081 … 等等Qualcomm自家出产的芯片。QSDK中内建可以支持的3rd party芯片&#xff0c;却寥寥可数。日前&#xff0c;客户使用车载以太网 - 88Q2112 - Marvell与IPQ6000做搭配。将之记录下来&#xff0c;以供参考。 方…

程序员延寿指南:科学延寿 20 年 | 开源日报 No.214

geekan/HowToLiveLonger Stars: 28.7k License: Unlicense HowToLiveLonger 是一个程序员延寿指南项目。 该项目旨在提供关于如何延长寿命的指南&#xff0c;特别是针对程序员群体。该项目包括术语、目标、关键结果、分析、行动和证据等内容&#xff0c;涵盖了各种与健康相关的…