• [Java]java类的加载:初始化


    在jvm中,类的生命周期分为七个阶段:加载 (Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化 (Initialization)、使用(Using)和卸载(Unloading)。

    这里就加载阶段中“类的初始化”阶段做说明测试,以解面试题。

    类的初始化是类的加载过程的最后一个步骤。初始化阶段就是执行类构造器()方法的过程。()并不是程序员在Java代码中直接编写 的方法,它是Javac编译器的自动生成物。

    Java虚拟机会保证在子类的()方法执行前,父类的()方法已经执行 完毕。
    因此,可以测试得出

    父类初始化(静态块顺序执行、变量赋值操作执行)>子类初始化
    即为执行顺序:
    父类静态块>子类静态块>父类变量和代码块>父类构造>子类变量和代码块>子类构造

    代码如下:

    
    public class SuperClass {
    
        public static int A = 1;
        
    
        static {
            System.out.println("A赋值");
            A = 2;
        }
    
        static {
            System.out.println("SuperClass init!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    
    public class SubClass extends SuperClass {
    
        public static int B = A;
        static {
            System.out.println("SubClass init,B赋值!");
            B = 3;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    执行SuperLoaderTest 类main方法

    public class SuperLoaderTest {
    
        public static void main(String[] args) {
            System.out.println(SubClass.B);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    最后输出结果为

    A赋值
    SuperClass init!
    SubClass init,B赋值!
    3
    
    • 1
    • 2
    • 3
    • 4

    但也有不需要执行父类初始化的情况,如果子类中存在final修饰的常量,在SubClass 中添加final修饰常量HELLOWORLD

    
    public class SubClass extends SuperClass {
    
        public static int B = A;
        static {
            System.out.println("SubClass init,B赋值!");
            B= 3;
        }
    
        public static final String HELLOWORLD = "hello world";
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    修改并执行SuperLoaderTest 类main方法

    public class SuperLoaderTest {
    
        public static void main(String[] args) {
            System.out.println(SubClass.HELLOWORLD);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    最后输出结果为

    hello world
    
    • 1

    此时不需要初始化父类,因为也并不需要初始化子类。
    因为 使用finall修饰的常量在引用时,会因为编译阶段已经进入到引用类的常量池了,不会引用到定义常量的类,不会触发常量类的初始化。
    即为在案例中,SubClass类中 final修饰的常量 HELLOWORLD在编译时已经进入到了SuperLoaderTest 常量池,因此程序执行时,不会初始化SubClass类,class如下图:
    在这里插入图片描述

  • 相关阅读:
    安装SQL Server详细教程
    Spring底层原理(二)
    Java之Map、三种Map遍历方式、HashMap、TreeMap、IO流、Properties、反射、获取类对象的三种方式、注解、元注解、工厂模式、装饰器
    归并(merge)排序
    《深入理解java虚拟机 第三版》学习笔记一
    shell中hiveSQL的split
    使用conda管理虚拟环境
    python调用函数详解
    数组----柔性数组
    SQLite事务处理
  • 原文地址:https://blog.csdn.net/mdwsmg/article/details/126875631