day21_反射&枚举
类加载器
类加载
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的 【加载】,【连接】,【初始化】 这三个步骤来对类进行初始化。
一个类的生命周期包括了 "加载"、"验证"、"准备"、"解析"、"初始化"、"使用"、"卸载" 这七个阶段,==
类的加载
将编译后的字节码文件加载到内存中,以便在程序运行时使用。类加载器将字节码文件读取到内存,并创建对应的 Class 对象。
用于加载二进制数据,类的加载主要做三件事情:
找到类文件、放入方法区、开个入口
类的连接
==【验证阶段】:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致==
==【准备阶段】:负责为类的类变量分配内存,并设置默认初始化值==
==【解析阶段】:将类的二进制数据中的符号(比如类、方法、字段的引用)替换为直接引用==
类的初始化
类的初始化的主要工作是为静态变量赋程序设定的初值。
类的初始化步骤
-
假如类还未被加载和连接,则程序先加载并连接该类
-
假如该类的直接父类还未被初始化,则先初始化其直接父类
-
假如类中有初始化语句,则系统依次执行这些初始化语句
-
注意:在执行第2个步骤的时候,系统对直接父类的初始化步骤也遵循初始化步骤1-3
类的初始化时机
-
创建类的实例
-
调用类的类方法
-
访问类或者接口的类变量,或者为该类变量赋值
-
使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
-
初始化某个类的子类
-
直接使用java.exe命令来运行某个主类
类加载器
作用
类加载器的作用,就是把class文件装进虚拟机,并为之生成对应的 java.lang.Class 对象
类加载机制
全盘负责、父类委托、缓存机制、双亲委派机制
双亲委派机制
好处
避免重复加载、保持一致性
Java中的内置类加载器
引导类加载器、扩展类加载器、系统类加载器、自定义类加载器
反射
可以通你这个对象拿到字节码文件,通过子节码文件还原到类的本身(也就是说你拿到类的Class对象去使用这个类的成员方法,成员变量,构造方法)
获取Class类对象的三种方式
-
类名.class属性
-
对象名.getClass()方法
-
Class.forName(全限定类名)方法
获取构造方法
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor<T> getConstructor(Class<?>... parameterTypes) | 返回单个公共构造方法对象 |
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | 返回单个构造方法对象 |
用于创建对象的方法
方法名 | 说明 |
---|---|
T newInstance(Object...initargs) | 根据指定的构造方法创建对象 |
获取成员变量
Class类获取成员变量对象的方法
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有公共成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
void set(Object obj,Object value) | 给obj对象的成员变量赋值为value |
获取成员方法
Class类获取成员方法对象的方法
方法名 | 说明 |
---|---|
Method[] getMethods() | 返回所有公共成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name, Class<?>... parameterTypes) | 返回单个公共成员方法对象 |
Method getDeclaredMethod(String name, Class<?>... parameterTypes) | 返回单个成员方法对象 |
Object invoke(Object obj,Object... args) | 调用obj对象的成员方法,参数是args,返回值是Object类型 |
案例-通过反射获取配置文件内容
public class Student { public void show(){ System.out.println("学生学习了"); } }
配置文件内容
ClassName=cn.yanqi_07.Student MethodName=show
public static void main(String[] args) throws Exception { // Student s = new Student(); // s.show(); //获取ApplicationConfig.properties配置文件,字符流缓冲 BufferedReader br = new BufferedReader(new FileReader("ApplicationConfig.properties")); //创建properties属性集合对象 Properties pro = new Properties(); //加载配置文件 pro.load(br); //关闭流 br.close(); //获取配置文件中的数据 String className = pro.getProperty("ClassName"); String methodName = pro.getProperty("MethodName"); //获取字节码class对象 Class c = Class.forName(className);//cn.properties.com.Student //创建反射实例 Constructor con = c.getConstructor(); Object o = con.newInstance(); //调用方法 Method method = c.getMethod(methodName);//show method.invoke(o); }
枚举
略