構造器的作用是在new一個對象時對其進行初始化操作。使用new初始化一個對象的過程如下:
(1) 首先執行靜態代碼塊,若該類有父類則先執行父類的靜態代碼塊。
(2) 接著執行該類的構造方法,若該類有父類,則先執行父類的構造方法。由此可以形成一條構造方法鏈,直到頂層父類。
執行如下代碼:
public class ObjTest {public static void main(String[] args) {Children obj = new Children();}}class Children extends Parent{static{System.out.println("children static block...");}public Children(){System.out.println("children constructor block....");}public void test() {System.out.println("instance block....");}}class Parent{static{System.out.println("parent static block...");}public Parent(){System.out.println("parent constructor block...");}}
結果為:
parent static block...
children static block...
parent constructor block..
children constructor block....
由此我們可以瞭解到對象初始化的過程,這其中最重要的就是構造方法,構造方法是對一個對象進行初始化的操作。接下來說說構造方法。當我們沒有為一個類指定構造方法時,編譯器會自動產生一個空構造方法。當我們為一個類指定一個非空構造方法時,編譯器就不會自動產生一個構造方法。
比如:
class Obj{public static void main(String[] args) {new Obj();}}
new Obj()的作用就是建立一個對象,並調用預設構造器,即使我們沒有指定構造器。
若修改代碼如下:
class Obj{public static void main(String[] args) {new Obj();}public Obj(int a){}}
則編譯器就會報錯,因為我們已經指定了一個構造方法。就好象我們沒有設定任何構建器,
編譯器會說:“你看來似乎需要一個構建器,所以讓我們給你製造一個吧。”但假如我們寫了一個構建器,編譯器就會說:“啊,你已寫了一個構建器,所以我知道你想幹什麼;如果你不放置一個預設的,是由於你打算省略它。”
因此當我們頂一個類時,若指定了非空的構造方法時,一般也需要手動指定一個非空的構造方法,便於類的繼承。
接下來說說this關鍵字,this關鍵字代表當前對象。
首先看下面的代碼:
class Obj{void f(int i){}public void test() {Obj a = new Obj(),b = new Obj();a.f(1);b.f(2);}}
這是一個普通的對象調用方法,它內部是如何?的呢?其實如下,
Obj.f(a,1);Obj.f(b,2);就是為某個方法指定一個控制代碼。我們也可以使用this關鍵字調用,this.f(1);但是事實上沒有必要的,編譯器會自動幫我們完成。但是對於那些特殊的類--需要明確使用當前對象的控制代碼,將當前對象的控制代碼返回時,需要使用this。
class Obj{int a = 0;void g(){test().test().test();}Obj test(){a++;return this;}}
我們可以這樣構造一個方法鏈。
若為一個類寫了多個構建器,那麼經常都需要在一個構建器裡調用另一個構建器,以避免寫重複的代碼。可用this關鍵字做到這一點
class Obj{int a = 0;public Obj(int a){this.a = a;}public Obj(String s){}public Obj(){this(4);//this("aa");System.out.println("....");}}
使用this可以在構造器裡調用另一個構造器,而且this語句必須是第一條語句,並且不能使用兩個this語句。在第一個構造器裡,成員變數和局部變數重名了,還可以使用this關鍵字調用成員變數。
在對象的初始化過程中我們也說到了static關鍵字,static關鍵字修飾的成員變數,方法都屬於類方法,是全域的,該類的所有執行個體都共用這些資料,不需要建立對象就可以使用這些資料。執行個體變數,執行個體方法(沒有static修飾的)是屬於某個執行個體的,必須先建立一個執行個體才可以使用這些資料.因此在靜態方法中不可以調用執行個體方法,因為執行個體方法需要確定對象。需要說明一點,靜態代碼塊。靜態代碼塊在類的位元組碼載入時執行,可以做些全域的初始化操作。而構造方法,做某個具體執行個體的初始化操作。