在Java中袒餐,構(gòu)造函數(shù)的訪問級別通常是public, 它提供了一個構(gòu)造該類對象的接口拴魄。可是你知不知道罕模,把構(gòu)造函數(shù)的級別設(shè)為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();
}
}
首先從語言角度分析帘瞭,我們可以知道淑掌, 任何類的使用者都無法使用構(gòu)造函數(shù)來生成一個圖形, 因?yàn)闃?gòu)造函數(shù)是私有的,無法被類以外的函數(shù)使用蝶念。而只能通過調(diào)用makeShape來實(shí)現(xiàn)抛腕。
也許你會問,為什么不直接使用構(gòu)造函數(shù)來生成圖形媒殉,而需要使用一個看上去多余的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 */
}
這里假設(shè)Retangle 和 Circle 都是shape的子類,并且和Shape類在同一個包內(nèi)桃犬,Shape類可以訪問子類的構(gòu)造函數(shù)刹悴。這樣shape就提供了一個圖形工廠。 用戶通過一個接口就可以生成不同的圖形攒暇。事實(shí)上颂跨,這種用法被稱為“工廠模式”。
2扯饶『阆鳎可以實(shí)現(xiàn)一個類只有一個對象。請看下面的代碼
//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();
}
}
當(dāng)handlerw為空時尾序,那么重新構(gòu)造一個handler钓丰,然后返回;如果已經(jīng)構(gòu)造過了每币,那么就直接返回已經(jīng)存在的handler携丁。這種用法被稱為“Singleton pattern". 如果直接使用構(gòu)造函數(shù)來構(gòu)造對象,那么你就無法控制生成的數(shù)量。在實(shí)際應(yīng)用中梦鉴,往往會做一些改變李茫。比如使用一個具有一定容量的池,當(dāng)需要構(gòu)造一個對象而池的容量仍未滿時肥橙,就構(gòu)造一個新的對象魄宏,并放入池中,并把對象的狀態(tài)設(shè)為“占用”狀態(tài)存筏;當(dāng)需要構(gòu)造一個對象而池的容量已滿宠互,則從池中選一個“空閑”狀態(tài)的對象返回,并把對象的狀態(tài)設(shè)為“占用”椭坚。當(dāng)對象使用完后再回收到池中并把狀態(tài)設(shè)為“空閑“予跌。
這種模式的一個典型應(yīng)用場景是:
在一個具有很多用戶的web站點(diǎn)里,需要一個對象來單獨(dú)處理一個連接善茎,而每一個連接的時間比較短券册。如果每次連接都創(chuàng)建一個對象然后又很快銷毀,那么創(chuàng)建和銷毀對象的系統(tǒng)開銷是很大的垂涯。這種時候可以使用對象池烁焙,這樣就免去了創(chuàng)建和銷毀對象的開銷。
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());
}
}
}
編譯鞠苟,執(zhí)行,你會發(fā)現(xiàn)這個異常不會被捕捉秽之,沒有任何輸出当娱;即使嘗試在構(gòu)造函數(shù)中捕捉異常也不行】颊ィ看下列代碼:
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();
}
}
編譯跨细,運(yùn)行,結(jié)果為:
trying to throw an exception
inside finally
原因是JVM把構(gòu)造函數(shù)產(chǎn)生的異常丟棄了河质。試想你正在使用一個第三方的類庫提供的類冀惭,那個類提供一個共有的構(gòu)造函數(shù),它允許你通過參數(shù)構(gòu)造一個類的對象掀鹅,可是如果你的參數(shù)不合法散休,導(dǎo)致在構(gòu)造函數(shù)中產(chǎn)生一個異常,那么你永遠(yuǎn)不知道具體發(fā)生了什么乐尊。當(dāng)然如可以在每次構(gòu)造對象時進(jìn)行參數(shù)合法性檢查戚丸,可是假設(shè)你要構(gòu)造好多這樣的對象?扔嵌?那將是一場災(zāi)難限府。這時可以通過把構(gòu)造函數(shù)的訪問級別設(shè)為私有夺颤,強(qiáng)迫類的使用者使用一個工廠函數(shù)來生成需要的對象,那么就可以在這個函數(shù)中統(tǒng)一的進(jìn)行參數(shù)檢查了胁勺。具體的代碼就不寫了世澜,留給讀者去實(shí)踐吧!
從上面的分析我們可以知道私有構(gòu)造函數(shù)的威力姻几。需要注意的一點(diǎn)是宜狐,即使你的構(gòu)造函數(shù)什么都不做,比如:
private Shape() {}
你仍然要顯示的定義蛇捌,因?yàn)槿绻悴欢x抚恒,那么Java會自動為你生成一個空構(gòu)造函數(shù),而這個空構(gòu)造函數(shù)是共有的络拌。
出處:http://blog.csdn.net/my_dream_fly/article/details/3857887