在Java中,構造函數的訪問級別通常是public, 它提供了一個構造該類對象的接口。可是你知不知道,把構造函數的級別設爲private, 有一些特別用處。
先來看一段代碼:
//Shape.java
public class Shape {
private Shape() {
/* set something here */
}
public static Shape makeShape(/* arglist */) {
System.out.println("here is the shape you ordered");
return (new Shape());
}
public static void main(String args[]) {
Shape.makeShape();
}
}
首先從語言角度分析,我們可以知道, 任何類的使用者都無法使用構造函數來生成一個圖形, 因爲構造函數是私有的,無法被類以外的函數使用。而只能通過調用makeShape來實現。
也許你會問,爲什麼不直接使用構造函數來生成圖形,而需要使用一個看上去多餘的makeShape方法呢?
這樣做有以下幾個好處:
1。你可以返回任何的Shape類型,包括Shape的子類。比如你可以把makeShape寫成這樣:
public static Shape makeShape(/* arglist */) {
System.out.println("here is the shape you ordered");
if (retangle)
return (new Retangle(/* arglist*/));
if (Circle)
return (new Circle(/* arglist */));
/* you can return as many shapes as you like */
}
這裏假設Retangle 和 Circle 都是shape的子類,並且和Shape類在同一個包內,Shape類可以訪問子類的構造函數。這樣shape就提供了一個圖形工廠。 用戶通過一個接口就可以生成不同的圖形。事實上,這種用法被稱爲“工廠模式”。
2。可以實現一個類只有一個對象。請看下面的代碼
//Handler.java
public class Handler {
private Handler handler = null;
private Handler() {
/* set something here */
}
public static getHandler(/* arglist */) {
if (!handler)
handler = new Handler();
return handler;
}
public static void main(String args[]) {
Handler.getHandler();
}
}
當handlerw爲空時,那麼重新構造一個handler,然後返回;如果已經構造過了,那麼就直接返回已經存在的handler。這種用法被稱爲“Singleton pattern". 如果直接使用構造函數來構造對象,那麼你就無法控制生成的數量。在實際應用中,往往會做一些改變。比如使用一個具有一定容量的池,當需要構造一個對象而池的容量仍未滿時,就構造一個新的對象,並放入池中,並把對象的狀態設爲“佔用”狀態;當需要構造一個對象而池的容量已滿,則從池中選一個“空閒”狀態的對象返回,並把對象的狀態設爲“佔用”。當對象使用完後再回收到池中並把狀態設爲“空閒“。
這種模式的一個典型應用場景是:
在一個具有很多用戶的web站點裏,需要一個對象來單獨處理一個連接,而每一個連接的時間比較短。如果每次連接都創建一個對象然後又很快銷燬,那麼創建和銷燬對象的系統開銷是很大的。這種時候可以使用對象池,這樣就免去了創建和銷燬對象的開銷。
3。可以方便的拋出異常。請看下列代碼:
public class Test {
public Test() {
double x = 1.0/0.0;
}
public static void main(String args[]) {
try {
Test test = new Test();
}catch (Exception e){
System.out.println(e.toString());
}
}
}
編譯,執行,你會發現這個異常不會被捕捉,沒有任何輸出;即使嘗試在構造函數中捕捉異常也不行。看下列代碼:
public class Test {
public Test() {
try {
System.out.println("trying to throw an exception");
double x = 1.0/0.0;
} catch(Exception e) {
System.out.println("Exception captured");
}finally {
System.out.println("inside finally");
}
}
public static void main(String args[]) {
Test test = new Test();
}
}
編譯,運行,結果爲:
trying to throw an exception
inside finally
原因是JVM把構造函數產生的異常丟棄了。試想你正在使用一個第三方的類庫提供的類,那個類提供一個共有的構造函數,它允許你通過參數構造一個類的對象,可是如果你的參數不合法,導致在構造函數中產生一個異常,那麼你永遠不知道具體發生了什麼。當然如可以在每次構造對象時進行參數合法性檢查,可是假設你要構造好多這樣的對象??那將是一場災難。這時可以通過把構造函數的訪問級別設爲私有,強迫類的使用者使用一個工廠函數來生成需要的對象,那麼就可以在這個函數中統一的進行參數檢查了。具體的代碼就不寫了,留給讀者去實踐吧!
從上面的分析我們可以知道私有構造函數的威力。需要注意的一點是,即使你的構造函數什麼都不做,比如:
private Shape() {}
你仍然要顯示的定義,因爲如果你不定義,那麼Java會自動爲你生成一個空構造函數,而這個空構造函數是共有的。
Java 私有構造函數的應用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.