在理解这两个区别前,需要弄清楚java类的加载机制。
类加载机制
- 加载。加载过程完成以下三件事:
- 通过类的完全限定名称获取定义该类的二进制字节流。
- 将该字节流表示的静态存储结构转换为方法区的运行时存储结构。
- 在内存中生成一个代表该类的 Class 对象,作为方法区中该类各种数据的访问入口。
- 验证。确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
- 准备。类变量是被 static 修饰的变量,准备阶段为类变量分配内存并设置初始值(一般为
0
或false
或null
),使用的是方法区的内存。实例变量不会在这阶段分配内存,它会在对象实例化时随着对象一起被分配在堆中。应该注意到,实例化不是类加载的一个过程,类加载发生在所有实例化操作之前,并且类加载只进行一次,实例化可以进行多次。特别的,类静态常量直接设置值。 - 解析。将常量池的符号引用替换为直接引用的过程。其中解析过程在某些情况下可以在初始化阶段之后再开始,这是为了支持 Java 的动态绑定。
- 初始化。初始化阶段才真正开始执行类中定义的 Java 程序代码。初始化阶段是虚拟机执行类构造器
<clinit>()
方法的过程。在准备阶段,类变量已经赋过一次系统要求的初始值,而在初始化阶段,根据程序员通过程序制定的主观计划去初始化类变量和其它资源。
区别
二者均是调用了 ClassLoad
的 loadClass(String name, boolean resolve)
方法。
不同的是 参数 resolve
取值不同。 Class.forName(String name)
取 true
,loadClass(String name)
取 false
。
1 | /** |
resolve默认是false
不链接,不进行链接意味着不进行上述2、3、4步骤,那么静态块和静态对象就不会得到执行。
测试
1 | public class Test{ |
输出为:
1 | 1----------------------- |