首页 > 代码库 > 类的加载的一个小问题
类的加载的一个小问题
前言
之前写了一篇文章专门介绍了一下类的加载和对象的创建流程,然后收到了一个博友的疑问,觉得蛮好的,在这里和大家分享下。
博文地址:【Java基础】Java类的加载和对象创建流程的分析
疑问
1 public class Test3 { 2 public static Test3 t = new Test3(); 3 4 { 5 System.out.println("blockA"); 6 } 7 8 static { 9 System.out.println("blockB");10 }11 12 public static void main(String[] args) {13 Test3 t1 = new Test3();14 }15 }
类在初始化的时候,是不是就可以被实例化?
分析
其实这个问题如果理解了类的加载和对象的创建流程,其实很容易理解的。
类的加载
简单的流程是:
1. 先加载静态内容,静态成员变量,静态代码块,静态方法。
2. 静态成员变量默认初始化,完成之后,静态成员变量显示初始化。
3. 执行静态的代码块。先执行父类的静态代码块,再执行子类的静态代码块。
4.类加载完成之后可以执行具体的对象创建和程序代码。
对象的创建
1.给对象分配内存空间,其实就是分配内存地址。
2.对类中的的非静态的成员变量开始默认初始化。
3.加载对应的构造方法,执行隐式三步
①有个隐式的super(); ②显示初始化(给所有的非静态的成员变量)③执行非静态构造代码块之后才开始执行本类的构造方法中的代码
4.对象创建完成
解答
针对上面的代码示例,我们可以分析下打印结果:
1. 执行main()方法,由于JVM中之前没有Test3.class信息,因此需要加载类Test3的Class文件到JVM中。
2. 根据类的加载原理,先加载静态内容,再加载非静态内容,因此首先加载的就是
public static Test3 t = new Test3();
这是一个静态实例化的代码,根据对象的创建流程,一步一步的执行,会在加载对应的构造方法时,执行隐式三步:Test3无显示继承的父类(默认继承超类Object),无非静态的成员变量,有非静态的构造代码块 --> 执行非静态的构造代码块,打印 "blockA"。
3. 第一个static 加载完成之后,继续往下执行其他的static,执行静态代码块,打印 "blockB"。
4. 类的加载完成
5. 回来执行main()方法中的 Test3 t1 = new Test3(); 执行隐式三步,得到打印结果:"blockA"。
因此最终的输出结果为:
1 blockA2 blockB3 blockA
类的加载的一个小问题