一文带你深入理解【Java基础】· Java反射机制(下)
写在前面
Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正!谢谢大家!!!
如果小哥哥小姐姐们对我的文章感兴趣,请不要吝啬你们的小手,多多点赞加关注呀!❤❤❤ 爱你们!!!
目录
写在前面
1. 获取运行时类的完整结构
1.1 通过反射获取运行时类的完整结构
1.2 代码演示
2. 调用运行时类的指定结构
2.1 调用运行时类的指定结构
2.2 关于setAccessible方法的使用
2.3 代码演示
3. 反射的应用:动态代理
3.1 代理设计模式的原理
3.2 Java动态代理相关API
3.3 动态代理步骤
3.4 动态代理与AOP(Aspect Orient Programming)
结语
【往期回顾】
一文带你深入理解【Java基础】· Java反射机制(上)
一文带你深入理解【Java基础】· 网络编程(下)
一文带你深入理解【Java基础】· 网络编程(上)
一文带你深入理解【Java基础】· IO流(下)
一文带你深入理解【Java基础】· IO流(中)
一文带你深入理解【Java基础】· IO流(上)
一文带你深入理解【Java基础】· 泛型
1. 获取运行时类的完整结构
1.1 通过反射获取运行时类的完整结构
Field、Method、Constructor、Superclass、Interface、Annotation
- 实现的全部接口
- 所继承的父类
- 全部的构造器
- 全部的方法
- 全部的Field
使用反射可以取得:
- 实现的全部接口
- public Class<?>[] getInterfaces()
- 确定此对象所表示的类或接口实现的接口。
- 所继承的父类
- public Class<? Super T> getSuperclass()
- 返回表示此 Class 所表示的实体(类、接口、基本类型)的父类的Class。
- 全部的构造器
- public Constructor<T>[] getConstructors()
- 返回此 Class 对象所表示的类的所有public构造方法。
- public Constructor<T>[] getDeclaredConstructors()
- 返回此 Class 对象表示的类声明的所有构造方法。
- Constructor类中:
- 取得修饰符: public int getModifiers();
- 取得方法名称: public String getName();
- 取得参数的类型:public Class<?>[] getParameterTypes();
- 全部的方法
- public Method[] getDeclaredMethods()
- 返回此Class对象所表示的类或接口的全部方法
- public Method[] getMethods()
- 返回此Class对象所表示的类或接口的public的方法
- Method类中:
- public Class<?> getReturnType()取得全部的返回值
- public Class<?>[] getParameterTypes()取得全部的参数
- public int getModifiers()取得修饰符
- public Class<?>[] getExceptionTypes()取得异常信息
- 全部的Field
- public Field[] getFields()
- 返回此Class对象所表示的类或接口的public的Field。
- public Field[] getDeclaredFields()
- 返回此Class对象所表示的类或接口的全部Field。
- Field方法中:
- public int getModifiers() 以整数形式返回此Field的修饰符
- public Class<?> getType() 得到Field的属性类型
- public String getName() 返回Field的名称。
- Annotation相关
- get Annotation(Class<T> annotationClass)
- getDeclaredAnnotations()
- 泛型相关
- 获取父类泛型类型:Type getGenericSuperclass()
- 泛型类型:ParameterizedType
- 获取实际的泛型类型参数数组:getActualTypeArguments()
- 类所在的包
- Package getPackage()
小 结:1.在实际的操作中,取得类的信息的操作代码,并不会经常开发。2.一定要熟悉java.lang.reflect包的作用,反射机制。3.如何取得属性、方法、构造器的名称,修饰符等。1.2 代码演示
public class FieldTest {@Testpublic void test1() {Class clazz = Person.class;//获取属性结构//getFields():获取当前运行时类及其父类中声明为public访问权限的属性Field[] fields = clazz.getFields();for (Field f : fields) {System.out.println(f);}System.out.println();//getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)Field[] declaredFields = clazz.getDeclaredFields();for (Field f : declaredFields) {System.out.println(f);}}/** 权限修饰符 数据类型 变量名 */@Testpublic void test2() {Class clazz = Person.class;Field[] declaredFields = clazz.getDeclaredFields();for (Field f : declaredFields) {//1.权限修饰符int modifier = f.getModifiers();System.out.print(Modifier.toString(modifier) + "\t");//2.数据类型Class type = f.getType();System.out.print(type.getName() + "\t");//3.变量名String fName = f.getName();System.out.print(fName);System.out.println();}} }
![]()
2. 调用运行时类的指定结构
2.1 调用运行时类的指定结构
- 调用指定方法
- 通过反射,调用类中的方法,通过Method类完成。步骤:
- 通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。
- 之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。
Object invoke(Object obj, Object … args)说明:
- Object 对应原方法的返回值,若原方法无返回值,此时返回null
- 若原方法若为静态方法,此时形参Object obj可为null
- 若原方法形参列表为空,则Object[] args为null
- 若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。
- 调用指定属性
- 在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()和get()方法就可以完成设置和取得属性内容的操作。
- public Field getField(String name) 返回此Class对象表示的类或接口的指定的public的Field。
- public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。
- 在Field中:
- public Object get(Object obj) 取得指定对象obj上此Field的属性内容
- public void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容
2.2 关于setAccessible方法的使用
- Method和Field、Constructor对象都有setAccessible()方法。
- setAccessible启动和禁用访问安全检查的开关。
- 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
- 提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。
- 使得原本无法访问的私有成员也可以访问
- 参数值为false则指示反射的对象应该实施Java语言访问检查。
2.3 代码演示
public class MethodTest {@Testpublic void test1() {Class clazz = Person.class;//getMethods():获取当前运行时类及其所有父类中声明为public权限的方法Method[] methods = clazz.getMethods();for (Method m : methods) {System.out.println(m);}System.out.println();//getDeclaredMethods():获取当前运行时类中声明的所有方法。(不包含父类中声明的方法)Method[] declaredMethods = clazz.getDeclaredMethods();for (Method m : declaredMethods) {System.out.println(m);}}/**@Xxxx权限修饰符 返回值类型 方法名(参数类型1 形参名1,...) throws XxxException{}*/@Testpublic void test2() {Class clazz = Person.class;Method[] declaredMethods = clazz.getDeclaredMethods();for (Method m : declaredMethods) {//1.获取方法声明的注解Annotation[] annos = m.getAnnotations();for (Annotation a : annos) {System.out.println(a);}//2.权限修饰符System.out.print(Modifier.toString(m.getModifiers()) + "\t");//3.返回值类型System.out.print(m.getReturnType().getName() + "\t");//4.方法名System.out.print(m.getName());System.out.print("(");//5.形参列表Class[] parameterTypes = m.getParameterTypes();if (!(parameterTypes == null && parameterTypes.length == 0)) {for (int i = 0; i < parameterTypes.length; i++) {if (i == parameterTypes.length - 1) {System.out.print(parameterTypes[i].getName() + " args_" + i);break;}System.out.print(parameterTypes[i].getName() + " args_" + i + ",");}}System.out.print(")");//6.抛出的异常Class[] exceptionTypes = m.getExceptionTypes();if (exceptionTypes.length > 0) {System.out.print("throws ");for (int i = 0; i < exceptionTypes.length; i++) {if (i == exceptionTypes.length - 1) {System.out.print(exceptionTypes[i].getName());break;}System.out.print(exceptionTypes[i].getName() + ",");}}System.out.println();}} }
![]()
3. 反射的应用:动态代理
3.1 代理设计模式的原理
- 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
- 之前为大家讲解过代理机制的操作,属于静态代理,特征是代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展。同时,每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理。最好可以通过一个代理类完成全部的代理功能。
- 动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。
- 动态代理使用场合:
- 调试
- 远程方法调用
动态代理相比于静态代理的优点:
- 抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。
3.2 Java动态代理相关API
- Proxy :专门完成代理的操作类,是所有动态代理类的父类。通过此类为一个或多个接口动态地生成实现类。
- 提供用于创建动态代理类和动态代理对象的静态方法
3.3 动态代理步骤
1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法,以完成代理的具体操作。2.创建被代理的类以及接口
3.通过Proxy的静态方法
4.通过 Subject代理调用RealSubject实现类的方法
3.4 动态代理与AOP(Aspect Orient Programming)
前面介绍的Proxy和InvocationHandler,很难看出这种动态代理的优势,下面介绍一种更实用的动态代理机制
改进后的说明:
- 代码段1、代码段2、代码段3和深色代码段分离开了,但代码段1、2、3又和一个特定的方法A耦合了!最理想的效果是:代码块1、2、3既可以执行方法A,又无须在程序中以硬编码的方式直接调用深色代码的方法
public interface Dog{void info();void run(); } public class HuntingDog implements Dog{public void info(){System.out.println("我是一只猎狗");}public void run(){System.out.println("我奔跑迅速");} }public class DogUtil{public void method1(){System.out.println("=====模拟通用方法一=====");}public void method2(){System.out.println("=====模拟通用方法二=====");} }public class MyInvocationHandler implements InvocationHandler{// 需要被代理的对象private Object target;public void setTarget(Object target){this.target = target;}// 执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法public Object invoke(Object proxy, Method method, Object[] args) throws Exception{DogUtil du = new DogUtil();// 执行DogUtil对象中的method1。du.method1();// 以target作为主调来执行method方法Object result = method.invoke(target , args);// 执行DogUtil对象中的method2。du.method2();return result;} }public class MyProxyFactory{// 为指定target生成动态代理对象public static Object getProxy(Object target) throws Exception{// 创建一个MyInvokationHandler对象MyInvokationHandler handler = new MyInvokationHandler();// 为MyInvokationHandler设置target对象handler.setTarget(target);// 创建、并返回一个动态代理对象return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces() , handler);} }public class Test{public static void main(String[] args) throws Exception{// 创建一个原始的HuntingDog对象,作为targetDog target = new HuntingDog();// 以指定的target来创建动态代理Dog dog = (Dog)MyProxyFactory.getProxy(target);dog.info();dog.run();} }
- 使用Proxy生成一个动态代理时,往往并不会凭空产生一个动态代理,这样没有太大的意义。通常都是为指定的目标对象生成动态代理
- 这种动态代理在AOP中被称为AOP代理,AOP代理可代替目标对象,AOP代理包含了目标对象的全部方法。但AOP代理中的方法与目标对象的方法存在差异:
- AOP代理里的方法可以在执行目标方法之前、之后插入一些通用处理
![]()
结语
本人会持续更新文章的哦!希望大家一键三连,你们的鼓励就是作者不断更新的动力
相关文章:
一文带你深入理解【Java基础】· Java反射机制(下)
写在前面 Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正࿰…...
JVM的几种GC
GC JVM在进行GC时,并不是对这三个区域统一回收。大部分时候,回收都是新生代~ 新生代GC(minor GC): 指发生在新生代的垃圾回收动作,因为Java对象大多都具备朝生夕灭的特点,所以minor GC发生得非…...
掌握Shell脚本的if语句,让你的代码更加精准和高效
前言 大家好,我是沐风晓月,本文首发于csdn, 作者: 我是沐风晓月。 文章收录于 我是沐风晓月csdn专栏 【系统架构实战】专栏中的【shell脚本入门到精通】专栏。 本专栏从零基础带你层层深入,学会shell脚本,不是梦。 &…...
音质好的蓝牙耳机有哪些?音质最好的蓝牙耳机排行
说起当代人外出必备是数码产品,蓝牙耳机肯定存在。不管是听歌还是追剧,蓝牙耳机在音质上的表现也是越来越好了。下面,我来给大家推荐几款音质好的蓝牙耳机,一起来看看吧。 一、南卡小音舱蓝牙耳机 参考价:259 蓝牙版…...
一次Android App NDK崩溃问题的分析及解决
文章目录小结NDK崩溃的问题通过logcat查看崩溃日志提取tombstone的记录通过ndk-stack来输出日志取得的日志分析并解决分析使用add2line定位具体报错的行数解决参考小结 最近碰一次Android App NDK崩溃的问题,这个NE(Native Exception)是从ND…...
因果图判定表法
因果图&判定表法 在了解了等价类和边界值比较适宜搭档的测试用例方法之后 接下来我们来了解另外一队就是因果图和判定表 因果图会产生判定表法 因果图法 等价类划分法和边界值分析方法都是着重考虑输入条件而不考虑输入条件的各种组合、输入条件之间的相互制约关系。例…...
Oracle 数据库相关信息清单列表
Oracle 数据库相关信息清单列表 一、设置Oracle安装目录 Oracle基目录(ORACLE_BASE):D:\databases\oracle\oracle_11g\app\Administrator 软件位置(ORACLE_HOME):D:\databases\oracle\oracle_11g\app\Administrator\product\11.2.0\dbhome_1 数据库文件位置:D:\databa…...
射频资料搜集--推荐几个网站和链接
https://picture.iczhiku.com/resource/eetop/wHKYFQlDTRRShCcc.pdfhttps://picture.iczhiku.com/resource/eetop/wHKYFQlDTRRShCcc.pdfVCO pulling的资料 模拟滤波器与电路设计手册 - 射频微波仿真 - RF技术社区 Practical RF Amplifier Design Using the Available Gain Pr…...
B1048 数字加密
decription 本题要求实现一种数字加密方法。首先固定一个加密用正整数 A,对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余——这里用 J 代表 10、Q 代表 11、K 代表 …...
Qt使用FFmpeg播放视频
一、使用场景 因为项目中需要加载MP4播放开机视频,而我们的设备所使用的架构为arm架构,其中缺乏一些多媒体库。安装这些插件库比较麻烦,所以最终决定使用FFmpeg播放视频。 二、下载编译ffmpeg库 2.1 下载源码 源码下载路径:http…...
Win32 ListBox控件
Win32 ListBox控件 创建ListBox控件 创建窗口函数 HWND CrateWindowEx(DWORD dwExStyle , // 窗口的扩展风格,基本没用LPCTSTR lpClassName, // 已经注册的窗口类名称LPCTSTR lpWindowName, // 窗口标题栏的名字DWORD dwStyle, // 窗口的基本风格int x, // 左上角水平坐标int …...
最大值池化与均值池化比较分析
1 问题在深度学习的卷积网络过程中,神经网络有卷积层,池化层,全连接层。而池化层有最大值池化和均值池化两种情况,而我们组就在思考,最大值池化和均值池化有什么区别呢?两者的模型准确率是否有所不同&#…...
统计学 多元线性回归
文章目录统计学 多元线性回归多元线性回归模型拟合优度显著性检验线性关系检验回归系数检验多重共线性及其处理多重共线性的问题多重共线性的识别与处理变量选择利用回归方程进行预测哑变量回归统计学 多元线性回归 多元线性回归模型 多元线性回归模型:设因变量为…...
tar和gzip压缩和解压
打包和压缩的区别:打包:将多文件 封装在一起压缩:将多文件 封装在一起 通过特定的算法 将冗余的数据 进行删除tar默认是打包命令,如果想用tar进行压缩 必须加选项1、gzip格式压缩:tar zcvf 压缩包包名 文件1 文件2 文件…...
搭建Docker企业私有仓库
什么是仓库 仓库(Repository)是存储和分发 Docker 镜像的地方。镜像仓库类似于代码仓库,Docker Hub 的命名来自 GitHub,Github 是我们常用的代码存储和分发的地方。同样 Docker Hub 是用来提供 Docker 镜像存储和分发的地方。 谈…...
[NOIP2009 提高组] 最优贸易(C++,tarjan,topo,DP)
题目描述 $C 国有国有国有 n 个大城市和个大城市和个大城市和 m$ 条道路,每条道路连接这 nnn个城市中的某两个城市。任意两个城市之间最多只有一条道路直接相连。这 mmm 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的…...
计算机网络:移动IP
移动IP相关概念 移动IP技术是移动结点(计算机/服务器)以固体的网络IP地址,实现跨越不同网段的漫游功能,并保证了基于网络IP的网络权限在漫游中不发生任何改变。移动结点:具有永久IP地址的设备。归属代理(本…...
binutils工具集——GNU binutils工具集简介
以下内容源于网络资源的学习与整理,如有侵权请告知删除。 GNU binutils是一个二进制工具集,主要包括: ld,GNU链接器。as,GNU汇编器。addr2line,把地址转化为文件名和行号。nm,列出目标文件的符…...
Golang编译选项(ldflags)有趣应用
本文介绍如何在构建时使用ldflags选项给Golang应用程序注入变量,用于给Go可执行文件增加版本标识或GIT提交摘要等信息。 应用程序的版本信息 我们首先查看Docker Cli 包含的提交信息: docker version 返回结果: Server: Docker Engine - Co…...
AIR32F103(十一) 在AIR32F103上移植微雪墨水屏驱动
目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告AIR32F103(二) Linux环境和LibOpenCM3项目模板AIR32F103(三) Linux环境基于标准外设库的项目模板AIR32F103(四) 27倍频216MHz,CoreMark跑分测试AIR32F103(五) FreeRTOSv202112核心库的集成和示例代码AIR32F103(六) ADC,I2S…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...










