Java中的反射机制详解

反射的简单demo

  1. 声明的原始类
    class Cat {private String name = "猫猫";public int age = 10;public Cat(){}public Cat(String name) {this.name = name;}public void hi() {System.out.println("hi~ " + name);}public void hi() {System.out.println(name + " cry");}
    }
    
  2. src目录下的配置文件re.properties
    classfullpath=com.zhl.Cat
    method=hi
    
  3. 编写反射代码
    public class Reflection01 {public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {// 加载配置文件中的信息Properties properties = new Properties();InputStream inputStream = ReflectionQuestion.class.getClassLoader().getResourceAsStream("re.properties");properties.load(inputStream);String classfullpath = properties.getProperty("classfullpath");String methodName = properties.getProperty("method");// 使用反射创建对象Class<?> aClass = Class.forName(classfullpath);Object o = aClass.newInstance();System.out.println(o.getClass());// 通过反射获取成员方法Method method = aClass.getMethod(methodName);method.invoke(o);// 通过反射获取成员变量(不能获取私有的)Field ageField = aClass.getField("age");System.out.println(ageField.get(o));// 通过反射获取构造器// 无参Constructor<?> constructor = aClass.getConstructor();System.out.println(constructor);// 有参Constructor<?> constructor2 = aClass.getConstructor(String.class);System.out.println(constructor2);}
    }
    

反射机制和传统调用方法的对比

public class Reflection02 {public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {m1();m2();}// 传统方法:直接创建对象public static void m1() {Cat cat = new Cat();long begin = System.currentTimeMillis();for (int i = 0; i < 1000000; i++) {cat.hi();}long end = System.currentTimeMillis();System.out.println("传统方案耗时:" + (end - begin) + "ms");}// 反射机制调用方法public static void m2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class<?> aClass = Class.forName("com.zhl.Cat");// 无参构造Constructor<?> constructor = aClass.getConstructor();// 关闭访问检查的开关constructor.setAccessible(true);Object o = constructor.newInstance();Method method = aClass.getMethod("hi");method.setAccessible(true);long begin = System.currentTimeMillis();for (int i = 0; i < 1000000; i++) {method.invoke(o);}long end = System.currentTimeMillis();System.out.println("使用反射方案耗时:" + (end - begin) + "ms");}
}

反射的优点和缺点:

  • 优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活。
  • 缺点:使用反射基本是解释执行,对执行速度有影响。

Class类

Class类的对象不是new出来的,是系统创建的,在类加载阶段生成的。
对于某个类的Class类对象,类只加载一次,在内存中只有一份。
每个类的实例都会记得自己是由哪个 Class 实例所生成。

  • 已知一个类的全类名 ,且该类在类路径下,可通过Class类的静态方法forName()获取
    • 应用场景:通过配置文件读取类的全路径,加载类
    String className;
    Class<?> clazz = Class.forName(className);
    
  • 若已知具体的类,通过 类的class获取,该方式最为安全可靠,程序性能最高
    • 应用场景:多用于参数传递,比如通过反射得到对应构造器对象
    Class<Cat> cat = Cat.class;
    
  • 已知某个类的实例,调用该实例的getClass()方法获取Class对象,实例:
    • 应用场景:通过创建好的对象,获取Class对象
    // 运行类型
    Class clazz = 对象.getClass();	
    
  • 其他方式
    获取类加载器,加载指定类 。
    ClassLoader loader =.class.getClassLoader();	
    Class<?> clazz = loader.loadClass("com.zhl.Cat");
    

类加载

  • 基本说明
    反射机制是 java实现动态语言的关键,也就是通过反射实现类动态加载

    1. 静态加载:编译时加载相关的类,如果没有则报错。
      依赖性太强
    2. 动态加载:运行时加载需要的类,如果运行时不用该类,则不报错。
      降低了依赖性
    3. 举例说明 (伪代码)
    String key = scan.next();
    switch(key) {case "1" : Dog dog = new Dog();dog.hi();break;case "2":Class<?> clazz = Class.forName("Person");Object o = clazz.newInstance();Method methodName = clazz.getMethod("hi");method.invoke(o);break;default:break;
    }
    

    注意这段代码中,并没有创建 DogPerson类(当前module中没有Dog或Person类),但是编译时,只会报 Dog 类没有创建,而Person类并没有监测出来是否被创建,只有真正被执行到这行代码时才会被加载,判断是否创建过Person类。

  • 类加载时机

    1. 当创建对象时(new)
    2. 当子类被加载时,父类也加载
    3. 调用类中的静态成员时
    4. 通过反射(动态加载)

    关于JVM的类加载可参考https://blog.csdn.net/m0_72406127/article/details/137058092?spm=1001.2014.3001.5501

通过反射获取类的结构信息

  • java.lang.Class

    1. getName:获取全类名
    2. getSimpleName:获取简单类名
    3. getFields:获取所有public修饰的属性,包含本类以及父类的
    4. getDeclaredFields:获取本类中所有属性
    5. getMethods:获取所有public修饰的方法,包含本类以及父类的
    6. getDeclaredMethods:获取本类中所有方法
    7. getConstructors:获取所有public修饰的构造器,包含本类
    8. getDeclaredConstructors:获取本类中所有构造器
    9. getPackage:以Package形式返回包信息
    10. getSuperClass:以Class形式返回父类信息
    11. getInterfaces:以Class[]形式返回接口信息
    12. getAnnotations:以Annotation[]形式返回注解信息
  • java.lang.reflect.Field

    1. getModifiers: 以int形式返回修饰符
      默认修饰符是0,public 是 1,private 是 2,protected 是 4,static 是 8 ,final是 16,多个不同的修饰符可以相加
    2. getType:以Class形式返回类型
    3. getName:返回属性名
  • java.lang.reflect.Method

    1. getModifiers:以int 形式返回修饰符
    2. getName:返回方法名
    3. getReturnType:以Class形式获取 返回类型
    4. getParameterTypes:以Class[]返回参数类型数组
  • java.lang.reflect.Constructor

    1. getModifiers: 以int形式返回修饰符
    2. getName:返回构造器名(全类名)
    3. getParameterTypes:以Class[]返回参数类型数组

通过反射创建对象

  • 方式一:调用类中的publi 修饰的无参构造器
  • 方式二:调用类中的指定构造器
  • Class类相关方法
    • newlnstance:调用类中的无参构造器,获取对应类的对象
    • getConstructor(Class…clazz):根据参数列表,获取对应的public构造器对象
    • getDeclaredConstructor(Class…clazz):根据参数列表,获取对应的所有构造器 对象
  • Constructor类相关方法
    • setAccessible: 设为true,可以访问private修饰的构造器
    • newinstance(Object…obj): 调用构造器

在构造器/方法/属性中使用 getDeclaredXxx方法可以获取本类中的所有构造器/方法/属性,
通过setAccessible()方法,设置参数为true,关闭访问检查的开关,就可以直接访问和修改被 private 修饰的构造器/方法/属性。

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

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

相关文章

基于达梦数据库开发-C#篇

文章目录 前言一、相关准备二、主要代码1.引入达梦类库2.连接达梦数据库3.DmCommand方式获取达梦数据库信息4.DmDataAdapter方式获取达梦数据库信息 总结 前言 达梦数据库是国产的新一代大型通用关系型数据库&#xff0c;全面支持 SQL 标准和主流编程语言接口/开发框架。其中.…

OpenHarmony实战开发-如何利用panel实现底部面板内嵌套列表。

介绍 本示例主要介绍了利用panel实现底部面板内嵌套列表&#xff0c;分阶段滑动效果场景。 效果图预览 使用说明 点击底部“展开”&#xff0c;弹出panel面板。在panel半展开时&#xff0c;手指向上滑动panel高度充满页面&#xff0c;手指向下滑动panel隐藏。在panel完全展开…

浏览器工作原理与实践--浏览上下文组:如何计算Chrome中渲染进程的个数

经常有朋友问到如何计算Chrome中渲染进程个数的问题&#xff0c;那么今天就来完整地解答这个问题。 在前面“04 | 导航流程”这一讲中我们介绍过了&#xff0c;在默认情况下&#xff0c;如果打开一个标签页&#xff0c;那么浏览器会默认为其创建一个渲染进程。不过我们在“04 |…

Echarts-知识图谱

Echarts-知识图谱 demo地址 打开CodePen 效果 思路 1. 生成根节点 2. 根据子节点距离与根节点的角度关系&#xff0c;生成子节点坐标&#xff0c;进而生成子节点 3. 从子节点上按角度生成对应的子节点 4. 递归将根节点与每一层级子节点连线核心代码 定义节点配置 functio…

1011 A+B 和 C

给定区间 [−2^31,2^31] 内的 3 个整数 A、B 和 C&#xff0c;请判断 AB 是否大于 C。 输入格式&#xff1a; 输入第 1 行给出正整数 T (≤10)&#xff0c;是测试用例的个数。随后给出 T 组测试用例&#xff0c;每组占一行&#xff0c;顺序给出 A、B 和 C。整数间以空格分隔。…

基于springboot实现车辆管理系统设计项目【项目源码+论文说明】计算机毕业设计

基于springboot实现车辆管理系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了车辆管理系统的开发全过程。通过分析车辆管理系统管理的不足&#xff0c;创建了一个计算机管理车辆管理系统的方案。文章介…

Linux查看cache工具

参考&#xff1a;Linux cache占用大量内存&#xff0c;如何分析是哪些进程、文件导致&#xff1f; 查看cache工具 工具fincorepcstathcachevmtouch说明该工具最初发布于googlecode&#xff0c;但googlecode现在已经关闭了。可以从github上找到其代码。很多工具基于该工具二次…

【数据结构】分块查找

分块查找&#xff08;也称为索引顺序查找&#xff09;是一种改进的顺序查找方法&#xff0c;它将查找表分成若干个块&#xff0c;并要求块内的元素有序排序&#xff0c;但块与块之间不要求有序。每个块内的最大元素构成一个索引表。分块查找的过程是先查找索引&#xff0c;确定…

黑洞路由、 DDoS 攻击 、 环路

黑洞路由 DDoS 攻击 DDoS 攻击是一种针对服务器、服务或网络的恶意行为。DDoS 攻击通过向目标发送大量流量&#xff0c;使其不堪重负&#xff0c;导致资源和带宽被耗尽。因此&#xff0c;目标可能会变慢或崩溃&#xff0c;无法正常处理合法的流量。DDoS 攻击通常是由僵尸网络…

在龙梦迷你电脑福珑2.0上使用Fedora 28 龙梦版

在龙梦迷你电脑福珑2.0上使用Fedora 28 龙梦版。这个版本的操作系统ISO文件是&#xff1a;Fedora28_for_loongson_MATE_Live_7.2.iso 。它在功能方面不错。能放音乐&#xff0c;能看cctv直播&#xff0c;有声音&#xff0c;能录屏&#xff0c;能在局域网里用PuTTY的ssh方式连接…

嵌入式学习——C语言基础——day5

1. 分支结构——switch 1.1 单层switch switch (整形表达式) { case 常量1:语句块1;break; case 常量2:语句块2;break; case 常量3:语句块3;break; default: 语句块4; } 注意&#xff1a; 1. 表达式必须…

《苏东坡 传》一蓑烟雨任平生

《苏东坡 传》一蓑烟雨任平生 林语堂&#xff0c;中国现代著名作家、学者、翻译家、语言学家。 张振玉 译 文章目录 《苏东坡 传》一蓑烟雨任平生[toc]摘录小结感悟 摘录 苏东坡是个秉性难改的乐天派&#xff0c;是悲天悯人的道德家&#xff0c;是黎民百姓的好朋友&#xff0c;…

C语言C/S架构PACS影像归档和通信系统源码 医院PACS系统源码

C语言C/&#xff33;架构PACS影像归档和通信系统源码 医院PACS系统源码 医院影像科PACS系统&#xff0c;意为影像归档和通信系统。它是应用在医院影像科室的系统&#xff0c;主要的任务是把日常产生的各种医学影像&#xff08;包括核磁、CT、超声、各种X光机、各种红外仪、显微…

JAVA ASM总结篇-03

MethodVisitor ClassVisitor的visitMethod能够访问到类中某个方法的一些入口信息&#xff0c;那么针对具体方法中字节码的访问是由MethodVisitor来进行的 访问顺序如下&#xff0c;其中visitCode和visitMaxs仅调用一次&#xff0c;标志方法字节码访问的开始和结束 MethodVisi…

不羁联盟怎么参与测试 不羁联盟测试时间+参与测试方法分享

不羁联盟怎么参与测试 不羁联盟测试时间参与测试方法分享 《不羁联盟》是由育碧&#xff08;Ubisoft&#xff09;开发的一款6v6团队合作射击游戏。游戏的背景设定在一个后启示录时代的废土世界中&#xff0c;玩家能够身临其境地感受到废土世界的荒凉和残酷。游戏在内测时候就受…

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台级联时,下级平台未发流是什么原因?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

AUTOCAD输出或打印PDF文件时,如何将图形居中且布满图纸?

AUTOCAD输出或打印PDF文件时,如何将图形居中且布满图纸? 如下图所示,我们打开一份DWG格式的图纸文件,然后点击上方的“打印“图标, 如下图所示, 打印机/绘图仪这里选择“DWG To PDF“; 图纸尺寸:这里以普通的A4纸为例进行说明; 打印比例选择“布满图纸“; 打印偏移…

优维应用级数字化架构管理:让企业运维天堑变通途

在优维科技的产品视角中&#xff0c;数字化架构管理就像是一门精妙的艺术&#xff0c;它将上层应用模型的业务概念以可视化的方式呈现出来&#xff0c;使得业务逻辑和流程变得更加直观、清晰。我们将这样的管理方式理解为“给企业搭起一座桥梁”——在这座桥梁的搭建过程中&…

express服务器 authorization 前端获取不到的问题

服务器生成token 设置在响应头&#xff0c;但是前端获取不到 const token JWT.generate({ id: new Date().getTime(), userName }, 10s) res.header(Authorization, token) axios.interceptors.response.use((response) > {console.log(response);if (response.data?.co…

破解费用管理迷局,企业费用管理从不止于报销

数字化变革浪潮下&#xff0c;各种企业费用报销软件如雨后春笋般不断涌现&#xff0c;企业报销效率大幅提升&#xff0c;部分财务处理流程得到固化和优化&#xff0c;报销早已不再是企业费时费力的财务难题。那么&#xff0c;企业费用管里如何实现呢&#xff1f; 企业费用贯穿于…