TODO
反射介绍
1、在运行状态中,对于任意一个类,都能够知道这个类的属性和方法。
2、对于任意一个对象,都能够调用它的任何方法和属性。
这种动态获取信息以及动态调用对象的方法的功能称为JAVA的反射。
JAVA语言编译之后会生成一个.class文件,反射就是通过字节码文件找到某一个类、类中的方法以及属性等。
类名.class、Class.forName和getClass不同
- 使用类名.class:加载类对象,装入内存,不初始化。返回class对象
- 使用Class.forName:加载类对象,进行静态属性/方法的初始化。返回class对象
- 使用getClass:加载类对象,进行静态属性/方法、非静态属性初始化,构造方法初始化。返回运行时“真正”对象(可能有父类声明,赋值为子类对象的情况)所属的类的class对象
因此使用Class.forName只能获取静态属性,不能获取私有变量,因为还未初始化。需要使用newInstance创建实例。
反射的作用
在JAVA中,只有给定类的名字,就可以通过反射机制来获取类的所有信息,可以动态的创建对象和编译。
反射的原理
首先明确的概念: 一切皆对象----类也是对象.
其次明白加载: 当Animal.class在硬盘中时,是一个文件,当载入到内存中,可以认为是一个对象,是java.lang.class的对象.
类对象(字节码对象):当JVM加载一个类时,会为这个类创建一个class对象。所有的类,都存在一个类对象,用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。
类的对象(实例化对象):类的实例化
类中的内容包括:modifier constructor field method.
反射的实现主要借助以下几个类:
Class:类的对象
Constructor:类的构造方法
Field:类中的属性对象
Method:类中的方法对象
Modifier
虚拟机允许两个相同类名的class被不同的ClassLoader加载,在运行时也会被认为是两个不同的类,因此需要注意不能相互赋值, 不然会抛出ClassCastException。
- getName():返回的是虚拟机里面的class的表示
- getCanonicalName():返回的是更容易理解的表示
对于普通类来说,二者没什么区别,只是对于特殊的类型上有点表示差异。例如
- byte[]类型,前者返回[B,后者返回byte[]
- byte[][]类型,前者返回[[B,后者返回byte
4. 代码实现
//todo待补充:https://www.jianshu.com/p/02bb399023f7
https://dandelioncloud.cn/article/details/1403089396840337410