Java技术栈——Java的Class与反射机制原理详解
深入理解java的Class与反射机制
前言
- Class
- 反射机制
深入理解Class对象机制
- Java代码运行阶段
- 类加载
- Class.forName方法
- Class字面常量
理解Java的反射技术
- Constructor类
- Method类
- Field类
简单的框架实现
前言
下面所有的示例学习内容中的所有的类和对象,均以Dog或者cat为例,进行学习。
Class
在Java编译运行过程中,当程序new一个新对象或者引用静态成员变量时,Java虚拟机(JVM)中的类加载器子系统会将对应Class对象加载到JVM中,然后JVM再根据这个类型信息相关的Class对象创建我们需要实例对象或者提供静态变量的引用值。需要特别注意的是,手动编写的每个class类,无论创建多少个实例对象,在JVM中都只有一个Class对象,即在内存中每个类有且只有一个相对应的Class对象。
反射机制
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。一直以来反射技术都是Java中的闪亮点,这也是目前大部分框架(如Spring/Mybatis等)得以实现的支柱。在Java中,Class类与java.lang.reflect类库一起对反射技术进行了全力的支持。
深入理解Class对象机制
Java代码运行阶段
先通过下图了解下java代码在计算机中运行的三个阶段:
类加载
实际上所有的类都是在对其第一次使用时动态加载到JVM中的,当程序创建第一个对类的静态成员引用时,就会加载这个被使用的类。下面通过一个简单例子来说明Class对象被加载的时间节点:
在上述代码中,每个类Dog、Cat都存在一个static语句:
运行结果:
Java程序在它们开始运行之前并非都被加载到内存的,其各个部分是按需加载,所以在程序使用该类时,类加载器首先会检查这个类的Class对象是否已被加载,如果还没有加载,默认的类加载器就会先根据类名查找.class文件(编译后Class对象被保存在同名的.class文件中),在这个类的字节码文件被加载时,它们必须接受相关验证,以确保其没有被破坏并且不包含不良Java代码(这是java的安全机制检测),完全没有问题后就会被动态加载到内存中,此时相当于Class对象也就被载入内存了(毕竟.class字节码文件保存的就是Class对象),同时也就可以被用来创建这个类的所有实例对象。
Class.forName方法
forName方法是Class类的一个static成员方法,程序中所创建的所有的Class对象都源于这个Class类,因此Class类中定义的方法将适应所有Class对象。通过forName方法,我们可以获取到类对应的Class对象引用。因此如果我们想获取一个类的运行时类型信息并加以使用时,可以调用Class.forName()方法获取Class对象的引用,这样做的好处是无需通过持有该类的实例对象引用而去获取Class对象。
Class字面常量
在Java中存在另一种方式来生成Class对象的引用,它就是Class字面常量,如下:
这种方式相对前面两种方法更加简单,更安全。因为它在编译器就会受到编译器的检查同时由于无需调用forName方法效率也会更高,因为通过字面量的方法获取Class对象的引用不会自动初始化该类。
理解Java的反射技术
如前言的反射机制所说,反射即是在程序动态运行的时候,对于任意一个类,可以获得其所有的方法以及变量。在反射包中,我们常用的类主要有:
1.Constructor类:表示的是Class 对象所表示的类的构造方法,利用它可以在运行时动态创建对象;
2.Field类:Field表示Class对象所表示的类的成员变量,通过它可以在运行时动态修改成员变量的属性值(包含private);
3.Method类:Method表示Class对象所表示的类的成员方法,通过它可以动态调用对象的方法(包含private)。
下面将对这几个重要类进行分别说明(类中的方法其实很好区分,每个方法后面+s,表示获取到相应类的所有对象;每个方法前面+declared,表示获取到不仅仅是public对象,还包括private对象)。
Constructor类
示例
获取带String参数的public构造函数
取得指定带int和String参数构造函数,该方法是私有构造
Method类
示例
Field类
示例,getDeclaredFields()方法获取的对象不包括父类,但是getFields()包括。
注意:Field其中的set(Object obj, Object value)方法是Field类本身的方法,用于设置字段的值,而get(Object obj)则是获取字段的值,相信这个不难理解。另外,final关键字修饰的Field字段是安全的,在运行时可以接收任何修改,但最终其实际值是不会发生改变的。
简单的框架实现
一直说反射是框架的核心,接下来就简单写一个框架,来帮助我们创建任何类的对象(以Dog为例)。
编写一个Dog类
编写配置文件 pro.properties
编写框架类
至此,一个简单的框架就实现了。
作者:菜C++鸡java
来源:CSDN
嗯嗯,学习了,哈哈哈