前言 在Java中,Static静态代码块、构造代码块、普通代码块、构造函数的执行顺序是一个java学习者必须掌握的基础,本篇博客旨在让大家能清除了解它们之间的执行顺序。
基本上代码块分为三种:Static静态代码块、构造代码块、普通代码块
代码块执行顺序 静态代码块——> 构造代码块 ——> 构造函数——> 普通代码块
继承中代码块执行顺序: 父类静态块——>子类静态块——>父类代码块——>父类构造器——>子类代码块——>子类构造器
Java静态代码块中的代码会在类加载JVM时运行,且只被执行一次,也就是说这些代码不需要实例化类就能够被调用。一般情况下,如果有些代码必须在项目启动的时候就执行的时候,就需要使用静态代码块,所以静态块常用来执行类属性的初始化!
1、Java静态代码块中的代码会在类加载JVM时运行,且只被执行一次 2、静态块常用来执行类属性的初始化 3、静态块优先于各种代码块以及构造函数,如果一个类中有多个静态代码块,会按照书写顺序依次执行 4、静态代码块可以定义在类的任何地方中除了方法体中【这里的方法体是任何方法体】 5、静态代码块不能访问普通变量
针对4中描述静态代码块不能存在任何方法体中的原因其实也是很简单,由于普通方法是通过加载类,然后new出实例化对象,通过对象才能运行这个方法,而静态代码块只需要加载类之后就能运行了。对于静态方法,在类加载的时候,静态方法也已经加载了,但是我们必须要通过类名或者对象名才能访问,也就是说相比于静态代码块,静态代码块是自己主动运行的,而静态方法是被动调用运行的。 不管是哪种方法,我们需要明确静态代码块的存在在类加载的时候就自动运行了 ,而放在不管是普通方法还是静态方法中,都是不能自动运行的。
针对5中描述静态代码块不能访问普通变量,原因同样简单。普通变量是被实例对象调用的,静态代码块中都不存在其实例对象,谈何调用变量?
static{ .............. } 复制代码
听这名字就知道和构造方法离不开!没错,但是还是和构造方法有着本质区别,我们都知道,没个方法中都可以有很多构造方法,每创建一个对象其构造方法就执行一个,而一个构造方法可以创建N个对象,构造方法就比较“高冷”了,而构造代码块就比较“舔狗”了,只要该类实例了一个对象,构造代码就执行一次,利用每次创建对象的时候都会提前调用一次构造代码块特性,所以它可以做统计创建对象的次数功能。当然构造代码块用的相对少!
1、构造代码块在创建对象时被调用,每次创建对象都会调用一次 2、构造代码块优先于构造函数执行,同时构造代码块的运行依赖于构造函数 3、 构造代码块在类中定义
针对2中的“ 依赖 ”可理解为如果不实例化对象(也就是不执行构造方法),构造代码块是不会执行的!
代码块小结
1、普通代码块定义在方法体中
2、普通代码块与构造代码块的格式一致都是 {}
3、普通代码块与构造代码块唯一能直接看出的区别是 构造代码块是在类中定义的,而普通代码块是在方法体中定义的
以上已经讲得差不多了,开始上代码了!
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
对应 BaseOne
、 BaseTwo
、 BaseThree
】
结论:多个类的继承中初始化块、静态初始化块、构造器的执行顺序为: 父类静态块——>子类静态块——>父类代码块——>父类构造器——>子类代码块——>子类构造器
如果本文对你有所帮助,请支持一下点个赞呗QnQ 最后,博主并不是什么大牛,也会犯错!如有不正之处欢迎指正!感激不尽!