【每日一题】JVM篇-类的实例化顺序

类的声明周期

加载、验证、准备、解析、初始化、使用、卸载

初始化的时机

  1. 遇到new、getstatic、putstatic、invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这4条指令的最常见的代码场景是:使用new关键字实例化对象的时候、读取或设置一个类的静态字段(被final修饰、已在编译器把结果放入常量池的静态字段除外)的时候、调用一个类的静态方法的时候
  2. 使用java.lang.reflect包的方法堆类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化
  3. 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化
  4. 当虚拟机启动时,用户需要指定一个要执行的主类(包含main方法的那个类),虚拟机会先初始化这个主类。

对于这四种会触发类进行初始化的场景,虚拟机规范使用了一个强烈的限定语:有且只有,这四种场景中的行为被称为对一个类进行主动引用。除此之外的所有引用类的方式,都不会触发初始化,称为被动引用
被动引用的例子
5. 通过子类引用父类的静态字段,不会导致子类初始化
6. 通过数组定义类引用类,不会触发此类的初始化
7. 常量在编译阶段会存入调用类的常量池中,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化

类加载的过程

  1. 加载
    1. 通过一个类的全限定名来获取定义此类的二进制字节流
    2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
    3. 在Java堆中生成一个代表这个类的Class对象,作为方法区这些数据的访问入口
  2. 验证
    1. 文件格式验证
    2. 元数据验证
    3. 字节码验证
    4. 符号引用验证
  3. 准备
  4. 解析
  5. 初始化

类初始化的过程

1.首先是父类的静态变量和静态代码块(看两者的书写顺序);
2.第二执行子类的静态变量和静态代码块(看两者的书写顺序);
3.第三执行父类的成员变量赋值
4.第四执行父类类的构造代码块
5.第五执行父类的构造方法()
6.第六执行子类的构造代码块
7.第七执行子类的构造方法();
总结,也就是说虽然客户端代码是new 的构造方法,但是构造方法确实是在整个实例创建中的最后一个调用。切记切记!!!

先是父类,再是子类。先是类静态变量和静态代码块,再是对象的成员变量和构造代码块及构造方法。
记住,构造方法最后调用!!!!成员变量优先构造代码块优先构造方法!!

你可能感兴趣的:(JVM)