百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

实操讲解Java的反射机制,你要是再看不懂,神仙都没救了

wptr33 2025-02-21 15:38 32 浏览

今天说一下Java 的反射,先从编程语言的类型入手吧。

解释型语言和编译型语言

解释型语言:不需要编译,在运行的过程中逐行进行翻译解释;修改代码时候非常方便,可以直接修改,并且在部署上非常的快速不过性能上比不上编译类型的语言,比如说JavaScript、Python。

编译型语言:需要通过编译器的帮助来进行源代码到机器码的转换;如果在编译结束后需要对代码进行修改,则执行之前就需要重新编译。例如C语言。

返回正题,Java严格来说也是编程语言,但是细分的话又介于编程和解释之间,因为Java生成的是中间码而并非机器码,在编译的过程中,是把源码交付给编译器进而生成class文件,在整个过程中,它只负责了翻译的工作,是没有将代码放进运行内存的。然后进入运行期后,Java虚拟机加载字节码并解释成机器语言运行。

动态语言和静态语言

动态语言:程序运行的过程当中有改变自身结构的能力,在运行的过程中确定数据的类型,一个对象执行操作的时候不取决于它属于某种类型而是取决于是否存在相对应的方法,例如JavaScript、Python。

静态语言:相对于动态语言来说,在编译的过程中就确定了变量的数据类型,在编译时进行类型匹配。比如C语言,Java。

反射的概念

Java的反射机制:在运行的过程中,针对某一类都可以了解到所有的属性和方法。无论对于哪一个对象都有调用它的属性和方法,这种动态信息的获取和调用对象方法的功能就叫Java的反射机制。

在提到反,就得说明一下正。如果要用Java中某个类的方法,一般来说“正向”是如此的:

ArrayList list = new ArrayList(); //实例化  
list.add("reflection");  //执行方法 

“反向”就变成了这样:

Class clz = Class.forName("java.util.ArrayList");  
Method method_add = clz.getMethod("add",Object.class);  
Constructor constructor = clz.getConstructor();  
Object object = constructor.newInstance();  
method_add.invoke(object, "reflection");  
Method method_get = clz.getMethod("get",int.class);  
System.out.println(method_get.invoke(object, 0)); 

看出来了吗?两端代码的执行结果是相同的,但是区别在于“正向”运行之前就将“类”给明确了,反向则不是如此,反向是代码运行时,才知道类是什么。

反射的作用

说到这里其实很多朋友就对反射的作用很疑惑了,我已经知道要使用的类是ArrayList,难道我不能直接new一个对象然后去执行里面的方法?

回答是当然可以,你完全可以这样做。不过在实际操作中会发现代码运行之前对哪个类的使用是不知道的,或者说只有在运行的那个时候才可以决定到底是哪个类。可以懂我的意思吗?举个例子,假设现在有一个功能,:“调用阿里云的人脸识别API”,如果我们去参考它的API文档,这个实现就变得非常的容易了。

faceRecognition(Object faceImg){  
  //调用阿里云的人脸识别 API 
} 

然后过了一段时间,合作商从阿里变成了腾讯,人脸识别的接口必然要改变,这个时候

faceRecognition(Object faceImg){  
  //调用腾讯云的人脸识别 API  
} 

又过了一段时间,又发生了改变,领导又说还回来把······

这个时候内心崩溃的同时,又必须要照做,这个时候比较聪明的程序员就会想到设置一个类似开关的程序,让开关决定走哪一段的代码,就算之后想换成亚马逊云的服务,继续写就好了

faceRecognition(Object faceImg){  
  if("AL".equals(configStr)){  
    //调用阿里云的人脸识别 API  
  }else if("TX".equals(configStr)){  
    //调用腾讯云的人脸识别 API  
  }else if("AM".equals(configStr)){  
    //调用亚马逊云的人脸识别 API  
  }  
} 

当然在除了这个点之外还有一个更好的办法:

定义一个接口:

interface FaceRecognitionInterface(){  
  faceRecognition(Object faceImg) ;  
} 

多个实现类:

class ALFaceRecognition implements FaceRecognitionInterface{  
  //调用阿里云的人脸识别 API 的实现  
}  
class TXFaceRecognition implements FaceRecognitionInterface{  
  //调用腾讯云的人脸识别 API 的实现  
} 

调用人脸识别功能代码时

String configStr = "读取配置,走阿里云还是腾讯云";  
FaceRecognitionInterface faceRe =  Class.forName(configStr).newInstance();  
faceRe.faceRecognition(faceImg); 

我们以上文的这个例子,你调用的时候做if-else判断和使用反射实现其实差距并不大,但是如果出现三个程序员分别做提供接口、提供实现、写客户端这三个工作呢?比如说我们创建一个链接

public Connection getConnection() throws Exception{  
  Connection conn = null;  
  //初始化驱动类  
  Class.forName("com.mysql.jdbc.Driver");  
  conn = DriverManager.getConnection("jdbc:mysql://url","root", "admin");  
  return conn;  
} 

在这个链接中可以看到一个程序员提供了接口,Oracle 公司提供 JDBC 标准,另一个程序员提供实现,也就各个数据厂商对自己数据库的实现,最后一个程序员负责客户端,公司的码农在Java中敲代码访问数据库。

从上面部分我们就可以看到Java的反射作用,它设计出的构架灵活度和通用性更高,有时候也可以通过配置加载不同的类来保证其通用性,这个时候是需要用到反射的,不仅如此:

动态代理:以不改变目标对象方法的前提下对方法进行增强,比如使用AOP拦截某些方法打印日志,这个时候使用反射就会非常的方便,

注解:利用反射机制获取注解并执行对应行为。

用反射的用法

之前说过Java运行时候的源文件是字节码,所以需要获取字节码的文件对象来使用反射,现在介绍三种获取字节码文件对象的方式:

调用某个类的class属性:类名.class

调用对象的 getClass() 方法:对象.getClass()

使用 Class 类中的 forName() 静态方法:Class.forName(类的全路径) ,建议使用这种方法

java.lang.reflect 类库提供了对反射的支持:

Field :可以使用 get 和 set 方法读取和修改对象的属性;

Method :可以使用 invoke() 方法调用对象中的方法;

Constructor :可以用 newInstance() 创建新的对象。

反射的优缺点

优点:在运行的过程中可以获得类和对象之间的内容,对于提高整体系统的灵活性和拓展性是非常有帮助的,甚至可以夸张一点,反射属于框架设计的灵魂。

缺点:在性能上会有一部分的损耗,JVM是无法优化此类的代码的。

大家在平时的开发过程中可能并没有写到过反射代码,但是在我们经常使用的开源框架中,反射可以说是随处可见。

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个else解...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。今天分享一下break和continue在代码中的执行效果是什么,进一步区分出二者的区别。一、continue例1:当小明3岁时不打印年龄,其余年龄正常循环打印。可以看...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。答案:CSS的盒模型是用于布局和定位元素的概念。它由内容区域...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)1.vue的生命周期有哪些及每个生命周期做了什么?beforeCreate是newVue()之后触发的第一个钩子,在当前阶段data、methods、com...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...