首页 > 代码库 > 类的加载的一个小问题

类的加载的一个小问题

前言

之前写了一篇文章专门介绍了一下类的加载和对象的创建流程,然后收到了一个博友的疑问,觉得蛮好的,在这里和大家分享下。

博文地址:【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

 

类的加载的一个小问题