240
世界上有10种人,一种懂二进制,另一种不懂二进制。

Java的初始化执行顺序(父类static变量->子类static变量->父类成员变量->父类构造器->成员变量->构造器->main函数)

1. 引言

了解Java初始化的顺序,有助于理解Java的初始化机制和内存机制

顺序:父类static变量->子类static变量->父类成员变量->父类构造器->成员变量->构造器->main函数(说明:static变量包括static变量和static代码块,按位置顺序执行)

2. 样例

2.1 无继承的类的初始化顺序

public class TestClass {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("Creating new Cupboard() in main");
		new Cupboard();
		System.out.println("Creating new Cupboard() in main");
		new Cupboard();
		t2.f2(1);
		t3.f3(1);
	}

	static Table t2 = new Table();
	static Cupboard t3 = new Cupboard();
}

// : StaticInitialization.java
// Specifying initial values in a
// class definition.

class Bowl {
	Bowl(int marker) {
		System.out.println("Bowl(" + marker + ")");
	}

	void f(int marker) {
		System.out.println("f(" + marker + ")");
	}
}

class Table {
	static Bowl b1 = new Bowl(1);
	
	static{
		System.out.println("Table() static 1");
	}

	Table() {
		System.out.println("Table()");
		b2.f(1);
	}

	void f2(int marker) {
		System.out.println("f2(" + marker + ")");
	}
	
	Bowl b10 = new Bowl(10);
	
	{
		System.out.println("Table() non-static");
	}
	
	Bowl b11 = new Bowl(11);

	static Bowl b2 = new Bowl(2);
	
	static{
		System.out.println("Table() static 2");
	}
}

class Cupboard {
	Bowl b3 = new Bowl(3);
	static Bowl b4 = new Bowl(4);

	Cupboard() {
		System.out.println("Cupboard()");
		b4.f(2);
	}

	void f3(int marker) {
		System.out.println("f3(" + marker + ")");
	}

	static Bowl b5 = new Bowl(5);
}

输出的结果如下:

Bowl(1)
Table() static 1
Bowl(2)
Table() static 2
Bowl(10)
Table() non-static
Bowl(11)
Table()
f(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
f2(1)
f3(1)

2.2 有继承的类的初始化顺序

//: Beetle.java 
	// The full process of initialization. 
	 
	class Insect { 
	  int i = 9; 
	  int j; 
	  Insect() { 
	    prt("i = " + i + ", j = " + j); 
	    j = 39; 
	  }
	  static{
		  System.out.println("Insert static block0");
	  }
	  
	  static int x1 =  
	    prt("static Insect.x1 initialized"); 
	  static int prt(String s) { 
	    System.out.println(s); 
	    return 47; 
	  }
	  static{
		  System.out.println("Insert static block1");
	  }
	} 
	
	public class Beetle extends Insect { 
		  int k = prt("Beetle.k initialized"); 
		  Beetle() { 
		    prt("k = " + k); 
		    prt("j = " + j); 
		  } 
		  static int x2 = 
		    prt("static Beetle.x2 initialized"); 
		  static int prt(String s) { 
		    System.out.println(s); 
		    return 63; 
		  } 
		  public static void main(String[] args) { 
		    prt("Beetle constructor"); //flag 1
		    Beetle b = new Beetle(); //flag 2
		  } 
		} ///:~ 

输出的结果如下:

Insert static block0
static Insect.x1 initialized
Insert static block1
static Beetle.x2 initialized
Beetle constructor
i = 9, j = 0
Beetle.k initialized
k = 63
j = 39

//如果只把flag 1 那条语句注释掉,输出内容如下:
Insert static block0
static Insect.x1 initialized
Insert static block1
static Beetle.x2 initialized
i = 9, j = 0
Beetle.k initialized
k = 63
j = 39

//如果只把flag 2 那条语句注释掉,输出内容如下:
Insert static block0
static Insect.x1 initialized
Insert static block1
static Beetle.x2 initialized
Beetle constructor

3. 总结

只要按照这个顺序:父类static变量->子类static变量->父类成员变量->父类构造器->成员变量->构造器->main函数(说明:static变量包括static变量和static代码块,按位置顺序执行), 去推导初始化执行顺序就能得到正确的执行答案数据。

注意点:

1.若仅仅执行static方法,则只会执行该类及其父类的所有静态变量,而且静态变量只会被执行一次

2.当对象被new出来时,才会开始初始化该类及其父类的所有变量,按照以上的说的顺序执行

3.成员或者静态static变量若申明时不赋值,会被初始化相应类型的默认值,例如int是0,String是null等

4.可以用debug模式直接断点调试,跟着走一遍,就能看到代码是怎么初始化变量的(当然,自己先演练一遍,效果更好)

4.参考

Thinking in Java P113, P158

 

posted @ 2017-09-06 16:12  unionline  阅读(1089)  评论(0编辑  收藏  举报