Java学习之反射的使用姿势详解

反射的学习使用

日常的学习工作中,可能用到反射的地方不太多,但看看一些优秀框架的源码,会发现基本上都离不开反射的使用;因此本篇博文将专注下如何

Java学习之反射的使用姿势详解


  1. 反射是什么,有什么用,可以做什么

  2. 如何使用反射

  3. 实例:

  • 利用反射方式,获取一个类的所有成员变量的name及值

  • 通过反射方式,修改对象的私有成员变量

  • 会通过写一个BeanUtils实现对象的成员变量值拷贝来覆盖上面两个场景


I. 反射定义

指程序可以访问、检测和修改它本身状态或行为的一种能力

直接说定义的话,可能并不能非常清晰的解释说明,结合作用进行描述

反射可以干什么?

Java学习之反射的使用姿势详解

直接说定义的话,可能并不能非常清晰的解释说明,下面尽可能结合作用进行描述

Java学习之反射的使用姿势详解

现在我有了clz,其赋值语句为Class clz = RefectTest.class, 那么我可以干啥?

1. 创建一个 RefectTest 对象

Java学习之反射的使用姿势详解

2. 判断父类是否是 MyRefect

Java学习之反射的使用姿势详解

3. 获取所有的成员变量

Java学习之反射的使用姿势详解

4. 获取所有的方法

Java学习之反射的使用姿势详解

上面给出了可以干些什么,并给了对应的简单示例,引入了几个新的类Constructor,Field,Method, 下面将详细解释这三个类是什么,怎么用

II. 反射的使用

努力结合实际的应用场景,给出每种利用反射的实现对应需求的使用姿势,有些场景可能并不是特别贴切,欢迎提出给合适的场景以此进行替换

1. 通过反射创建对象

这是个比较常见的场景,我在使用了自定义注解时,通常会这么晚

应用场景:

我定义了一个校验器的注解ValDot,注解中有个校验规则class对象,如下

Java学习之反射的使用姿势详解

上面定义了注解和校验条件,接着进入整体,在切面中,需要获取

Java学习之反射的使用姿势详解

上面是一个较好的利用反射获取实例的应用场景,想一想,如果不用反射,这个校验规则怎么传进来呢,这个时候就没那么方便了(当然也不是不可以,最简单的就是拿一个Holder持有类名到类对象的映射关系,然后在注解中传类名,也可以达到上面的效果)

还有一种场景可能就比较蛋疼了,如果一个类没有默认构造方法,通过反射就没法直接用class.newInstanace()了


Constructor构造器类

根据Class优先获取到Constructor对象,然后传入需要的构造参数, 测试如下

Java学习之反射的使用姿势详解

输出

Java学习之反射的使用姿势详解

一般常用下面四种方式获取

Java学习之反射的使用姿势详解


2. 判断class的继承关系

判断是否为基础数据类型

基本类型较为特殊,所以JDK很人性化的给封装了一个方法,Class#isPrimitive

因此返回true的类型有:

  • int

  • long

  • short

  • byte

  • char

  • boolean

封装后的类型,返回的依然是false

附带一句,是没有null.class这种用法的


判断是否为另一个类的子类,另一个接口的实现类

通常我们利用instanceof关键字来判断继承关系,但是这个是针对对象来的,现在给一个class,要怎么玩?

看下面,主要就是Class#isAssignableFrom()的功劳了

Java学习之反射的使用姿势详解

需要注意一点,父类作为调用方,子类作为参数


结合泛型时,获取泛型的实际类型

泛型,又是一个有意思的功能,这里不多说,继承一个泛型基类,然后问题是如何通过反射获得泛型签名中的类型,一般会在继承或实现泛型接口时会用到它。

Java学习之反射的使用姿势详解

换成泛型接口呢 ?

Java学习之反射的使用姿势详解

3. 获取成员变量

获取成员变量,主要是根据B.class.getDeclaredFields()来获取所有声明的变量,这个应用场景会和下面的获取方法并执行联合一起说明

Java学习之反射的使用姿势详解

这个主要返回Field对象,现在有了Field,可以做些啥?

Java学习之反射的使用姿势详解


4. 获取方法

获取方法,同上面的差不多,也有四种方式

Java学习之反射的使用姿势详解

返回了一个Method类,那么这个东西又有一些什么功能?

  1. 获取方法名Method#getName()

  2. 获取方法所在的类 :Method#getDeclaringClass()

  3. 获取方法返回类型 :Method#getReturnType()

  4. 获取方法上的注解 :Method#getAnnotations()

  5. 执行方法 有了这个就可以做很多事情了,实例中给出说明

    Java学习之反射的使用姿势详解


III. 实例DEMO

通过反射的方式,实现一个BeanUtils,实现Bean的拷贝

当一个Bean有较多的成员变量时,如果我们采用最原始的setXXX()来一次赋值的时候,一是实现比较繁琐,其次就是当Bean的字段发生变动之后,也需要同步的修改,那么我们借助反射的方式,实现一个优雅的BeanUtils工具类

Java学习之反射的使用姿势详解


IV. 小结

反射的四种用途

Java学习之反射的使用姿势详解

使用注意事项

  1. 操作私有变量,私有方法时,先设置field.setAccessible(true);确保可访问

  2. 反射会带来额外的性能开销

  3. 可以用Class#isAssignableFrom()来判断类继承关系

  4. 可以用Class#isPrimitive()判断是否为基本数据类型

  5. 可以用Class#getGenericSuperclass()获取泛型类型


V. 其他有需要Java资料的可以加群523401738


猜你喜欢

转载自blog.csdn.net/weixin_41780944/article/details/79583429