• Java类初始化、实例化流程你真的清楚吗


    一、前言

    最近在SpringAOP的源码,里面涉及到一些类初始化、实例化的顺序,比如AbstractAutoProxyCreator的触发在初始化 bean 之后,实例化 bean之前。特写此文记录一下。

    二、流程

    1、类初始化流程

    1. 想创建一个类的实例,就需要先加载并初始化该类;
    2. 想要初始化一个子类,就需要先初始化父类(extends);
    3. 所谓类的初始化就是执行<clinit>()方法:
      • <clinit>()方法由静态类变量显式的赋值代码 和 静态代码块组成(static关键字);
      • 并且<clinit>()方法只会执行一次。

    2、类实例化流程

    实例化一个类时,就是执行<init>()方法:

    1. <init>()方法可能会重载多个,因为有几个构造器就有几个<init>()方法;
    2. <init>()方法由非静态实例变量显示赋值代码、非静态代码块、对应构造器代码组成;
    3. 非静态实例变量显示赋值代码、非静态代码块代码从上到下顺序执行(谁先出现谁先加载),构造器的代码最后执行。
    4. 每次创建实例对象时,都会调用相应的构造器,即执行对应的<init>()方法;
    5. <init>()方法的首行是super()或super(Object …),即对应父类的<init>()方法,也就是说类实例化也是先实例化父类。

    3、方法重写过程

    1> 方法重写正是对象多态性的体现:

    1. 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码;
    2. 非静态方法默认的调用对象是this,即:非静态方法前面有一个默认的对象this;
    3. this对象在构造器(<init>()方法)中其实就是正在创建的对象;

    2> 不可被重写的方法?

    • final方法
    • 静态方法
    • private等子类不可见的方法

    三、验证

    1、代码案例

    创建一个父类Father、一个子类Son(extends Father);

    1)Father

    package com.saint.base.base;
    
    /**
     * @author Saint
     */
    public class Father {
    
        // 构造器
        Father() {
            System.out.println("father constructor(1)");
        }
    
        // 静态代码块
        static {
            System.out.println("father static code block(2)");
        }
    
        // 普通代码块
        {
            System.out.println("father common code block(3)");
        }
    
        // 静态成员变量
        private static int i = staticMember();
    
        // 成员变量
        private int j = member();
    
        /**
         * 静态方法
         */
        public static int staticMember() {
            System.out.println("father static method for static member(4)");
            return 1;
        }
    
        /**
         * 成员方法
         */
        public int member() {
            System.out.println("father method for common member(5)");
            return 1;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    2)Son

    package com.saint.base.base;
    
    /**
     * @author Saint
     */
    public class Son extends Father{
    
        // 构造器
        Son() {
            // super()写或不写,在子类构造器中一定会先调用父类的构造器
    //        super();
            System.out.println("son constructor(6)");
        }
    
        // 静态代码块
        static {
            System.out.println("son static code block(7)");
        }
    
        // 普通代码块
        {
            System.out.println("son common code block(8)");
        }
    
        // 静态成员变量
        private static int i = staticMember();
    
        // 成员变量
        private int j = member();
    
        /**
         * 静态方法
         */
        public static int staticMember() {
            System.out. println("son static method for static member(9)");
            return 1;
        }
    
        /**
         * 成员方法
         */
        public int member() {
            System.out.println("son method for common member(10)");
            return 1;
        }
    
        public static void main(String[] args) {
            System.out.println("---------第1次实例化Son对象----------");
            Son son1 = new Son();
            System.out.println();
            System.out.println("---------第二次实例化Son对象----------");
            Son son2 = new Son();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    2、Son类main()运行结果

    在这里插入图片描述

    1)结果分析

    1. 实例化子类时要先实例化父类;
    2. 先加载父类静态变量和静态代码块,再加载子类静态变量和静态代码块;
    3. 若子类重写父类方法,则父类调用的是子类方法代码;
    4. 然后再先加载父类非静态变量和非静态代码块、构造方法,再加载子类非静态变量和非静态代码块、构造方法;
    5. 仅初始化是静态变量和静态方法会被执行一次;非静态变量、非静态方法、构造器则是对象实例化一次执行一次。
  • 相关阅读:
    06.论Redis持久化的几种方式
    wxPython 布局调试技巧
    DES算法揭秘:数据加密的前沿技术
    Dockerfile指令与Docker-compose容器编排-搭建docker私有仓库
    M401H_山东移动_SM0_SD46_国科6323芯片_安卓4_AI语音_免拆卡刷固件包
    [生活][杂项] 上班党的注意事项
    【技术分享】OSPFv3基本原理
    SpringBoot项目的创建(一):通过idea的Spring Initializr来创建(需联网以下载SpringBoot相关的模板)
    NX二次开发-调内部函数UGS::UICOMP_enum::set_width(int)更改BlockUI的枚举控件宽度
    C#操作modbus
  • 原文地址:https://blog.csdn.net/Saintmm/article/details/125596829