静态代码块、构造代码块和构造方法的执行顺序
静态代码块和构造代码块结构如下:
static {
静态语句代码块
}
{ 构造代码块 }
特点:静态初始化块只在类加载时执行,且只会执行一次,同时静态初始化块只能给静态变量赋值,不能初始化普通的成员变量。而构造代码块随着对象的创建而执行,每创建一次对象就执行一次构造代码块。优先级:静态代码块>构造代码块(普通初始化块)>构造方法。
1 public class Test_Static_Class {
2 //静态代码块
3 static {
4
5 System.out.println("静态代码块");
6 }
7 {
8 System.out.println("普通代码块1");
9 }
10
11 public Test_Static_Class() {
12 System.out.println("执行了构造方法");
13 }
14 //普通的成员方法
15 public void test() {
16 System.out.println("在方法中的普通代码块");
17 //普通的代码块
18 {
19 System.out.println("普通代码块");
20 }
21
22 }
23 public static void main(String[] args) {
24 System.out.println("执行了主方法");
25 System.out.println("--------------------");
26 new Test_Static_Class();
27 System.out.println("------第二次创建对象---------------");
28 new Test_Static_Class();
29 System.out.println("------第三次创建对象---------------");
30 new Test_Static_Class().test();
31 }
32
33 {
34 System.out.println("普通代码块2");
35 }
36 }
1. 多次创建对象,静态代码块只执行一次,且最先执行。
2. 接下来执行的是非静态语句代码块(即:构造代码块) ,会每创建一个对象执行一次,且多个构造代码块会由上到下的执行。
3. 在接下来执行的是构造方法,构造方法也是每创建一个对象就会执行一次。
4. 在接下来就是调用普通的方法中的代码块,执行的顺序,在方法中没有什么特殊的。
对于静态属性,与静态代码块一样,也是在类加载时就会被自动执行,属于整个类的属性。
静态方法只能直接访问静态成员,不能直接访问非静态成员,如果希望在静态方法中调用非静态变量,可以通过创建类的对象,然后通过对象来间接的访问非静态变量. 对于静态方法中也不能直接使用this对象。
若有继承的情况:
1 public class Demo { 2 public static class ClassA { 3 public ClassA() { 4 System.out.println("ClassA"); 5 } 6 7 static { 8 System.out.println("static A class"); 9 } 10 11 { 12 System.out.println("A class"); 13 } 14 } 15 16 public static class ClassB extends ClassA { 17 public ClassB() { 18 super(); 19 System.out.println("ClassB"); 20 } 21 22 static { 23 System.out.println("static B class"); 24 } 25 26 { 27 System.out.println("B class"); 28 } 29 public void print() { 30 System.out.println("B print"); 31 } 32 } 33 34 public static void main(String []args) { 35 new ClassB(); 36 } 37 38 static { 39 System.out.println("static Demo class"); 40 } 41 42 { 43 System.out.println("Demo class"); 44 } 45 46 }
结果:
static Demo class
static A class
static B class
A class
ClassA
B class
ClassB
原因:首先加载Demo类文件,执行Demo类中的static代码块;执行main函数中的new ClassB(),因为继承ClassA,加载ClassA,执行ClassA中的static代码块->加载ClassB,执行ClassB中的static代码块;
执行classA的构造代码块->执行classA的构造函数->执行classB的构造代码块->执行classB的构造函数
1 public class Demo {
2 public static class ClassA {
3 public ClassA() {
4 System.out.println("ClassA");
5 }
6 }
7
8 static {
9 System.out.println("static A class");
10 }
11
12 {
13 System.out.println("A class");
14 }
15
16 public static class ClassB {
17 public ClassB() {
18 System.out.println("ClassB");
19 }
20
21 static {
22 System.out.println("static B class");
23 }
24
25 {
26 System.out.println("B class");
27 }
28 public void print() {
29 System.out.println("B print");
30 }
31 }
32
33 public static void main(String []args) {
34 new ClassB();
35 }
36
37 }
让ClassB不在继承ClassA
结果:
1 public class ExA {
2 static {
3 System.out.println("父类--静态代码块");
4 }
5
6 public ExA() {
7 System.out.println("父类--构造函数");
8 }
9
10 {
11 System.out.println("父类--非静态代码块");
12 }
13
14 public static void main(String[] args) {
15 new ExB();
16 }
17 }
18
19 class ExB extends ExA {
20 static {
21 System.out.println("子类--静态代码块");
22 }
23 {
24 System.out.println("子类--非静态代码块");
25 }
26
27 public ExB() {
28 System.out.println("子类--构造函数");
29 }
30 }
结果:
父类--静态代码块
子类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
若一个类(用B表示)继承其他类(用A表示),则在new B()时,执行A的静态代码块(只执行一次)--->执行B的静态代码块(只执行一次)——>执行A的非静态代码块——>A的构造方法——>执行B的非静态代码块——>B的构造方法。