类加载机制
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化来对这个类进行初始化。
加载:
就是将.class文件读入内存,并为之创建一个Class对象。
任何类被使用时,系统都会创建一个Class对象。
连接: 连接阶段负责把类的二进制数据合并到JRE中
验证:是否有正确的内部结构,并和其他类协调一致。
准备:负责为类的静态Field分配内存,并设置初始值。
解析:将类的二进制数据中的符号引用替换成直接引用。
初始化:该阶段主要是对静态Field进行初始化。
类的加载时机:
类加载器的概述
概述:类加载器负责将.class文件加载到内存,并为之创Class对象。
类加载器的组成:
Bootstrap ClassLoader 根类加载器
负责java核心类加载,比如System、String类,在JRE目录下lib的rt.jar
Extension ClassLoader 扩展类加载器
System ClassLoader 系统类加载器
负责JVM 启动时来自java命令的类
以及classpath环境变量下所指定的jar包和类路径
所以一般程序员的工程里的类和jar由系统类加载器加载、
反射
概述:java反射技术是指在程序运行时,可以对任意一个类,都能够获取它的属性和方法、对任意一个对象都能够调用它的方法,这种动态获取类信息和动态调用对象方法称为java的反射机制。
简单来说就是动态操作Class类:
成员变量:Field
构造方法:Constructor
成员方法:Method
获取Class对象的三种方式
//第一种方式
Person person = new Person();
Class c1 = person.getClass();
//第二种方式
Class c2 = Person.class;
// 第三种方式
Class c3 = Class.forName("com.alita.Person" );
构造方法
// 返回指定参数的公共构造器
Constructor constructor1 = c1.getConstructor(String.class, Integer.class);
// 返回指定参数的公共、私有、保护等构造器
Constructor constructor2 = c1.getDeclaredConstructor(String.class, Integer.class);
// 返回所有公共构造器
Constructor[] constructors1 =c1.getConstructors();
//所有构造器
Constructor[] constructors2 =c1.getDeclaredConstructors();
//创建对象
Person p = (Person) constructor1.newInstance();
成员变量
// 公共的成员变量
Field f1 = c1.getField("age" );
Field[] fields1 = c1.getFields();
// 包括私有,受保护的成员变量
Field f2 = c1.getDeclaredField("age" );
Field[] fields2 = c1.getDeclaredFields();
// 赋值
f1.setInt(person, 18);
f1.get(person);
成员方法
Method m1 = c1.getMethod("show" );
// 获取自己的包括其父类所有公共方法
c1.getMethods();
// 只获取自己的所有的公共方法
Method m2 = c1.getDeclaredMethod("show" ,String.class);
m1.invoke(person,"arg" );
Java的内省机制
概述:基于反射基础上实现的Java的内省(Introspector)机制能够专门针对JavaBean对象,提供方便快捷的反射操作。
// 获取JavaBean描述对象beanInfo
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
// 获取所有的 属性
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pds : propertyDescriptors) {
pds.getPropertyType();
pds.getReadMethod();
pds.getWriteMethod();
pds.getName();
}
// 手动创建 属性描述器,此时必须保证get 和 set 方法 同时 存在
PropertyDescriptor pd =new PropertyDescriptor("age" ,Person.class);
Method method = pd.getReadMethod();
int age = (int)method.invoke(person);