0.前言
- 在之前的文章中學習了編寫簡單的構造器,可以定義對象的初始狀態。
- Java 提供了多種編寫構造器的機制。下面將詳細地介紹這些機制。
1.重載
- 如果
多個方法
(比如, StringBuilder 構造器方法)有相同的名字、不同的參數
,便產生了重載
。
例如, 可以如下構造一個空的 StringBuilder 對象:
StringBuilder messages = new StringBuilder();
或者, 可以指定一個初始字符串:
StringBuilder todoList = new StringBuilder("To do:\n");
重載解析:
- 編譯器必須挑選出具體執行哪個方法,它通過用 各個方法給出的參數類型與特定方法調用所使用的值類型進行匹配來挑選出相應的方法。
如 果編譯器找不到匹配的參數, 就會產生編譯時錯誤,因爲根本不存在匹配, 或者沒有一個比其他的更好。(這個過程被稱爲重載解析
(overloading resolution)。
注:
Java 允許重載任何方法, 而不只是構造器方法。
因此,要完整地描述一個方法, 需要指出方法名以及參數類型
。這叫做方法的簽名(signature)
。
例如, String 類有 4 個 稱爲 indexOf 的公有方法。它們的簽名是
indexOf(int)
indexOf(int, int)
indexOf(String)
indexOf(String,int)
返回類型不是方法簽名的一部分。
也就是說, 不能有兩個名字相同、 參數類型也相 同卻返回不同類型值的方法。
如下就是錯誤的:
2.默認域初始化
- 如果在
構造器中沒有顯式地給域賦予初值
,那麼就會被自動地賦爲默認值
:數值爲 0、 布爾值爲 false、 對象引用爲null
。 - 仔細看一下 Employee類。假定沒有在構造器中對某些域進行初始化, 就會默認 地將 salary 域初始化爲 0, 將 name 和 hireDay 域初始化爲 null。
3.無參數的構造器
- 很多類都包含一個無參數的構造函數,對象由無參數構造函數創建時, 其狀態會設置爲 適當的默認值。
如果在編寫一個類時沒有編寫構造器, 那麼系統就會提供一個無參數構造器。
這個構造 器將所有的實例域設置爲默認值。於是, 實例域中的數值型數據設置爲 0、 布爾型數據設置 爲 false、 所有對象變量將設置爲 null
。
- 如果類中提供了至少一個構造器, 但是沒有提供無參數的構造器, 則在構造對象時如果 沒有提供參數就會被視爲不合法
4.顯式域初始化
- 可以在類定義中, 直接將一個值賦給任何域,比如我上面那張圖的
private double d=10.3d;
- 在執行構造器之前,先執行賦值操作。當一個類的所有構造器都希望把相同的值賦予某 個特定的實例域時,這種方式特別有用。
Employee類,其中每個僱員有一個 id 域。可以使用下列方式進行初始化:
5.參數變量名
可以將參數變量名用同樣的名字將實例域屏蔽起來
例如,如果將參數命名爲 salary, salary將引用這個參數, 而不是實例域。 但是,可以採用 this, salary 的形式訪問實例域。this指示隱式參數,也就是當前所構造的對象。
public Employee(String naie, double salary) {
this.name = name;
this,salary = salary;
}
6. this調用另一個構造器
- 關鍵字 this 引用方法的隱式參數,即引用調用這個方法的對象。然而,這個關鍵字還有另外一個含義。
如果構造器的第一個語句形如 this(...), 這個構造器將調用同一個類的另一個構造器
- 當調用 new Employee(100) 時, Employee(double) 構造器將調用 Employee(String,double) 構造器。
7.初始化塊
前面已經講過兩種初始化數據域的方法:
- 在構造器中設置值
- 在聲明中賦值
實際上,Java 還有第三種機制, 稱爲初始化塊(initializationblock)
。在一個類的聲明中, 可以包含多個代碼塊。只要構造類的對象,這些塊就會被執行。例如:
- 在這個示例中,無論是否使用構造器構造對象,name域都在對象初始化塊中被初始化。
首先運行初始化塊,然後才運行構造器的主體部分
。 這種機制不是必需的,也不常見。通常會直接將初始化代碼放在構造器中。
由於初始化數據域有多種途徑,所以列出構造過程的所有路徑可能相當混亂。下面是調 用構造器的具體處理步驟:
- 1 ) 所有數據域被初始化爲設置的值,不設置則爲默認值(0、false 或 null)。
- 2 )
按照在類聲明中出現的次序, 依執行所有域初始化語句和初始化塊
。 - 3 ) 如果構造器第一行調用了第二個構造器,則執行第二個構造器主體 ) 執行這個構造器的主體.
- 如果對類的靜態域進行初始化的代碼比較複雜,那麼可以使用靜態的初始化塊。 將代碼放在一個塊中,並標記關鍵字 static。
在類第一次加載的時候, 將會首先執行靜態static域進行初始化,然後執行普通初始化塊,最後執行構造器函數。
8. 對象析構與 finalize 方法
- 有些面向對象的程序設計語言,特別是 C++, 有
顯式的析構器方法
,其中放置一些當對 象不再使用時需要執行的清理代碼。在析構器
中, 最常見的操作是回收分配給對象的存儲空間
。由於 Java 有自動的垃圾回收器,不需要人工回收內存, 所以 Java 不支持析構器。 - 當然,某些對象使用了內存之外的其他資源, 例如,文件或使用了系統資源的另一個對 象的句柄。在這種情況下,當資源不再需要時, 將其回收和再利用將顯得十分重要。
- 可以爲任何一個類添加 finalize 方法。finalize 方法將在垃圾回收器清除對象之前調用。
在實際應用中,不要依賴於使用 finalize 方法回收任何短缺的資源, 這是因爲很難知道這個方法什麼時候才能夠調用。
- 如果某個資源需要在使用完畢後立刻被關閉, 那麼就需要由人工來管理。
對象用完時, 可以應用一個 close方法來完成相應的清理操作
參考:《java核心技術卷Ⅰ》