提起hook概念,相信大家都听说过,然后hook就是将反射和动态代理运用于Android平台源码之上的。可是,反射的应用场景缺非常广泛,注解的内容也同样需要使用反射去获取,所以反射是我们Android开发者必须要学习的知识。
反射
什么是反射?
反射 (Reflection) 是 Java 的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性
简而言之,通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。
反射的核心是 JVM 在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。
Java 反射主要提供以下功能:
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
- 在运行时调用任意一个对象的方法
- 重点:是运行时而不是编译时
反射的运用
获得 Class 对象
使用 Class 类的 forName 静态方法
直接获取某一个对象的 class
调用某个对象的 getClass() 方法
判断是否为某个类的实例
一般地,我们用 instanceof 关键字来判断是否为某个类的实例。同时我们也可以借助反射中 Class 对象的 isInstance() 方法来判断是否为某个类的实例,它是一个 native 方法:
创建实例
通过反射来生成对象主要有两种方式。
- 使用Class对象的newInstance()方法来创建Class对象对应类的实例。
- 先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这种方法可以用指定的构造器构造类的实例。
获取构造器信息
得到构造器的方法
获取类构造器的用法与上述获取方法的用法类似。主要是通过Class类的getConstructor方法得到Constructor类的一个实例,而Constructor类有一个newInstance方法可以创建一个对象实例:
获取类的成员变量(字段)信息
获得字段信息的方法
调用方法
获得方法信息的方法
当我们从类中获取了一个方法后,我们就可以用 invoke() 方法来调用这个方法。invoke 方法的原型为:
利用反射创建数组
数组在Java里是比较特殊的一种类型,它可以赋值给一个Object Reference
其中的Array类为java.lang.reflect.Array类。我们通过Array.newInstance()创建数组对象,它的原型是:
而 newArray 方法是一个 native 方法,它在 HotSpot JVM 里的具体实现我们后边再研究,这里先把源码贴出来:
注意事项
反射会额外消耗一定的系统资源,因此如果不需要动态地创建一个对象,那么就不需要用反射
反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题!
最后
读到最后的朋友可转发关注下,以后还会不定期更新更多精选文章干货分享!