Java基础8-一文读懂Java 代码块和执行顺序(一):https://developer.aliyun.com/article/1535666
构造代码块
位置:类成员的位置,就是类中方法之外的位置
作用:把多个构造方法共同的部分提取出来,共用构造代码块
调用:每次调用构造方法时,都会优先于构造方法执行,也就是每次new一个对象时自动调用,对 对象的初始化
class A{ int i = 1; int initValue;//成员变量的初始化交给代码块来完成 { //代码块的作用体现于此:在调用构造方法之前,用某段代码对成员变量进行初始化。 //而不是在构造方法调用时再进行。一般用于将构造方法的相同部分提取出来。 // for (int i = 0;i < 100;i ++) { initValue += i; } } { System.out.println(initValue); System.out.println(i);//此时会打印1 int i = 2;//代码块里的变量和成员变量不冲突,但会优先使用代码块的变量 System.out.println(i);//此时打印2 //System.out.println(j);//提示非法向后引用,因为此时j的的初始化还没开始。 // } { System.out.println("代码块运行"); } int j = 2; { System.out.println(j); System.out.println(i);//代码块中的变量运行后自动释放,不会影响代码块之外的代码 } A(){ System.out.println("构造方法运行"); } } public class 构造代码块 { @Test public void test() { A a = new A(); } }复制代码
静态代码块
位置:类成员位置,用static修饰的代码块 作用:对类进行一些初始化 只加载一次,当new多个对象时,只有第一次会调用静态代码块,因为,静态代码块 是属于类的,所有对象共享一份 调用: new 一个对象时自动调用 public class 静态代码块 { @Test public void test() { C c1 = new C(); C c2 = new C(); //结果,静态代码块只会调用一次,类的所有对象共享该代码块 //一般用于类的全局信息初始化 //静态代码块调用 //代码块调用 //构造方法调用 //代码块调用 //构造方法调用 } } class C{ C(){ System.out.println("构造方法调用"); } { System.out.println("代码块调用"); } static { System.out.println("静态代码块调用"); } }复制代码
Java代码块、构造方法(包含继承关系)的执行顺序
这是一道常见的面试题,要回答这个问题,先看看这个实例吧。
一共3个类:A、B、C其中A是B的父类,C无继承仅作为输出
A类:
public class A { static { Log.i("HIDETAG", "A静态代码块"); } private static C c = new C("A静态成员"); private C c1 = new C("A成员"); { Log.i("HIDETAG", "A代码块"); } static { Log.i("HIDETAG", "A静态代码块2"); } public A() { Log.i("HIDETAG", "A构造方法"); } }复制代码
B类:
public class B extends A { private static C c1 = new C("B静态成员"); { Log.i("HIDETAG", "B代码块"); } private C c = new C("B成员"); static { Log.i("HIDETAG", "B静态代码块2"); } static { Log.i("HIDETAG", "B静态代码块"); } public B() { Log.i("HIDETAG", "B构造方法"); } }复制代码
C类:
public class C { public C(String str) { Log.i("HIDETAG", str + "构造方法"); } }复制代码
执行语句:new B();
输出结果如下:
I/HIDETAG: A静态代码块 I/HIDETAG: A静态成员构造方法 I/HIDETAG: A静态代码块2 I/HIDETAG: B静态成员构造方法 I/HIDETAG: B静态代码块2 I/HIDETAG: B静态代码块 I/HIDETAG: A成员构造方法 I/HIDETAG: A代码块 I/HIDETAG: A构造方法 I/HIDETAG: B代码块 I/HIDETAG: B成员构造方法 I/HIDETAG: B构造方法复制代码
得出结论:
执行顺序依次为: 父类的静态成员和代码块 子类静态成员和代码块 父类成员初始化和代码快 父类构造方法 子类成员初始化和代码块 子类构造方法复制代码
注意:可以发现,同一级别的代码块和成员初始化是按照代码顺序从上到下依次执行
看完上面这个demo,再来看看下面这道题,看看你搞得定吗?
看下面一段代码,求执行顺序:
class A { public A() { System.out.println("1A类的构造方法"); } { System.out.println("2A类的构造快"); } static { System.out.println("3A类的静态块"); } } public class B extends A { public B() { System.out.println("4B类的构造方法"); } { System.out.println("5B类的构造快"); } static { System.out.println("6B类的静态块"); } public static void main(String[] args) { System.out.println("7"); new B(); new B(); System.out.println("8"); } }复制代码
执行顺序结果为:367215421548
为什么呢?
首先我们要知道下面这5点:
每次new都会执行构造方法以及构造块。构造块的内容会在构造方法之前执行。非主类的静态块会在类加载时,构造方法和构造块之前执行,切只执行一次。主类(public class)里的静态块会先于main执行。继承中,子类实例化,会先执行父类的构造方法,产生父类对象,再调用子类构造方法。所以题目里,由于主类B继承A,所以会先加载A,所以第一个执行的是第3句。
从第4点我们知道6会在7之前执行,所以前三句是367。
之后实例化了B两次,每次都会先实例化他的父类A,然后再实例化B,而根据第1、2、5点,知道顺序为2154。
最后执行8
所以顺序是367215421548