Static静态代码块以及各代码块之间的执行顺序

前言 在Java中,Static静态代码块、构造代码块、普通代码块、构造函数的执行顺序是一个java学习者必须掌握的基础,本篇博客旨在让你们能清除了解它们之间的执行顺序。javascript

代码块的分类

基本上代码块分为三种:Static静态代码块、构造代码块、普通代码块java

代码块执行顺序静态代码块——> 构造代码块 ——> 构造函数——> 普通代码块函数

继承中代码块执行顺序:父类静态块——>子类静态块——>父类代码块——>父类构造器——>子类代码块——>子类构造器学习

一、静态代码块(也叫静态块、静态初始化块)

Java静态代码块中的代码会在类加载JVM时运行,且只被执行一次,也就是说这些代码不须要实例化类就可以被调用。通常状况下,若是有些代码必须在项目启动的时候就执行的时候,就须要使用静态代码块,因此静态块经常使用来执行类属性的初始化!测试

关于Static静态代码块的五个小结点ui

一、Java静态代码块中的代码会在类加载JVM时运行,且只被执行一次 二、静态块经常使用来执行类属性的初始化 三、静态块优先于各类代码块以及构造函数,若是一个类中有多个静态代码块,会按照书写顺序依次执行 四、静态代码块能够定义在类的任何地方中除了方法体中【这里的方法体是任何方法体】 五、静态代码块不能访问普通变量spa

针对4中描述静态代码块不能存在任何方法体中的缘由其实也是很简单,因为普通方法是经过加载类,而后new出实例化对象,经过对象才能运行这个方法,而静态代码块只须要加载类以后就能运行了。对于静态方法,在类加载的时候,静态方法也已经加载了,可是咱们必需要经过类名或者对象名才能访问,也就是说相比于静态代码块,静态代码块是本身主动运行的,而静态方法是被动调用运行的。不论是哪一种方法,咱们须要明确静态代码块的存在在类加载的时候就自动运行了,而放在不论是普通方法仍是静态方法中,都是不能自动运行的。code

针对5中描述静态代码块不能访问普通变量,缘由一样简单。普通变量是被实例对象调用的,静态代码块中都不存在其实例对象,谈何调用变量?对象

Static静态代码块使用格式继承

static{
  ..............
}
复制代码

二、构造代码块(也叫构造初始化块)

听这名字就知道和构造方法离不开!没错,可是仍是和构造方法有着本质区别,咱们都知道,没个方法中均可以有不少构造方法,每建立一个对象其构造方法就执行一个,而一个构造方法能够建立N个对象,构造方法就比较“高冷”了,而构造代码块就比较“舔狗”了,只要该类实例了一个对象,构造代码就执行一次,利用每次建立对象的时候都会提早调用一次构造代码块特性,因此它能够作统计建立对象的次数功能。固然构造代码块用的相对少!

构造代码块小结

一、构造代码块在建立对象时被调用,每次建立对象都会调用一次 二、构造代码块优先于构造函数执行,同时构造代码块的运行依赖于构造函数 三、构造代码块在类中定义

针对2中的“依赖”可理解为若是不实例化对象(也就是不执行构造方法),构造代码块是不会执行的!

三、代码块(又叫普通代码块、初始化块)

代码块小结

一、普通代码块定义在方法体中 二、普通代码块与构造代码块的格式一致都是{} 三、普通代码块与构造代码块惟一能直接看出的区别是构造代码块是在类中定义的,而普通代码块是在方法体中定义的

执行顺序的代码测试

以上已经讲得差很少了,开始上代码了!

package com.gx.initializationblock;

public class Initializationblock {

    int intA;
    int intB;


    public Initializationblock() {
        System.out.println("无参构造器00000000");
    }

    public Initializationblock(int a) {
        System.out.println("一个参数的构造器");
        
    }


    {
        intA = 10;
        intB = 15;

        System.out.println("构造初始化块11111");
    }

    {
        System.out.println("构造初始化块22222");
    }

    {
    	
        System.out.println("构造初始化块33333");
    }

    //静态初始化块
    static {
        System.out.println("静态初始化块01010101");
    }

    static {
        System.out.println("静态初始化块0202020202");
    }
    public void method(){
    	{
    		System.out.println("普通初始化块");
    	}
    }
}
复制代码

测试demo

package com.gx.initializationblock;

