大家先看下下面這段代碼的結(jié)果應(yīng)該是多少?
public class ParentObjectInit {
public void test() {
}
public ParentObjectInit() {
test();
}
public static void main(String[] args) {
new ChildObjectInit();
}
}
class ChildObjectInit extends ParentObjectInit {
private int instanceValue = 20;
public void test() {
System.out.println("instance1 value is: " + instanceValue);
}
}
結(jié)果調(diào)試出來是20還是0呢?
*******************************************************************
(1)類中屬性缺省初始化和顯示初始化:
*******************************************************************
public class ParentObjectInit {
public void test() {
}
public ParentObjectInit() {
test();
}
public static void main(String[] args) {
//先調(diào)用父類ParentObjectInit 的構(gòu)造器
new ChildObjectInit();
}
}
class ChildObjectInit extends ParentObjectInit {
//屬性顯示初始化在調(diào)用本類構(gòu)造器之后
private int instanceValue = 20;
//進(jìn)入ChildObjectInit類的構(gòu)造器后,instanceValue值為20
public ChildObjectInit() {
System.out.println("instance1 value is: " + instanceValue);
}
// 在調(diào)用ChildObjectInit類構(gòu)造器前打印
public void test() {
System.out.println("instance1 value is: " + instanceValue);
}
}
過程如下:
上面程序可以說明的是:直到調(diào)用完父類ParentObjectInit 的構(gòu)造方法之后,接著才對其成員變量instanceValue 顯式的初始化操作,即將賦值20。
上面代碼中的private int instanceValue = 20;定義應(yīng)看成兩部分:第一部分是定義變量,第二部分是給變量賦值。非static屬性定義(缺省初始化)位于父類ParentObjectInit 構(gòu)造方法之前,非static屬性顯示賦值位于父類ParentObjectInit 構(gòu)造方法之后。
在父類ParentObjectInit 的構(gòu)造方法執(zhí)行時(shí),根據(jù)多態(tài)性,它會去調(diào)用子類中定義的test()方法,可是,這時(shí)候,子類中的成員變量還沒執(zhí)行顯式初始化操作, 對于private int instanceValue = 20;定義,instanceValue 的值為默認(rèn)的初始化值0,所以,這時(shí)候在test方法中打印出的值為0。
備注:
private int instanceValue = 20;改為static修飾,其結(jié)果就是20,因?yàn)閟tatic屬性在構(gòu)造器調(diào)用之前就已經(jīng)初始化了,并之后不會改變,屬于整個(gè)類共享。
*******************************************************************
(2)類中對象初始化流程:
*******************************************************************
class Bowl {
Bowl(int marker) {
System.out.println("Bowl(" + marker + ")");
}
}
class Cupboard {
//非靜態(tài)初始化塊
{
Bowl b1 = new Bowl(1);
}
//靜態(tài)初始化塊
static{
Bowl b2 = new Bowl(2);
}
/**
* 非靜態(tài)實(shí)例屬性
*/
Bowl b3 = new Bowl(3);
/**
* 靜態(tài)實(shí)例屬性
*/
static Bowl b4 = new Bowl(4);
Cupboard() {
System.out.println("Cupboard()");
}
void f3(int marker) {
System.out.println("f3(" + marker + ")");
}
/**
* 靜態(tài)實(shí)例屬性
*/
static Bowl b5 = new Bowl(5);
}
class StaticDataInit {
public static void main(String[] args) {
Cupboard t3 = new Cupboard();
t3.f3(1);
}
/**
* 和在main()里面用Cupboard t3 = new Cupboard();結(jié)果等價(jià)
*/
// static Cupboard t3 = new Cupboard();
}
運(yùn)行結(jié)果為:
Bowl(2) 先調(diào)用static初始化塊
Bowl(4) 順序初始化static屬性b4和b5
Bowl(5) ...
Bowl(1) 調(diào)用非static初始化塊
Bowl(3) 調(diào)用非static實(shí)例屬性
Cupboard() 調(diào)用類Cupboard的構(gòu)造器
f3(1) 對象t3調(diào)用f3方法
備注:如果將上面程序最后一句 static Cupboard t3 = new Cupboard();
注釋解開。
運(yùn)行結(jié)果為:
//static Cupboard t3 = new Cupboard();初始化的結(jié)果
Bowl(2)
Bowl(4)
Bowl(5)
Bowl(1)
Bowl(3)
Cupboard()
//創(chuàng)建對象t3并調(diào)用方法f3的結(jié)果
Bowl(1)
Bowl(3)
Cupboard()
f3(1)
//說明static屬性和static塊只在對象第一次初始化或static屬性第一次初始化時(shí)賦值,以后不變
************************************************************************
形如:
public class A{
private int a = 100;
public A(){
//...
}
public static void main(String[] args){
new A();
}
}
//屬性a的缺省值為0,在調(diào)用構(gòu)造器A()之前,屬性a的值是0。
//僅當(dāng)調(diào)用到構(gòu)造器A()后才將100顯示地賦給屬性a,之后再執(zhí)行構(gòu)造器中的邏輯。
總結(jié):當(dāng)一個(gè)類A中的對象a初始化時(shí),依次先初始化其static初始化塊,static屬性,非static初始化塊(...)和非static屬性(缺省初始化)。然后再調(diào)用類A的構(gòu)造器對A中的屬性進(jìn)行顯示初始化。