• 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. 仅初始化是静态变量和静态方法会被执行一次;非静态变量、非静态方法、构造器则是对象实例化一次执行一次。
  • 相关阅读:
    软件项目管理 第八章 软件项目的人员与沟通管理 课后习题参考答案——主编:李冰、张桥珍、刘玉娥
    抓包整理外篇——————状态栏[ 四]
    基于kubeasz部署高可用k8s集群
    计算机网络第二章习题_物理层
    智慧城市-疫情流调系列2-Prompt-UIE信息抽取
    chrome控制台怎么看hover的样式
    数据结构上机实验——栈和队列的实现、栈和队列的应用、进制转换、约瑟夫环问题
    Zookeeper-集群介绍与核心理论
    【C++设计模式之模板模式】分析及示例
    Rust开发问题汇总
  • 原文地址:https://blog.csdn.net/Saintmm/article/details/125596829