持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情
1. 反射-类的加载
1.1 类的加载概述
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化三步来实现对这个类进行初始化。
(1) 加载
就是指将class文件读入内存,并为之创建一个Class对象;
任何类被使用时系统都会建立一个Class对象。
(2)连接
a. 验证: 是否有正确的内部结构,并和其他类协调一致;
b. 准备: 负责为类的静态成员分配内存,并设置默认初始化值;
c. 解析:把类中的符号引用转换为直接引用。
(3) 初始化
a. main方法所在的类在加线时,直接就先初始化;
b. new一个类的对象,一定会先完成类的初始化;
c. 调用该类的静态变量(final的常量除外)和静态方法;
d. 使用java.lang.reflect包的方法对类进行反射调用;
e. 当初始化一个类,如果其父类没有被初始化,则先会初始化他的父类。
1.2 类的加载时机
a. 创建类的实例;
b. 访问类的静态变量,或者为静态变量赋值;
c. 调用类的静态方法;
d. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象;
f. 初始化某个类的子类;
e. 直接使用java.exe命令来运行某个主类。
2. 反射-类加载器
2.1 类加载器的概述
负责将.class文件加载到内在中,并为之生成对应的Class对象。
2.2 类加载器的分类
(1) Bootstrap ClassLoader 根类加载器
(2) Extension ClassLoader 扩展类加载器
(3) Sysetm ClassLoader 系统类加载器
2.3 类加载器的作用
(1) Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载,比如System,String等,在JDK中JRE的lib目录下rt.jar文件中。
(2) Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载,在JDK中JRE的lib目录下ext目录。
(3) Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath 环境变量所指定的jar包和类路径。
3. 反射-反射概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个 类的所有属性和方法。对于任意一个对象,都能够调用它的任意一个方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。
4. 反射-获取class对象
4.1 获取class对象三种方式
(1) Object类的getClass()方法
(2) 静态属性class
(3) Class类中静态方法forName()
4.2 获取class对象三种方式代码示例
getClass()方法
import java.util.Date;
public class test {
public static void main(String[] args) {
Date date=new Date();
System.out.println(date.getClass());
}
}
类的静态属性class
import java.util.Date;
public class test {
public static void main(String[] args) throws Exception{
System.out.println(Date.class);
}
}
Class.forName()方法
import java.lang.Class;
public class test {
public static void main(String[] args) throws Exception{
Class<?> date =Class.forName("java.util.Date");
System.out.println(date);
}
}
除了getClass()方法会实例化对象之外,其他的两种不会产生实例化对象。
5. 反射-通过反射实例化对象
通过反射实例化对象方法:对象.newInstance()
newInstance()方法内部实际上调用了无参数构造方法,必须保证无参构造存在才可以
import java.lang.Class;
import java.util.Date;
public class test {
public static void main(String[] args) throws Exception{
//通过反射机制,获取Class,通过Class来实例化对象
Class<?> cl=Class.forName("java.util.Date");
//newInstance() 这个方法会调用Date这个类的无参数构造方法,完成对象的创建。
// 重点是:newInstance()调用的是无参构造,必须保证无参构造是存在的!
Object object=cl.newInstance();
System.out.println(object);
}
}