Java 構造器初始化
阿新 • • 發佈:2019-02-06
可以用構造器來進行初始化,但是成員變數的自動初始化是在構造器被呼叫之前發生的,即成員變數的自動初始化不能被阻止。
如以下例子:
public class Counter {
int count;
Counter(){
count = 7;
}
}
count首先是為0,當呼叫其構造方法後,才使得count為7.
1.初始化順序
在類的內部,變數定義的先後順序決定了其初始化順序。但變數的初始化操作會在呼叫任何方法之前完成,包括構造方法,哪怕變數的定義散佈於方法定義之間。
如以下例子:
當執行這個程式碼時,其結果為:class Window{ Window(int i){ System.out.println("Window("+i+")"); } } class House{ Window window1 = new Window(1); House(){ System.out.println("----I'm contructor method----"); } Window window2 = new Window(2); void f(){ System.out.println("-----I'm f()-----"); } Window window3 = new Window(3); } public class Demo { public static void main(String[] args) { House house = new House(); house.f(); } }
Window(1)
Window(2)
Window(3)
----I'm contructor method----
-----I'm f()-----
由此可以看出,Window的幾個物件均在House的構造器和f()方法之前便已完成初始化。
2、靜態資料的初始化
無論建立多少物件,靜態資料都只佔據一份儲存域。static關鍵字不能應用於區域性變數,因此它只能作用於域。
可以通過一個例子來看靜態資料的初始化是如何進行的:
package com.hd.demo; class Bowl{ Bowl(int i){ System.out.println("Bowl("+i+")"); } void f(int i){ System.out.println("f("+i+")"); } } class Table{ static Bowl bolw1 = new Bowl(1); Table(){ System.out.println("----I'm Table contructor method----"); } void f(){ System.out.println("-----I'm f() method in Table-----"); } static Bowl bolw2 = new Bowl(2); } class Cupboard{ Bowl bowl3 = new Bowl(3); static Bowl bowl4 = new Bowl(4); Cupboard(){ System.out.println("----I'm Cupboard contructor method----"); bowl4.f(1); } void f(){ System.out.println("-----I'm f() method in Cupboard-----"); } static Bowl bowl5 = new Bowl(5); } public class StaticDemo { 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.f(); cupboard.f(); } static Table table = new Table(); static Cupboard cupboard = new Cupboard(); }
其執行結果如下:
以上程式碼有幾個需要注意的地方,一個是StaticDemo中在main方法的下面定義了靜態資料成員table和cupboard。它們會在main方法執行之前先進行初始化。另一個是Cupboard類中,先定義了一個非靜態的bowl3成員。最後就是在main方法中又new了Cupboard物件。Bowl(1) Bowl(2) ----I'm Table contructor method---- Bowl(4) Bowl(5) Bowl(3) ----I'm Cupboard contructor method---- f(1) creating new Cupboard() in main Bowl(3) ----I'm Cupboard contructor method---- f(1) creating new Cupboard() in main Bowl(3) ----I'm Cupboard contructor method---- f(1) -----I'm f() method in Table----- -----I'm f() method in Cupboard-----
通過以上執行結果可以得出以下結果:
1)、靜態初始化只有在必要的時候才會進行,如果不建立Table物件,那麼bowl1和bowl2就不會建立。
2)、靜態資料只有在第一次被訪問時才會進行初始化,此後便不再被初始化。比如,在main方法中new Cupboard,初始化了非靜態成員bowl3,而靜態成員bowl4和bowl5不再被初始化。
3)、初始化的順序是先靜態物件,後是非靜態物件。
3、顯示的靜態初始化
先看一段程式碼:
class Cup{
Cup(int mark){
System.out.println("Cup("+mark+")");
}
void f(int mark){
System.out.println("f("+mark+")");
}
}
class Cups{
static Cup cup1 ;
static Cup cup2 ;
static {
cup1 = new Cup(1);
cup2 = new Cup(2);
}
}
public class ExplicitStatic {
public static void main(String[] args) {
Cups.cup1.f(1); //(1)
}
//static Cups cups1 = new Cups(); //(2)
//static Cups cups2 = new Cups(); //(3)
}
其執行結果如下:
Cup(1)
Cup(2)
f(1)
假設註釋掉(1)的程式碼,解除(2)或(3)的程式碼,那麼結果就會為:
Cup(1)
Cup(2)
如果同時解除(2)和(3)的程式碼,其執行結果都是一樣的。因為上面已經提到,靜態資料只有在第一次被訪問時才會初始化,此後便不再初始化。4、非靜態例項初始化
先看一段程式碼:
class Mug{
Mug(int i){
System.out.println("Mug("+i+")");
}
}
public class Mugs {
Mug mug1;
Mug mug2;
{
mug1 = new Mug(1);
mug2 = new Mug(2);
}
Mugs(){
System.out.println("無參構造器");
}
Mugs(int i){
System.out.println("有參構造器");
}
public static void main(String[] args) {
new Mugs();
new Mugs(1);
}
}
執行結果:
Mug(1)
Mug(2)
無參構造器
Mug(1)
Mug(2)
有參構造器
可以看到,因為少了一個static關鍵字,因此,每new一個物件,mug1和mug2都會初始化一次,並且也是在構造器執行之前完成。
寫這篇部落格是因為在《Java思想程式設計》中看到專門講構造器初始化的知識,感覺自己有很多不懂的地方,看了兩三遍才明白。現在再總結一下,算是加深印象吧。