反射及其应用---->2
目录
1.使用类对象
1.1创建对象
1.2使用对象属性
1.3使用方法
2.反射操作数组
3.反射获得泛型
4.类加载器
4.1双亲委派机制
4.2自定义加载器
1.使用类对象
-
通过反射使用类对象,主要体现3个部分
-
创建对象,调用方法,调用属性(存值,取值)
1.1创建对象
利用反射创建对象有两种方式
-
通过构造器创建对象(推荐)
-
通过Class直接创建对象(只支持利用无参构造器创建对象)
Object o = c.newInstance(); //使用无参构造器创建对象Constructor con = c.getConstructor(int.class, int.class);
//A a = new A(10,20);
Object o = con.newInstance(10, 20);
1.2使用对象属性
-
包括使用属性赋值, 使用属性取值。
-
需要先获得要操作的属性对象
Object a1 = c.newInstance();Field n = c.getField("n"); //获得的public的属性n.set(a1,"XXXX");Object value = n.get(a1);
System.out.println(value);
//私有属性,可以通过设置i.setAccessible(true) 实现对私有成员的访问
//注意1: 使用后,建议将其重新锁住 i.setAccessible(false)
//注意2: 强烈不推荐使用该方式操作私有成员,建议通过封装,提供对应的get和set方法。
Field i = c.getDeclaredField("i");
i.setAccessible(true);
i.set(null,100); //传递null,是因为i属性是一个static属性
Object value = i.get(null);
System.out.println(value);
i.setAccessible(false);
-
在jdk1.9之后,对java中的类库做了重新的处理
-
增加了一个模块的功能,成员属于类,类属于包,包属于模块, 模块属于程序
-
包中的类需要export导出,其他模块中的类才可见。
-
包中未导出的类,其他模块中的类不可见,不可引入,不可反射操作
-
当然,可以通过jvm参数配置,使得模块中的内容都可以反射操作。
-
1.3使用方法
反射调用对象的方法,需要先获得对应的Method方法对象
-
获得Method对象时,除了指定方法名,还需要指定方法的参数列表(Class)
-
调用方法时,需要指定所属对象(static方法所属null或Class),需要传递具体的参数值(Object)
Object a = c.newInstance();
Method m = c.getMethod("t1", int.class, int.class);//t1(int,int)
//a.t1(100,200);
Object r = m.invoke(a, 100, 200);
Method m = c.getDeclaredMethod("t2");//t2()
m.setAccessible(true);
m.invoke(a) ;
m.setAccessible(false);
2.反射操作数组
反射操作数组,使用的是Array类
//Object array = new int[5];
//array[1] (取值, 赋值)
Object array = Array.newInstance(int.class, 5);Array.set( array , 0 , 250 );Object value = Array.get(array, 0);
System.out.println(value);int len = Array.getLength(array);
System.out.println(len);
3.反射获得泛型
关于反射获得泛型,有两种操作需求
-
获得类定义时的泛型 T , V , K , E
public static void t1(){Class c = A.class;TypeVariable[] typeParameters = c.getTypeParameters();//类定义时的泛型System.out.println(typeParameters.length);System.out.println(typeParameters[0].getName());
}
2.获得类使用时的泛型,具体的类型 List<String>
public static void t2() throws NoSuchFieldException, NoSuchMethodException {Class c = B.class ;Field a = c.getDeclaredField("a");Type type = a.getGenericType();//一般getGeneric系列,都是用来获得所包含的泛型的。//(属性类型,返回类型,参数类型,父类型,父接口类型)都有该系列方法//Class is a Type //泛型类型,也称为参数化类型 is a Type , 本质是 ParameterizedTypeParameterizedType pt = (ParameterizedType) type;//Type[] pts = pt.getActualTypeArguments(); //获得多个泛型的数组Type rawType = pt.getRawType();//获得泛型类型}
4.类加载器
-
JVM在运行程序时,会使用类加载器,加载(读取)类文件的信息,并对其进行一系列的处理,最终将其存储在方法区,并生成与之对应的Class对象。
-
类信息有不同的情况
-
有我们自己的写的类信息
-
有jdk自带的类信息
-
未来可能还有其他的类信息,如:网络中的类信息,需要加密处理类信息等。
-
-
jdk针对于不同的类信息情况,提供了不同的类加载器,默认有3种
-
BootstrapClassLoader 启动类加载器,使用C/C++实现,加载jdk基本类库,如:java.lang等
-
ExtClassLoader 扩展类加载器,使用Java实现的,加载jdk扩展类库
-
AppClassLoader 应用类加载器,使用Java实现的,classpath路径中的类,我们自己编写的类
-
4.1双亲委派机制
-
jdk提供了3个加载器,未来我们还能自定义加载器
-
jdk同时提供了双亲委派机制,使得多个加载器可以更合理的协作应用
-
当我们在程序中需要使用一个类时,会先向最底层的类加载器申请这个类(app)
-
如果app加载器加载过这个类,就会返回该类的Class对象
-
如果app没有加载过这个类,app会向其父级加载器(ext)申请这个类
-
如果ext加载过就返回这个类,如果没有加载过这个类,继续想起父级(Bootstrap)申请
-
如果bootstrap加载过就返回这个类,如果没有加载过,就尝试加载
-
如果在bootstrap的加载范围内,则加载这个类
-
如果不再bootstrap的加载范围内, 尝试让ext加载
-
如果在ext加载范围内,就让ext加载。如果不在就尝试让app加载
-
如果在app加载范围内,就让app加载,否则就抛出ClassNotFoundException
-
-
注意:app 和 ext 和 bootstrap是逻辑上的子父级关系,不是真正 的extends继承关系
-
双亲委派机制的优点
-
防止核心类被篡改。
-
方式类重复加载
-
防止在核心包中扩展类(沙箱机制)
-
4.2自定义加载器
-
哪些情况需要自定义类加载器呢?
-
扩展加载源 ,如:从网络中加载类库
-
类的隔离
-
类信息的解密
-
-
如何自定义类加载器
-
自定义加载器类, 继承ClassLoader
-
重写方法
-
可以重写
loadClass
方法,但不推荐。因为该方法中提供了双亲委派机制如果重写该方法,相等于破坏了双亲委派机制。
-
可以重写
findClass
方法,根据需求,去指定的地方获取类文件信息以byte[]的形式装载找到的类信息
-
还有一个很重要的方法
defineClass()
,用来将字节码内容进行一系列的处理,并存储在方法区,并生成Class对象所以在findClass之后,一定要调用该方法。
-
-
使用类加载器
-
public class MyClassLoader extends ClassLoader{//name 一般就是com.buka.User 类路径//可以根据这个类路径确定最重要加载的目标类@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {try {Socket link = new Socket("localhost",6666);InputStream is = link.getInputStream();//存储所有读取到的字节信息//本来是需要使用字节数组//但无法确定从网络中读取字节的数量,就不知道要定义多长的字节数组//可以使用ByteArrayOutputStreamByteArrayOutputStream bos = new ByteArrayOutputStream();byte[] bs =new byte[010];while(true){int len = is.read(bs);if(len == -1){break ;}bos.write(bs,0,len);}byte[] content = bos.toByteArray();return super.defineClass("X",content,0,content.length);} catch (IOException e) {throw new RuntimeException(e);}}
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {MyClassLoader loader = new MyClassLoader();Class<?> c = loader.loadClass("X");c.newInstance();
}
相关文章:

反射及其应用---->2
目录 1.使用类对象 1.1创建对象 1.2使用对象属性 1.3使用方法 2.反射操作数组 3.反射获得泛型 4.类加载器 4.1双亲委派机制 4.2自定义加载器 1.使用类对象 通过反射使用类对象,主要体现3个部分 创建对象,调用方法,调用属性ÿ…...

[Python学习日记-32] Python 中的函数的返回值与作用域
[Python学习日记-32] Python 中的函数的返回值与作用域 简介 返回值 作用域 简介 在函数的介绍中我们提到了函数的返回值,当时只是做了简单的介绍,下面我们将会进行详细的介绍和演示,同时也会讲一下 Python 中的作用域,作用域分…...

儿童发光耳勺值得买吗?儿童发光耳勺最建议买的五个牌子!
儿童耳部清洁需谨慎,发光耳勺能在光线不足时提供照明,便于看清耳道。但不同产品质量参差不齐,选择时需综合考虑安全性、实用性等因素,为孩子的耳部健康做出正确选择! 这里给大家总结了全新的儿童发光耳勺的避雷指南&am…...

TIPS 二进制程序暴露符号给动态链接库使用
背景 在支持插件/扩展的C/C系统中,通常会支持在程序运行时加载动态链接库。这时二进制程序会提供一些函数/接口让动态链接库调用,但是这些函数在二进制程序中又不会使用,导致在编译时编译器直接把这些符号删除了,加载链接库就会由…...

【分布式微服务云原生】8分钟掌握微服务通信的艺术:Dubbo与OpenFeign全面解析
摘要: 在构建微服务架构时,服务间的通信机制是核心要素之一。Dubbo和OpenFeign是两个非常流行的服务调用框架,它们各有千秋,适用于不同的场景。本文将深入探讨Dubbo和OpenFeign的主要特点、使用场景以及它们之间的差异,…...

sicp每日一题[2.33]
Exercise 2.33 Fill in the missing expressions to complete the following definitions of some basic list-manipulation operations as accumulations: ; p 表示一个函数,sequence 表示一个列表 ; 这个函数将对列表中每一个元素进行 p 操作 (define (map p sequ…...

【Mybatis】常见面试题汇总 共56题
文章目录 1. 介绍下MyBatis?2. MyBatis 框架的应用场景?3. MyBatis 有哪些优点?4. MyBatis 有哪些缺点?5. MyBatis 用到了哪些设计模式?6. MyBatis常用注解有哪些?7. MyBatis 有哪些核心组件?8. MyBatis编程步骤是什么样的?9. MyBatis 和…...

每天一道面试题(17):服务网格学习笔记
什么是服务网格? 服务网格(Service Mesh)是处理微服务间通信的一种基础设施层。它主要用于解耦服务间的通信与业务逻辑,使开发者可以专注于业务实现。服务网格在微服务架构的演进中扮演了重要角色,特别是在解决服务间…...

【nrm】npm 注册表管理器
nrm是什么 nrm(NPM Registry Manager)是一个用于管理 Node.js 包管理器(如 npm 和 Yarn)的注册表工具。它可以帮助用户快速切换不同的 npm 源,以便于提高包安装的速度和效率,特别是在中国大陆地区…...

解压短视频素材资源网站推荐
如果你正在寻找解压短视频素材,那么这篇文章正是为你而写!以下是一些热门的网站,帮助你轻松找到所需的素材,快来看看吧! 蛙学网 蛙学网是国内领先的视频素材网站,提供丰富的解压视频素材。无论是放松心情的…...

Qemu开发ARM篇-6、emmc/SD卡AB分区镜像制作并通过uboot进行挂载启动
文章目录 1、AB分区镜像制作2、uboot修改3、镜像启动 在上一篇 Qemu开发ARM篇-5、buildroot制作根文件系统并挂载启动中,我们通过buildroot制作了根文件系统,并通过 SD卡的形式将其挂载到设备并成功进行了启动,但上一章中,我们的…...

Spring Boot中使用ThreadPoolTaskScheduler实现轻量级多线程定时任务
引言 在Java开发中,Spring Boot提供了多种方式来执行定时任务,如Scheduled注解和TaskScheduler。当需要执行多线程定时任务时,ThreadPoolTaskScheduler是一个轻量级的解决方案。本文将通过一个具体的业务场景,介绍如何使用Thread…...

完全二叉树的节点个数 C++ 简单问题
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。 示例 1ÿ…...

每日一题学习笔记
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以,返回 true ;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次。 示例 1: 输入&#…...

从事人工智能学习Python还是学习C++?
人工智能(Artificial Intelligence,简称AI)是当今科技领域最热门的研究方向之一。AI 涉及多个学科和技术,特别是机器学习、神经网络、深度学习等技术的应用。在AI的开发过程中,编程语言的选择对于开发效率和项目实现至…...

博客摘录「 CNN中的感受野和有效感受野会对模型产生怎样的影响?」2024年9月29日
,中心像素受影响较大,离中心越远梯度信号越弱。梯度信号的衰减是指数级的,这意味着应用于感受野的大多数像素的梯度将是可忽略的(如果有的话)。 有效感受野的定义...

AURIX单片机示例:开发入门与点亮LED
文章目录 目的模板工程Blinky_LED示例链接总结 目的 这个例程比较简单,主要通过这个例程来介绍 AURIX™ Development Studio(ADS) 和 iLLD 库来开发 AURIX 系列单片机一些入门的内容。一些更为基础的资料等内容可以参考下面文章: 《英飞凌 AURIX TriCo…...

MySQL字符串函数与操作
在编程领域中,字符串操作是数据处理中至关重要的一部分。无论是文本分析、日志处理,还是格式化输出,字符串的操作技能都能极大提高工作效率。在 Python 中,字符串相关的函数和方法为开发者提供了强大的工具,帮助完成各种任务。了解如何灵活运用这些工具,能够有效提升编程…...

HTML+CSS 水滴登录页
文章目录 一、效果演示二、Code1.HTML2.CSS 三、实现思路拆分 一、效果演示 实现了一个水滴登录页的效果。页面包含一个水滴形状的登录框和两个按钮,登录框包括用户名、密码和登录按钮,按钮分别为忘记密码和注册。整个页面的设计非常有创意,采…...

基于Next.js和TailwindCss的TailwindCss
最近在研究 Next.js 和 TailwindCss ,这两天没事的时候就搞了一个 c。 目前工具部署在 Vercel ,欢迎各位体验(能提出意见更好嘿嘿) 体验地址: https://icon.999872.xyz/ 图片预览 👇...

若依开源系统多数据源整合clickhouse数据库详细步骤
1.添加依赖【pom.xml文件】 <!-- clickhouse数据源依赖--><dependency><groupId>ru.yandex.clickhouse</groupId>...

Subdominator:一款针对漏洞奖励计划的子域名安全枚举工具
关于Subdominator Subdominator是一款针对漏洞奖励计划的子域名安全枚举工具,可用于在漏洞搜寻和侦察过程中进行被动子域名枚举。它旨在通过高效枚举子域名和各种免费被动资源来帮助研究人员和网络安全专业人员发现潜在的安全漏洞。 Subdominator 与各种免费和付费…...

[leetcode]516_最长回文子序列
给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。示例 1: 输入:s "bbbab" 输出&a…...

电子相册|智能化电子相册|基于java的电子相册管理系统设计与实现(源码+数据库+文档)
电子相册管理系统 目录 基于java的电子相册管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码农|毕设布道师&…...

linux项目_c语言:Makefile编写、动态库生成、添加动态库路径
一直想搞懂Linux中Makefile是怎么管理项目的,知识积累到一定程度后,我就做了一个自己的缩小项目去把剩下的细节搞清楚 代码: Service.c: #include <stdio.h> #include "lib_sevr.h" int main(){printf("输入a, b的值…...

Python学习(1):字典、DataFrame的创建方法
1. 字典的创建方法 1.1 直接创建 # 创建一个包含姓名和年龄的字典 person {"name": "Alice", "age": 25}print(person) # 输出:{name: Alice, age: 25} 1.2 使用 dict() 函数 # 使用键值对列表创建字典 person dict(name"…...

async await 介绍 从0手动实现async await
1 async await介绍 async 和 await 是用于处理异步编程的语法糖,它们简化了异步操作的编写,使其看起来像同步代码。通过 async 标记一个函数为异步函数,返回的是一个 Promise 对象,而 await 用来暂停执行,直到 Promise…...

UDP校验和计算及网络中的校验和机制
UDP (User Datagram Protocol) 是一种无连接的传输层协议,它不像 TCP 那样提供可靠的传输保证。虽然 UDP 不保证数据可靠性,但它仍然提供了一个可选的校验和机制来检测数据在传输过程中出现的错误。 理解UDP校验和的计算过程和其在网络中的作用至关重要。…...

如何使用C语言接入Doris数据库
如何使用C语言接入Doris数据库 一、环境准备1. 安装MySQL C API2. Doris数据库环境二、编写C语言接入代码1. 包含必要的头文件2. 编写连接和查询函数3. 编译和运行程序三、注意事项1. 安全性2. 错误处理3. 性能优化4. 兼容性5. 调试和日志记录四、结论Doris(之前称为Palo或Apa…...

DarkLabel 2.4 目标追标注工具介绍
DarkLabel介绍 https://github.com/darkpgmr/DarkLabel 官方地址 视频/图像标注工具,很适合用于目标追踪任务 DarkLabel可以在视频和图像中标注物体的边界框,并附上 ID 和name。还可以用于裁剪视频、从视频中采样训练图像以及对图像区域进行马赛克处理…...