Java的两种类加载方式
一 :隐式加载
通过直接new对象的方式加载,再java运行过程中发现new关键字,会隐式调用类加载器。这种方式可以调用类的空参和带参构造
二 :显示加载
通过loadClass和forName这种加载方式需要通过newInstance方法生成对象的实例,这种方式不能调用带参构造,调用带参构造需要反射调用newInstance方法
loadClass和forName的区别
首先了解一下类装载的过程
1 加载 将类的class字节码文件生成class对象
2 连接
连接分三步
1 校验 验证字节码文件的安全性
2 准备 为类变量分配内存空间 并设置初始值 类变量随类型信息存放在方法区中
3 解析 JVM常量池内符号引用转化为直接引用
3 初始化 执行类变量赋值 和静态代码块
LoadClass源码
传入的是fasle 里面调用的resolveClass是不会执行的 我们进入看看这个方法的作用
这个方法是用来确认是否连接这个类的 默认是false说明 loadClass得到的class对象只完成了类装载过程的第一步加载
我们举个例子
也就是说forName会执行Static代码 表示forName他会初始化我们这个类
forName源码
我们找到forName的重载方法
forName得到的class是已经完成初始化的
是否在类装载的时候连接是通过initialize属性 默认是true
loadClass得到的class是还没有完成连接的
是否连接通过resolveClass 属性 默认false
列举一个forName的使用场景
连接MySQL数据库时
这个driver他返回Driver对象是靠里面的静态代码块的 因此呢 如果使用ClassLoader 是不行的 需要用forName
loadClass场景
在SpringIOC中,在资源加载器获取要读入的资源的时候以及读取一些bean的配置的时候,是以classpath的方式加载 需要使用ClassLoader.loadClass 方法 。
之所以这样做是和SpringIOC的lazyLoad有关 SpringIOC为了提高加载速度,因此大量使用了延迟加载技术,而使用ClassLoader不需要执行类中的初始化代码 还有连接等步骤,这样做可以加快加载速度,把了类的初始化工作留到类实际使用的时候再去完成。