11.對象構造【Java溫故系列】

參考自–《Java核心技術卷1》


Java 提供了多種編寫構造器的機制。


1 重載

有些類有多個構造器,例如:

可以構造一個空的 StringBuilder 對象:

StringBuilder sb1 = new StringBuilder();

也可以指定一個初始字符串構造 StringBuilder 對象:

StringBuilder sb2 = new StringBuilder("To do:\n");

這種特徵叫做重載。如果多個方法,有相同的名字、不同的參數,便產生了重載。編譯器必須挑選出具體執行哪個方法,它通過用各個方法給出的參數類型與特定方法調用所使用的值類型進行匹配來挑選出相應的方法。如果編譯器找不到匹配的參數,就會產生編譯時錯誤,因爲根本不存在匹配(或者沒有一個比其他的更好),這個過程稱爲重載解析。

:Java 允許重載任何方法。因此,要完整地描述一個方法,需要指出方法名以及參數類型。這叫做方法的簽名。方法的返回類型不是方法簽名的一部分,即不能有兩個名字相同、參數類型也相同卻返回不同類型值的方法。


2 實例域初始化

2.1 構造器初始化實例域

大多數情況下,類的構造器在執行時都會初始化類的實例域。

2.1 默認域初始化

如果在構造器中沒有顯式地給域賦予初值,那麼就會自動地賦予默認值:數值爲0、布爾值爲 false、對象引用爲 null.(包括靜態域)

2.2 顯式域初始化

通過重載類的構造器方法,可以採用多種形式設置類的實例域的初始狀態。確保不管怎樣調用構造器,每個實例域都可以被設置爲一個有意義的初值。

然而,我們可以在類的定義中,直接將一個值賦給任何域。如:

class Employee{
	private String name = ""; //顯式 域初始化
}
//也可以通過調用方法給實例域賦初值

在執行構造器前,先執行賦值操作。當一個類的所有構造器都希望把相同的值賦予某個特定的實例域時,這種方法特別有效。

2.3 初始化塊

在一個類的聲明中,可以包含多個代碼塊。只要構造類的對象,這些塊就會被執行,如:

public class Employee {
    private static int nextId;

    private int id;
    private String name;
    private double salary;
    
    //靜態域初始化(在類的第一次加載時,將會進行靜態域的初始化)
    static{
        Random generator = new Rondom();
        //賦予小於1000的任意整數
        nextId = generator.nextInt(1000);
    }
	//代碼塊(初始化塊)
    {
        id = nextId;
        nextId++;
    }

    public Employee(){
        name = "";
        salary = 0;
    }
}

在上述示例中,無論使用哪個構造器構造對象,id 域都在對象初始化塊中被初始化。首先運行初始化塊,然後才執行構造器的主體部分。(但是不常見,非必需的)


3 構造器

3.1 無參構造器

很多類都包含一個無參數的構造函數,對象由無參數構造函數創建時,其狀態會設置爲適當的默認值。如:

class Employee{
	private String name;
	private int salary;
	private Data hireDay;
    ...
    public Employee(){
    	//無參構造器,指定默認值
    	name = "";
    	salary = 0;
    	hireDay = LocalDate.now();
    }
}

如果在編寫一個類時沒有編寫構造器,那麼系統就會提供一個無參數構造器。這個構造器將所有的實例域設置爲默認值。即實例域中的數值型數據域設置爲0、布爾型數據域設置爲 false、所有對象變量將設置爲 null。

如果類中提供了至少一個構造器,但是沒有提供無參數的構造器,則在構造對象時如果沒有提供參數就會被視爲不合法。

3.2 調用另一個構造器

關鍵字 this 引用方法的隱式參數。然而,這個關鍵字還有另外一個含義。

如果構造器的第一個語句形如 this(…),這個構造器將調用類的另一個構造器。

public Employee(double s){
	this("Employee #"+nextId,s); //調用Employee(String,double)構造器
	nextId++;
}

如上,調用 new Employee(6000) 時,Employee(double) 構造器將調用 Employee(String,double) 構造器。

採用這種方式使用 this 關鍵字非常有用,這樣對公共的構造器代碼部分只編寫一次即可。

3.3 調用構造器的具體執行步驟

1)所有數據域被初始化爲默認值(0、false、null)

2)按照在類中聲明中出現的次序,依次執行所有域初始化語句和初始化塊

3)若構造器第一行調用了另外一個構造器,則執行另外那個構造器主體

4)執行這個構造器主體


4 對象析構與 finalize 方法

有些面向對象的程序設計語言,特別是 C++ ,有顯示的析構器方法,其中放置一些當對象不再使用時需要執行的清理代碼。在析構器中,最常見的操作是回收分配給對象的存儲空間。由於 Java 有自動的垃圾回收機制,不需要人工回收內存,所以 Java 不支持析構器。

當然,某些對象可能使用了內存之外的其他資源,如,文件或使用了系統資源的另一個對象的句柄(如 String s;此處 s 就是創建的一個句柄,並不一定有 String 對象與它連接)。這種情況下,當資源不再需要時,將其回收和再利用將顯得十分重要。

可以爲任何一個類添加 finalize 方法。finalize 方法將在垃圾回收器清除對象之前調用。在實際應用中,不要依賴於使用 finalize 方法回收任何短缺的資源,因爲很難知道這個方法在什麼時候才能夠調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章