您的位置:首页 > 编程语言 > Java开发

java反射基础知识(四)反射应用实践

2017-07-24 00:26 399 查看

反射基础

p.s: 本文需要读者对反射机制的API有一定程度的了解,如果之前没有接触过的话,建议先看一下官方文档的Quick Start

在应用反射机制之前,首先我们先来看一下如何获取一个对象对应的反射类
Class
,在Java中我们有三种方法可以获取一个对象的反射类。

通过getClass方法

在Java中,每一个
Object
都有一个
getClass()
方法,通过getClass方法我们可以获取到这个对象对应的反射类:

通过forName方法

我们也可以调用
Class
类的静态方法
forName()


使用.class

或者我们也可以直接使用
.class


获取类型信息

在文章开头我们就提到反射的一大好处就是可以允许我们在运行期间获取对象的类型信息,下面我们通过一个例子来具体看一下。

首先我们在
typeinfo.interfacea
包下面新建一个接口
A


接着我们在
typeinfo.packageaccess
包下面新建一个接口
C
,接口
C
继承自接口
A
,并且我们还另外创建了几个用于测试的方法,注意下面几个方法的权限都是不同的。

callHiddenMethod()
方法中我们用到了几个新的API,其中
getDeclaredMethod()
根据方法名用于获取Class类指代对象自己声明的某个方法,然后我们通过调用
invoke()
方法就可以触发对象的相关方法:

从输出结果我们可以看出来,不管是
public
default
protect
还是
pricate
方法,通过反射类我们都可以自由调用。当然这里我们只是为了显示反射的强大威力,在实际开发中这种技巧还是不提倡。

上面我们只是测试了
Method
对象,感兴趣的读者在熟悉了反射的API之后,不妨测试一下
Filed
,这里我们就不重复了。

与注解相结合

在单元测试框架比如
Junit
中反射机制也得到了广泛的应用,即通过注解的方式。下面我们简单地来了解一下如何通过反射机制来获取相关方法的注解信息,比如说我们有下面这样一个业务场景,当用户在修改自己密码的时候,为了保证密码的安全性,我们要求用户的新密码要满足一些条件,比如说至少要包含一个非数字字符,不能与以前的密码相同之类的条件等。

下面是我们检测密码的工具类的实现:

利用反射我们可以写出更加清晰的测试代码,其中
getDeclaredMethods()
方法可以获取相关对象自己声明的相关方法,而
getAnnotation()
则可以获取
Method
对象的指定注解。

解决泛型擦除

现在有下面这样一个业务场景,我们有一个泛型集合类
List<Class<? extends Pet>>
,我们需要统计出这个集合类中每种具体的
Pet
有多少个。由于Java的泛型擦除,注意类似
List<? extends Pet>
的做法肯定是不行的,因为编译器做了静态类型检查之后,到了运行期间JVM会将集合中的对象都视为
Pet
,但是并不会知道
Pet
代表的究竟是
Cat
还是
Dog
,所以到了运行期间对象的类型信息其实全部丢失了。p.s: 关于泛型擦除:我在上一篇文章里面有详细解释,感兴趣的朋友可以看一看。

为了实现我们上面的例子,我们先来定义几个类:

上面的
Pet
类继承自
Individual
Individual
类的的实现稍微复杂一点,我们实现了
Comparable
接口,重新自定义了类的比较规则,如果不是很明白的话,也没有关系,我们已经将它抽象出来了,所以不理解实现原理也没有关系。

下面创建了一个抽象类
PetCreator
,以后我们通过调用
arrayList()
方法便可以直接获取相关
Pet
类的集合。这里使用到了我们上面没有提及的
newInstance()
方法,它会返回Class类所真正指代的类的实例,这是什么意思呢?比如说声明
new Dog().getClass().newInstance()
和直接
new Dog()
是等价的。

接下来我们来实现上面这一个抽象类,解释一下下面的代码,在下面的代码中,我们声明了两个集合类,
allTypes
types
,其中
allTypes
中包含了我们呢上面所声明的所有类,但是我们具体的类型实际上只有两种即
Mutt
EgypianMau
,所以我们真正需要
new
出来的宠物只是
types
中所包含的类型,以后我们通过调用
getTypes()
便可以得到
types
中所包含的所有类型。

总体的逻辑已经完成了,最后我们实现用来统计集合中相关
Pet
类个数的
TypeCounter
类。解释一下
isAssignalbeFrom()
方法,它可以判断一个反射类是某个反射类的子类或者间接子类。而
getSuperclass()
顾名思义就是得到某个反射类的父类了。

References

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