构造器初始化流程顺序 主要是包括这几层关系:
非静态成员属性、静态成员属性、非静态代码块、静态代码块、构造器,这5者的关系.
对于这几层关系 ,我分开来阐述,避免在一个类中统一归纳,比较麻烦,不易理解。
1.非静态成员属性
可以看到w1、w2、w3 散列于House()构造方法之间,但从结果来看,是先初始化w1,w2,w3,最后调用构造方法
package com.caolh._5InitializationAcleanup;//: initialization/_5_7OrderOfInitialization.java
// Demonstrates initialization order.
// When the constructor is called to create a
// Window object, you'll see a message:
class Window {
Window(int marker) { System.out.println("Window(" + marker + ")"); }
}
class House {
Window w1 = new Window(1); // w1在构造器之前调用
House() {
// Show that we're in the constructor:
System.out.println("House()");
w3 = new Window(33); // Reinitialize w3
}
Window w2 = new Window(2); // w1在构造器之后调用
void f() { System.out.println("f()"); }
Window w3 = new Window(3); // At end
}
public class _5_7OrderOfInitialization {
public static void main(String[] args) {
House h = new House();
h.f(); // Shows that construction is done
}
} /* Output:
Window(1)
Window(2)
Window(3)
House()
Window(33)
f()
*///:~
2.引入静态成员属性,初始化过程
看测试结果:记住几个原则:
只是静态属性的引用,是触发的类加载 ,此时不执行构造方法,类加载只执行一次,这些值存在于常量池;而创建对象,是也可以触发类加载的(如果之前没有,那么会首先执行静态属性初始化),这些值存在于堆栈,而且此时才会执行构造器方法。
1.先执行 静态的成员属性初始化,再执行非静态成员属性初始化。
2.静态成员属性初始化只执行1次,就是在调用该类的静态属性或静态方法,或者是第一次创建对象的时候;以后多次创建,不执行静态属性初始化了
package com.caolh._5InitializationAcleanup;//: initialization/StaticInitialization.java
// Specifying initial values in a class definition.
class Bowl {
Bowl(int marker) {
System.out.println("Bowl(" + marker + ")");
}
void f1(int marker) {
System.out.println("f1(" + marker + ")");
}
}
class Table {
static Bowl bowl1 = new Bowl(1);
Table() {
System.out.println("Table()");
bowl2.f1(1);
}
void f2(int marker) {
System.out.println("f2(" + marker + ")");
}
static Bowl bowl2 = new Bowl(2);
}
class Cupboard {
Bowl bowl3 = new Bowl(3);
static Bowl bowl4 = new Bowl(4);
Cupboard() {
System.out.println("Cupboard()");
bowl4.f1(2);
}
void f3(int marker) {
System.out.println("f3(" + marker + ")");
}
static Bowl bowl5 = new Bowl(5);
}
public class StaticInitialization {
public static void main(String[] args) {
System.out.println("Creating new Cupboard() in main");
new Cupboard();
System.out.println("Creating new Cupboard() in main");
new Cupboard();
table.f2(1);
cupboard.f3(1);
}
static Table table = new Table();
static Cupboard cupboard = new Cupboard();
} /* Output:
Bowl(1)
Bowl(2)
Table()
f1(1)
---------------
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
----------------------
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
------------------------
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
--------------------------
f2(1)
f3(1)
*///:~
3.引入静态代码块
static 的cup1 定义和静态代码块先后顺序无所谓,
只执行(1),直接触发静态代码块。
只执行(2),两次创建对象,静态代码块只执行1次
package com.caolh._5InitializationAcleanup;//: initialization/ExplicitStatic.java
// Explicit static initialization with the "static" clause.
class Cup {
Cup(int marker) {
System.out.println("Cup(" + marker + ")");
}
void f(int marker) {
System.out.println("f(" + marker + ")");
}
}
class Cups {
static Cup cup1;
static {
cup1 = new Cup(1);
cup2 = new Cup(2);
}
static Cup cup2;
Cups() {
System.out.println("Cups()");
}
}
public class ExplicitStatic {
public static void main(String[] args) {
System.out.println("Inside main()");
//Cups.cup1.f(99); // (1)
}
static Cups cups1 = new Cups(); // (2)
static Cups cups2 = new Cups(); // (2)
} /* Output:
Cup(1)
Cup(2)
Cups()
Cups()
Inside main()
*///:~
4.非静态代码块引入
可以看到,对象创建2次,非静态代码块执行了2次
package com.caolh._5InitializationAcleanup;//: initialization/_5_7_4Mugs.java
// Java "Instance Initialization."
class Mug {
Mug(int marker) {
System.out.println("Mug(" + marker + ")");
}
void f(int marker) {
System.out.println("f(" + marker + ")");
}
}
public class _5_7_4Mugs {
Mug mug1;
Mug mug2;
{
mug1 = new Mug(1);
mug2 = new Mug(2);
System.out.println("mug1 & mug2 initialized");
}
_5_7_4Mugs() {
System.out.println("Mugs()");
}
_5_7_4Mugs(int i) {
System.out.println("Mugs(int)");
}
public static void main(String[] args) {
System.out.println("Inside main()");
new _5_7_4Mugs();
System.out.println("new Mugs() completed");
new _5_7_4Mugs(1);
System.out.println("new Mugs(1) completed");
}
} /* Output:
Inside main()
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs()
new Mugs() completed
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs(int)
new Mugs(1) completed
*///:~