如何理解反射?

在开发过程中我们会经常听到、见到、乃至使用到反射,但是对于反射的理解大家应该都有自己的独特见解,本文章仅在叙述个人对反射的理解,如有补充请评论。
在讲述个人理解之前,先来看一下Oracle官方对反射的解释:
在这里插入图片描述
看到英文应该就有人头疼了,不要紧,可以用百度翻译一下,大概的意思就是:反射使Java代码能够发现有关已加载类的字段、方法和构造函数的信息,并在安全限制内使用反射的字段、方法和构造函数对其底层对应项进行操作。API容纳需要访问目标对象的公共成员(基于其运行时类)或给定类声明的成员的应用程序。它还允许程序抑制默认的反射访问控制。
反射的核心就是JVM在运行时动态加载类或者调用方法/访问属性,而不需要在写代码或者编译期知道运行对象是谁。
Java反射框架主要提供的功能有:
1、在运行时判断任意一个对象所属的类
2、在运行时构造任意一个类的对象
3、在运行时判断任意一个类所具有的成员变量和方法-私有方法也可以
4、在运行时调用任意一个对象的方法
基于Class类的反射应用
A.Class是一个类,一个描述类的类(即描述类),封装了描述方法的Method,描述字段的Field,描述构造器的Constructor等属性
B.对象反射(照镜子)后可以得到的信息:某个类的数据成员名,方法和构造器以及某个类实现了那些接口
C.对于每个类而言,JRE都为其保留一个不变的Class类型的对象,一个Class对象包含了特定某个类的有关信息
D.Class对象只能由系统建立对象
E.一个类在JVM中只会有一个Class实例

总结:JDK中有一个类-Class,这个类封装了所有Java类型,包括这些类的所有信息,JVM中类信息放在方法区
那么根据上边的解释,我们就可以了解到,反射的过程其实是发生在程序的运行态,拿到编译阶段(类加载)过程中加载到JVM中的类信息,其实本质上反射就类似于是一个镜子,将java code和加载到JVM内存中的属性、方法以及类信息形成对照。

在这里插入图片描述
上边扯了很多的概念,估计都得头晕晕了,接下来就说一下反射的常见使用:
获取Class对象
这里的Class对象和声明类使用的class是不一样的点击这里了解

Class<?> clazz=Class.forName("全限定类名")//返回的clazz其实是全限定类名的类的Class类对象引用,指向这个类以及类的字节码文件信息
Class<?> clazz=object.getClass() //通过引用得到Class对象
Class<?> clazz=Object.class //通过类字面量常量获得(懒加载)

获得构造器
获得构造器我们就需要借助jdk提供的reflect包下的constructor类
1.获得指定构造器
Constructor getConstructor(Class<?>…parameterTypes)
parameterTypes是Class[],里边的元素和元素顺序与构造器参数对应(本质上这种方式就是创建一个带参的类)

Constructor constructor=getConstructor(new Class[]{})//获得默认构造器
Constructor constructor=getConstructor(new Class[]{String.Class,int.Class})//获得参数为(String,int)的构造器

2.获得所有构造器

Constructor[] constructor=clazz.getConstructors()

获得字段
1.获得public字段

Field field=clazz.getField(String name);//获得对应名称的字段
Filed[] fields=clazz.getField();//获得所有public字段
2.获得自身字段(所有字段)
Field field=clazz.getDeclareField(String name);//获得当前类中定义的所有字段---tips:所有
Field[] fields=clazz.getDeclareField();//获取所有字段的数组

3.获得所有字段(include 父类字段)

getSuperClass()//获得父类Class对象,然后循环调用getSuperClass()和getDeclaredField[],将Field放入List中即可

获得方法
1.获得public方法

Method method=clazz.getMethod(String name,Class<?>..parameterTypes);//
name是方法名,parameterTypes是Class[],用来获取方法参数的类型

注意:这种方式只能够获取到当前引用类以及父类的public方法,其他权限无法获得

Method[] methods=clazz.getMethods();//获得所有方法

2.获得自身方法

Method method=clazz.getDeclaredMethod(String name,Class<?>...parameterTypes);//获得当前类定义的所有方法,不包括父类
Method[] methods=clazz.getDeclaredMethods();//获得所有方法

注意:这种方式虽然可以获得私有或者保护修饰符的方法,但是无法使用,需要有强制穿透才可以
3.获得所有方法(include 父类方法)
同获得所有字段的操作,不再赘述
创建实例对象
1.通过反射得到的构造器创建实例(推荐使用,可降低耦合度)

//无参构造器创建对象
XXX xxx=(XXX)constructor.newInstance();
//带参构造器创建对象
XXX xxx=(XXX)constructor.newInstance(xx);

2.通过Class对象创建实例

XXX xxx=XXX.class.newInstance();

3.new、反序列化、clone()等方式
通过反射调用方法

method.invoke(Object obj,Object ... args)//传入实例对象obj和方法对应的参数

private修饰的方法无法反射(上边有提到),需要设置method.setAccessible(true)强制穿透才能够完成反射调用

本人才疏学浅,如有不准确的地方,评论区可以提出大家的见解,下边我也列举两篇博客供大家参考
参考1
参考2
同时也提出一个问题,大家可以思考一下:反射机制到底是不是安全的?如果是安全的为什么是安全的?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

new_repo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值