<div style="font-size:16px;">
<p>本文为 Android 开源项目源码解析 公共技术点中的 Java 反射 部分</p>
<p>分析者:Mr.Simple,校对者:Trinea,校对状态:未完成</p>
<p>1. 了解 Java 中的反射</p>
<p>1.1 什么是 Java 的反射</p>
<p>Java 反射是可以让我们在运行时获取类的函数、属性、父类、接口等 Class 内部信息的机制。通过反射还可以让我们在运行期实例化对象,调用方法,通过调用 get/set 方法获取变量的值,即使方法或属性是私有的的也可以通过反射的形式调用,这种“看透 class”的能力被称为内省,这种能力在框架开发中尤为重要。</p>
<p>有些情况下,我们要使用的类在运行时才会确定,这个时候我们不能在编译期就使用它,因此只能通过反射的形式来使用在运行时才存在的类(该类符合某种特定的规范,例如 JDBC),这是反射用得比较多的场景。</p>
<p>还有一个比较常见的场景就是编译时我们对于类的内部信息不可知,必须得到运行时才能获取类的具体信息。比如 ORM 框架,在运行时才能够获取类中的各个属性,然后通过反射的形式获取其属性名和值,存入数据库。这也是反射比较经典应用场景之一。</p>
<p>1.2 Class 类</p>
<p>那么既然反射是操作 Class 信息的,Class 又是什么呢?</p>
<p align="center"><img alt="arch.png" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-7c946c832f95f1f0c3b29111199faa9d.png"></p>
<p>当我们编写完一个 Java 项目之后,所有的 Java 文件都会被编译成一个.class 文件,这些 Class 对象承载了这个类型的父类、接口、构造函数、方法、属性等原始信息,这些 class 文件在程序运行时会被 ClassLoader 加载到虚拟机中。当一个类被加载以后,Java 虚拟机就会在内存中自动产生一个 Class 对象。我们通过 new 的形式创建对象实际上就是通过这些 Class 来创建,只是这个过程对于我们是不透明的而已。</p>
<p>下面的章节中我们会为大家演示反射的一些常用 api,从代码的角度理解反射。</p>
<p>2. 反射 Class 以及构造对象</p>
<p>2.1 获取 Class 对象</p>
<p>在你想检查一个类的信息之前,你首先需要获取类的 Class 对象。Java 中的所有类型包括基本类型,即使是数组都有与之关联的 Class 类的对象。如果你在编译期知道一个类的名字的话,那么你可以使用如下的方式获取一个类的 Class 对象。</p>
<p>Class> myObjectClass = MyObject.class;</p>
<p>如果你已经得到了某个对象,但是你想获取这个对象的 Class 对象,那么你可以通过下面的方法得到:</p>
<p>Student me = new Student("mr.simple");</p>
<p>Class> clazz = me.getClass();</p>
<p>如果你在编译期获取不到目标类型,但是你知道它的完整类路径,那么你可以通过如下的形式来获取 Class 对象:</p>
<p>Class> myObjectClass = Class.forName("com.simple.User");</p>
<p>在使用 Class.forName()方法时,你必须提供一个类的全名,这个全名包括类所在的包的名字。例如 User 类位于 com.simple 包,那么他的完整类路径就是 com.simple.User。</p>
<p>如果在调用 Class.forName()方法时,没有在编译路径下(classpath)找到对应的类,那么将会抛出 ClassNotFoundException。</p>
<p>接口说明</p>
<p>// 加载指定的 Class 对象,参数 1 为要加载的类的完整路径,例如"com.simple.Student". ( 常用方式 )</p>
<p>public static Class> forName (String className)</p>
<p>// 加载指定的 Class 对象,参数 1 为要加载的类的完整路径,例如"com.simple.Student";</p>
<p>// 参数 2 为是否要初始化该 Class 对象,参数 3 为指定加载该类的 ClassLoader.</p>
<p>public static Class> forName (String className, boolean shouldInitialize, ClassLoader classLoader)</p>
<p>2.2 通过 Class 对象构造目标类型的对象</p>
<p>一旦你拿到 Class 对象之后,你就可以为所欲为了!当你善用它的时候它就是神兵利器,当你心怀鬼胎之时它就会变成恶魔。但获取 Class 对象只是第一步,我们需要在执行那些强大的行为之前通过 Class 对象构造出该类型的对象,然后才能通过该对象释放它的能量。</p>
<p>我们知道,在 java 中要构造对象,必须通过该类的构造函数,那么其实反射也是一样一样的。但是它们确实有区别的,通过反射构造对象,我们首先要获取类的 Constructor(构造器)对象,然后通过 Constructor 来创建目标类的对象。还是直接上代码的。</p>
<p>private static void classForName() {<!-- --></p>
<p>try {<!-- --></p>
<p>// 获取 Class 对象</p>
<p>Class> clz = Class.forName("org |
|