类的加载和加载时机
- A:类的加载概述
-
- 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
- 加载
- 就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。
连接
- 验证 是否有正确的内部结构,并和其他类协调一致
- 准备 负责为类的静态成员分配内存,并设置默认初始化值
- 解析 将类的二进制数据中的符号引用替换为直接引用
初始化
B:加载时机
- 创建类的实例
- 访问类的静态变量,或者为静态变量赋值
- 调用类的静态方法
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类
反射概述
反射就是动态加载一个指定的类,并获取该类中的所有的内容。而且将字节码文件封装成对象,
并将字节码文件中的内容都封装成对象,这样便于操作这些成员。
简单说:反射就是对一个类进行解剖。
反射的好处:增强了程序的扩展性。
A:反射概述
- JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
- 对于任意一个对象,都能够调用它的任意一个方法和属性;
- 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
- 要想解剖一个类,必须先要获取到该类的字节码文件对象。
- 而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。
B:三种方式
- a:Object类的getClass()方法,判断两个对象是否是同一个字节码文件
- b:静态属性class,锁对象
- c:Class类中静态方法forName(),读取配置文件
反射的基本步骤:
- 获得Class对象,就是获取到指定的名称的字节码文件对象。
- 实例化对象,获得类的属性、方法或构造函数。
- 访问属性、调用方法、调用构造函数创建对象。
具体使用
1)、获取字节码文件的三种方式栗子(Person类已有):
//第一种方式 Class类中静态方法forName(),读取配置文件
Class clazz1 = Class.forName("com.learn.bean.Person");
//第二种方式 静态属性class,锁对象.线程时,曾经使用
Class clazz2 = Person.class;
//第三种方式
Person p = new Person();
Class clazz3 = p.getClass();
2)、反射类的成员方法:
Class clazz = Person.class;
Method method = clazz.getMethod(methodName, new Class[]{paramClazz1, paramClazz2});
method.invoke();
3)、反射类的构造方法:
Constructor con = clazz.getConstructor(new Class[]{paramClazz1, paramClazz2,...})
con.newInstance(params...)
4)、反射类的属性:
Field field = clazz.getField(fieldName);
field.setAccessible(true);
field.setObject(value);
5)、如果要使用原类的私有方法,需要使用暴力反射
public static void method() throws Exception {
Class clazz = Class.forName("com.learn.bean.Person");
//想要获取私有方法。必须用getDeclearMethod();
Method method = clazz.getDeclaredMethod("method", null);
// 私有方法不能直接访问,因为权限不够。非要访问,可以通过暴力的方式。一般很少用,因为私有就是隐藏起来,所以尽量不要访问。
method.setAccessible(true);
}