| layout | post | |
|---|---|---|
| categories |
|
|
| description | none | |
| keywords | Java |
反射(Reflection),是指Java程序具有在 运行期分析类以及修改其本身状态或行为的能力。 通俗点说 就是 通过反射我们可以 动态地 获取一个类的所有属性和方法,还可以操作这些方法和属性。
一般我们创建一个对象实例Person zhang = new Person(); 虽然是简简单单一句,但JVM内部的实现过程是复杂的:
- 将硬盘上指定位置的Person.class文件加载进内存
- 执行main方法时,在栈内存中开辟了main方法的空间(压栈-进栈),然后在main方法的栈区分配了一个变量zhang。
- 执行new,在堆内存中开辟一个 实体类的 空间,分配了一个内存首地址值
- 调用该实体类对应的构造函数,进行初始化(如果没有构造函数,Java会补上一个默认构造函数)。
- 将实体类的 首地址赋值给zhang,变量zhang就引用了该实体。(指向了该对象)
将class文件加载到内存中具体分为3个阶段:加载、连接、初始化
JVM 的类加载器(你可以理解成一个工具)通过一个类的全限定名来获取该类的二进制字节流,然后将该 class 文件加载到 JVM 的方法区中。
类加载器加载一个 .class 文件到方法区的同时会在堆中生成一个唯一的 Class 对象,这个 Class 包含这个类的成员变量、构造方法以及成员方法。
所以表面上你 new 了一个对象,实际上当 JVM 运行程序的时候,真正帮你创建对象的是该类的 Class 对象。
也就是说反射其实就是 JVM 在运行程序的时候将你创建的所有类都封装成唯一一个 Class 对象。这个 Class 对象包含属性、构造方法和成员方法。你拿到了 Class 对象,也就能获取这三个东西。
你拿到了反射之后(Class)的属性,就能获取对象的属性名、属性类别、属性值,也能给属性设置值。
你拿到了反射之后(Class)的构造方法,就能创建对象。
你拿到了反射之后(Class)的成员方法,就能执行该方法。
而又在 加载阶段,类加载器 会将类对应的.class文件中的二进制字节流读入到内存中,将这个字节流转化为方法区的运行时数据结构,然后在堆区创建一个java.lang.Class对象(类相关的信息),作为对方法区中这些数据的访问入口
然后再通过 类的实例 来执操作 类的方法和属性 ,比如zhang.eat(), zhang.getHeight()等等
如果我们使用反射的话,我们需要拿到该类Person的Class对象,再通过Class对象来操作 类的方法和属性或者创建类的实例
Class personClass = Person.class;//这边只是举一个例子,获取class对象的多种方式,本文后面再慢慢道来
Object person = personClass.newInstance();
我们可以发现 通过new创建类的实例和反射创建类的实例,都绕不开.class文件 和 Class类的。