Java---反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,
都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

在编译后产生字节码文件的时候,类加载器子系统通过二进制字节流,负责从文件系统加载class文件。
在执行程序(java.exe)时候,将字节码文件读入JVM中--->这个过程叫做类的加载。然后在内存中对应创建一个java.lang.Class对象-->这个对象会被放入字节码信息中,这个Class对象,就对应加载那个字节码信息,这个对象将被作为程序访问方法区中的这个类的各种数据的外部接口。
所以:我们可以通过这个对象看到类的结构,这个对象就好像是一面镜子,透过镜子看到类的各种信息,我们形象的称之为反射
这种“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

说明:在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。
如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。

补充:
动态语言vs静态语言
1、动态语言
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以
被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运
行时代码可以根据某些条件改变自身结构。
主要动态语言: Object-C、 C#、JavaScript、 PHP、 Python、 Erlang 。
2、静态语言
与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、
C++。

所以Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动
态性,我们可以利用反射机制、字节码操作  获得类似动态语言的特性。
Java的动态性让编程的时候更加灵活! 

 Class类的理解

 获取运行时类的完整结构

1、获取构造器和创建对象

package com.zhaoss.test03;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test01 {public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {//获取字节码信息:Class cls = Student.class;//通过字节码信息可以获取构造器://getConstructors只能获取当前运行时类的被public修饰的构造器Constructor[] c1 = cls.getConstructors();1for(Constructor c:c1){System.out.println(c);}System.out.println("-------------------");//getDeclaredConstructors:获取运行时类的全部修饰符的构造器Constructor[] c2 = cls.getDeclaredConstructors();for(Constructor c:c2){System.out.println(c);}System.out.println("-------------------");//获取指定的构造器://得到空构造器Constructor con1 = cls.getConstructor();System.out.println(con1);//得到两个参数的有参构造器:Constructor con2 = cls.getConstructor(double.class, double.class);System.out.println(con2);//得到一个参数的有参构造器:并且是private修饰的Constructor con3 = cls.getDeclaredConstructor(int.class);System.out.println(con3);//有了构造器以后我就可以创建对象:Object o1 = con1.newInstance();System.out.println(o1);Object o2 = con2.newInstance(180.5, 170.6);System.out.println(o2);}
}

2、获取属性和对属性进行赋值

package com.zhaoss.test03;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Test02 {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {//获取运行时类的字节码信息:Class cls = Student.class;//获取属性://getFields:获取运行时类和父类中被public修饰的属性Field[] fields = cls.getFields();for(Field f:fields){System.out.println(f);}System.out.println("---------------------");//getDeclaredFields:获取运行时类中的所有属性Field[] declaredFields = cls.getDeclaredFields();for(Field f:declaredFields){System.out.println(f);}System.out.println("---------------------");//获取指定的属性:Field score = cls.getField("score");System.out.println(score);Field sno = cls.getDeclaredField("sno");System.out.println(sno);System.out.println("---------------------");//属性的具体结构://获取修饰符/*int modifiers = sno.getModifiers();System.out.println(modifiers);System.out.println(Modifier.toString(modifiers));*/System.out.println(Modifier.toString(sno.getModifiers()));//获取属性的数据类型:Class clazz = sno.getType();System.out.println(clazz.getName());//获取属性的名字:String name = sno.getName();System.out.println(name);System.out.println("-------------------------------");//给属性赋值:(给属性设置值,必须要有对象)Field sco = cls.getField("score");Object obj = cls.newInstance();sco.set(obj,98);//给obj这个对象的score属性设置具体的值,这个值为98System.out.println(obj);}
}

3、获取方法和调用方法

package com.zhaoss.test03;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test03 {public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {//获取字节码信息:Class cls = Student.class;//获取方法://getMethods:获取运行时类的方法还有所有父类中的方法(被public修饰)Method[] methods = cls.getMethods();for(Method m:methods){System.out.println(m);}System.out.println("-----------------------");//getDeclaredMethods:获取运行时类中的所有方法:Method[] declaredMethods = cls.getDeclaredMethods();for(Method m:declaredMethods){System.out.println(m);}System.out.println("-----------------------");//获取指定的方法:Method showInfo1 = cls.getMethod("showInfo");System.out.println(showInfo1);Method showInfo2 = cls.getMethod("showInfo", int.class, int.class);System.out.println(showInfo2);Method work = cls.getDeclaredMethod("work",int.class);System.out.println(work);System.out.println("-----------------------");//获取方法的具体结构:/*@注解修饰符 返回值类型  方法名(参数列表) throws XXXXX{}*///名字:System.out.println(work.getName());//修饰符:int modifiers = work.getModifiers();System.out.println(Modifier.toString(modifiers));//返回值:System.out.println(work.getReturnType());//参数列表:Class[] parameterTypes = work.getParameterTypes();for(Class c:parameterTypes){System.out.println(c);}//获取注解:Method myMethod = cls.getMethod("myMethod");Annotation[] annotations = myMethod.getAnnotations();for(Annotation a:annotations){System.out.println(a);}//获取异常:Class[] exceptionTypes = myMethod.getExceptionTypes();for(Class c:exceptionTypes){System.out.println(c);}//调用方法:Object o = cls.newInstance();myMethod.invoke(o);//调用o对象的mymethod方法System.out.println(showInfo2.invoke(o,12,45));;}
}

4、获取类的接口,所在包,注解

package com.zhaoss.test03;
import java.lang.annotation.Annotation;
public class Test04 {public static void main(String[] args) {//获取字节码信息:Class cls = Student.class;//获取运行时类的接口:Class[] interfaces = cls.getInterfaces();for(Class c:interfaces){System.out.println(c);}//得到父类的接口://先得到父类的字节码信息:Class superclass = cls.getSuperclass();//得到接口:Class[] interfaces1 = superclass.getInterfaces();for(Class c:interfaces1){System.out.println(c);}//获取运行时类所在的包:Package aPackage = cls.getPackage();System.out.println(aPackage);System.out.println(aPackage.getName());//获取运行类的注解:Annotation[] annotations = cls.getAnnotations();for(Annotation a:annotations){System.out.println(a);}}
}

总结

  • 反射机制是一项强大的功能,允许开发者动态地操作类和对象,增强了代码的灵活性。
  • Java 本身是静态语言,但通过反射机制,能够在某些方面具备动态语言的特性。
  • 反射提供了对类结构的深入访问,开发者可以通过它获取和操作类的各种信息,为框架设计和工具开发提供了强大的支持。

反射虽然带来灵活性,但也可能引入性能开销和安全风险,因此需要谨慎使用。

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

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

相关文章

Java 线程状态详解

1 引言 在 Java 多线程编程中,线程的状态是一个非常重要的概念。了解线程的状态及其转换过程,有助于我们更好地理解和控制线程的行为。本文将详细介绍 Java 线程的 6 种状态,并通过示例代码和图解来帮助读者更好地理解这些状态及其转换过程。…

AirScreen 安卓平板作为MacOS副屏

前言: 对笔记本续航有刚需,不得不选MacBook。 手机用的是mate40Pro,平板用的是matepad pro 12.6 干货: 参考网友的分享: https://www.bilibili.com/video/BV12A4y1d7zX/?spm_id_from333.337.search-card.all.click 【…

深度强化学习(RL)介绍

深度强化学习(RL)介绍 写到了一半,图待后补 一、强化学习概述 (一)与监督学习对比及定义 强化学习不同于监督学习,在一些任务中数据标注困难,但机器可通过环境反馈知道结果好坏。强化学习是机…

使用 Elasticsearch 构建食谱搜索(二)

这篇文章是之前的文章 “使用 Elasticsearch 构建食谱搜索(一)” 的续篇。在这篇文章中,我将详述如何使用本地 Elasticsearch 部署来完成对示例代码的运行。该项目演示了如何使用 Elastic 的 ELSER 实现语义搜索并将其结果与传统的词汇搜索进…

数据结构 【带环单链表】

在单链表中可能会存在一种情况,某一结点在经过几次转移之后回到了自己本身,这种情况就称之为带环链表。对于带环链表,我们不能轻易对其进行遍历,遍历可能会导致产生死循环。 带环链表的逻辑图如下所示:(这…

Vue 项目中如何使用FullCalendar 时间段选择插件(类似会议室预定、课程表)

本文中是基于VUEelementui项目中实现的前后端分离的前端功能部分: 插件的官方文档:FullCalendar 1.安装对应依赖(统一安装版本为6.15) npm install --save fullcalendar/core6.15 npm install --save fullcalendar/daygrid6.…

学习路之压力测试--jmeter安装教程

Jmeter安装 0、先安装jdk:这里是安装jdk-8u211-windows-x64 1、百度网盘上下载 jdk和jmeter 链接: https://pan.baidu.com/s/1qqqaQdNj1ABT1PnH4hfeCw?pwdkwrr 提取码: kwrr 复制这段内容后打开百度网盘手机App,操作更方便哦 官网:Apache JMeter - D…

SQL99版全外连接和交叉连接和总结

全外连接MySQL不支持 elect 查询列表 from 表名1 表别名1 cross join 表名2 表别名2 on 连接条件 ...... ; 交叉连接 就两个记录做笛卡尔积!没什么好说的,基本也没用过! 总结

Python爬虫:深入探索1688关键词接口获取之道

在数字化经济的浪潮中,数据的价值愈发凸显,尤其是在电商领域。对于电商平台而言,关键词不仅是搜索流量的入口,也是洞察市场趋势、优化营销策略的重要工具。1688作为中国领先的B2B电商平台,其关键词接口的获取对于商家来…

ffmpeg本地编译不容易发现的问题 — Error:xxxxx not found!

这里区分电脑CPU架构 本次编译是在Mac笔记本,M1芯片上进行! 前面大致流程:分为两种(1.仅适用,直接下载编译好的本地安装即可;2.使用并查看源码,自己修改编译运行)。这里介绍的是第…

从0-1逐步搭建一个前端脚手架工具并发布到npm

前言 本文介绍的案例已同步到github,github地址。 vue-cli 和 create-react-app 等 cli 脚手架工具用于快速搭建应用,无需手动配置复杂的构建环境。本文介绍如何使用 rollup 搭建一个脚手架工具。 脚手架工具的工作流程简言为:提供远端仓库…

摄影:相机控色

摄影:相机控色 白平衡(White Balance)白平衡的作用: 白平衡的使用环境色温下相机色温下总结 白平衡偏移与包围白平衡包围 影调 白平衡(White Balance) 人眼看到的白色:会自动适应环境光线。 相…

键盘党福音!自定义指令实现回车快捷删除

前言 📫 大家好,我是南木元元,热爱技术和分享,欢迎大家交流,一起学习进步! 🍅 个人主页:南木元元 目录 确认对话框 回车键快捷确认 自定义指令实现回车删除 实现思路 实现代码 …

AG32既可以做MCU,也可以仅当CPLD使用

Question: AHB总线上的所有外设都需要像ADC一样,通过cpld处理之后才能使用? Reply: 不用。 除了ADC外,其他都是 mcu可以直接配置使用的。 Question: DMA和CMP也不用? Reply: DMA不用。 ADC/DAC/CMP 用。 CMP 其实配置好后,可以直…

深度学习实战人脸识别

文章目录 前言一、人脸识别一般过程二、人脸检测主流算法1. MTCNN2. RetinaFace3. CenterFace4. BlazeFace5. YOLO6. SSD7. CascadeCNN 三、人脸识别主流算法1.deepface2.FaceNet3.ArcFace4.VGGFace5.DeepID 四、人脸识别系统实现0.安装教程与资源说明1. 界面采用PyQt5框架2.人…

macOS 的目录结构

文章目录 根目录 (/)常见目录及其用途示例目录结构注意事项根目录 (/)主要目录及其含义其他目录总结 macOS 的目录结构无论是在 Intel 架构还是 ARM 架构的 Mac 电脑上都是相同的。macOS 的目录结构遵循 Unix 和 BSD 的传统,具有许多标准目录。以下是一些主要目录及…

003 STM32基础、架构以及资料介绍——常识

注: 本笔记参考学习B站官方视频教程,免费公开交流,切莫商用。内容可能有误,具体以官方为准,也欢迎大家指出问题所在。 01什么是STM32(宏观) STM32属于一个微控制器,自带了各种常用通…

aws凭证(一)凭证存储

AWS 凭证用于验证身份,并授权对 DynamoDB 等等 AWS 服务的访问。配置了aws凭证后,才可以通过编程方式或从AWS CLI连接访问AWS资源。凭证存储在哪里呢?有以下几个方法: 一、使用文件存储 1、介绍 文件存储适用于长期和多账户配置…

力扣面试经典 150(上)

文章目录 数组/字符串1. 合并两个有序数组2. 移除元素3. 删除有序数组中的重复项4. 删除有序数组的重复项II5. 多数元素6. 轮转数组7. 买卖股票的最佳时机8. 买卖股票的最佳时机II9. 跳跃游戏10. 跳跃游戏II11. H 指数12. O(1)时间插入、删除和获取随机元素13. 除自身以外数组的…