/* 初始化块一 * 由于静态块是在类的初始化阶段完成的, * 所以在建立某个类的第二个对象时,该类的静态块就不会执行了 * * 在单个类中,静态初始化块,初始化块,构造器 * 多个类的继承中初始化块、静态初始化块、构造器的执行顺序 在继承中,前后执行父类A的静态块,父类B的静态块,最后子类的静态块,而后再执行父类A的非静态块和构造器,而后是B类的非静态块和构造器,最后执行子类的非静态块和构造器 */
public class Demo1 {
    public static void main(String[] args) {
        Initializationblock initializationblock = new Initializationblock();
        initializationblock.method();
        System.out.println("------------");
        //多打印几个对象的目的是:好看出Static静态代码块只执行一次!!!
        Initializationblock initializationblock2 = new Initializationblock(); //由于静态块是在类的初始化阶段完成的,所以在建立某个类的第二个对象时,该类的静态块就不会执行了
        initializationblock2.method();
        Initializationblock initializationblock3 = new Initializationblock();
        initializationblock3.method();
    }
}
复制代码

打印结果

静态初始化块01010101
静态初始化块0202020202
构造初始化块11111
构造初始化块22222
构造初始化块33333
无参构造器00000000
普通初始化块
------------
构造初始化块11111
构造初始化块22222
构造初始化块33333
无参构造器00000000
普通初始化块
构造初始化块11111
构造初始化块22222
构造初始化块33333
无参构造器00000000
普通初始化块
复制代码

得出结论:执行顺序静态代码块 > 构造代码块 > 构造函数 > 普通代码块

继承中各代码块的执行顺序

啥都不说了,直接撸代码:继承关系为 BaseThree——> BaseTwo——> BaseOne BaseOne类

package com.gx.initializationblock;

public class BaseOne {

    public BaseOne() {
        System.out.println("BaseOne构造器");
    }

    {
        System.out.println("BaseOne初始化块");
        System.out.println();
    }

    static {
        System.out.println("BaseOne静态初始化块");

    }

}
复制代码

BaseTwo类

package com.gx.initializationblock;

public class BaseTwo extends BaseOne {
    public BaseTwo() {
        System.out.println("BaseTwo构造器");
    }

    {
        System.out.println("BaseTwo初始化块");
    }

    static {
        System.out.println("BaseTwo静态初始化块");
    }
}
复制代码

BaseThree 类

package com.gx.initializationblock;

public class BaseThree extends BaseTwo {
    public BaseThree() {
        System.out.println("BaseThree构造器");
    }

    {
        System.out.println("BaseThree初始化块");
    }

    static {
        System.out.println("BaseThree静态初始化块");
    }
}
复制代码

测试demo2类

package com.gx.initializationblock;

/* 注:这里的ABC对应BaseOne、BaseTwo、BaseThree * 多个类的继承中初始化块、静态初始化块、构造器的执行顺序 在继承中,前后执行父类A的静态块,父类B的静态块,最后子类的静态块, 而后再执行父类A的非静态块和构造器,而后是B类的非静态块和构造器,最后执行子类的非静态块和构造器 */
public class Demo2 {
    public static void main(String[] args) {
        BaseThree baseThree = new BaseThree();
        System.out.println("-----");
        BaseThree baseThree2 = new BaseThree();

    }
}
复制代码

运行结果

BaseOne静态初始化块
BaseTwo静态初始化块
BaseThree静态初始化块
BaseOne初始化块

BaseOne构造器
BaseTwo初始化块
BaseTwo构造器
BaseThree初始化块
BaseThree构造器
-----
BaseOne初始化块

BaseOne构造器
BaseTwo初始化块
BaseTwo构造器
BaseThree初始化块
BaseThree构造器
复制代码

多个类的继承中初始化块、静态初始化块、构造器的执行顺序为:前后执行父类A的静态块,父类B的静态块,最后子类的静态块,而后再执行父类A的非静态块和构造器,而后是B类的非静态块和构造器,最后执行子类的非静态块和构造器【注:这里的ABC对应BaseOneBaseTwoBaseThree

结论:多个类的继承中初始化块、静态初始化块、构造器的执行顺序为:父类静态块——>子类静态块——>父类代码块——>父类构造器——>子类代码块——>子类构造器

若是本文对你有所帮助,请支持一下点个赞呗QnQ 最后,博主并非什么大牛,也会犯错!若有不正之处欢迎指正!感激涕零!

相关文章
相关标签/搜索