hi,
??? 今天無(wú)意中看到有個(gè)兄弟在java程序中多次用到了goto語(yǔ)句,感覺(jué)很是怪異,copy來(lái)編譯下發(fā)現(xiàn)有很多錯(cuò)誤!
為此,我付出了一下午時(shí)間去研究這個(gè)塊被人遺忘了的可怕的"魔鬼".
?? “可怕”的goto語(yǔ)句是c和c++的“遺物”,它是該語(yǔ)言技術(shù)上的合法部分,引用goto語(yǔ)句引起了程序結(jié)構(gòu)的混亂,不易理解,goto語(yǔ)句子要用于無(wú)條件轉(zhuǎn)移子程序和多結(jié)構(gòu)分支技術(shù)。鑒于以廣理由,Java不提供goto語(yǔ)句,它雖然指定goto作為關(guān)鍵字,但不支持它的使用,使程序簡(jiǎn)潔易讀。在Java中g(shù)oto語(yǔ)句被完全拋棄了,與此同時(shí),Java又?jǐn)U大了break語(yǔ)句和continue語(yǔ)句的功能,通過(guò)使用break和continue,程序流程被允許在多層循環(huán)中跳轉(zhuǎn)。
大家再看看以下代碼:
?
import java.sql.*;
import java.util.Enumeration;
import java.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
// Referenced classes of package fiyucore.db:
//??????????? DBOptions
class DBConnectionManager
{
??? class DBConnectionPool
??? {
??????? private String URL;
??????? private int checkedOut;
??????? private Vector freeConnections;
??????? private int maxConn;
??????? private String password;
??????? private String user;
??????? synchronized void freeConnection(Connection con)
??????? {
??????????? if(con == null)
??????????????? break MISSING_BLOCK_LABEL_63;
??????????? if(checkedOut > 0)
??????????????? break MISSING_BLOCK_LABEL_39;
??????????? DBConnectionManager.log.debug("DBConnectionManager: 關(guān)閉連接");
??????????? con.close();
????????????? goto _L1
??????????? SQLException ex;
??????????? ex;
_L1:
??????????? break MISSING_BLOCK_LABEL_62;
??????????? freeConnections.addElement(con);
??????????? checkedOut--;
??????????? notifyAll();
??????????? return;
??????? }
??????? Connection getConnection(long timeout)
??????? {
??????????? long startTime = System.currentTimeMillis();
????????????? goto _L1
_L3:
??????????? long timeToWait;
??????????? long elapsedTime = System.currentTimeMillis() - startTime;
??????????? if(elapsedTime >= timeout)
??????????????? return null;
??????????? timeToWait = timeout - elapsedTime;
??????????? if(timeToWait > 500L)
??????????????? timeToWait = 500L;
??????????? Thread.sleep(timeToWait);
??????????? continue; /* Loop/switch isn't completed */
??????????? InterruptedException e;
??????????? e;
_L1:
??????????? Connection con;
??????????? if((con = getConnection()) == null) goto _L3; else goto _L2
_L2:
??????????? return con;
??????? }
??????? synchronized Connection getConnection()
??????? {
??????????? Connection con;
??????????? for(con = null; freeConnections.size() > 0 && con == null;)
??????????? {
??????????????? con = (Connection)freeConnections.firstElement();
??????????????? freeConnections.removeElementAt(0);
??????????????? try
??????????????? {
??????????????????? if(con.isClosed())
??????????????????? {
??????????????????????? DBConnectionManager.log.info("刪除壞連接!");
??????????????????????? con = null;
??????????????????? }
??????????????? }
??????????????? catch(SQLException e)
??????????????? {
??????????????????? con = null;
??????????????? }
??????????? }
??????????? if(con == null)
??????????? {
??????????????? if(maxConn == 0 || checkedOut < maxConn)
??????????????????? con = newConnection();
??????????? }
??????????? if(con != null)
??????????????? checkedOut++;
??????????? return con;
??????? }
??????? private Connection newConnection()
??????? {
??????????? Connection con = null;
??????????? if(user == null)
??????????????? con = DriverManager.getConnection(URL);
??????????? else
??????????????? con = DriverManager.getConnection(URL, user, password);
??????????? con.setAutoCommit(true);
??????????? break MISSING_BLOCK_LABEL_83;
??????????? SQLException e;
??????????? e;
??????????? DBConnectionManager.log.error("不能在連接池中創(chuàng)建新的連接. URL = " + URL, e);
??????????? return null;
??????????? return con;
??????? }
??????? synchronized boolean release()
??????? {
??????????? boolean retValue;
??????????? Enumeration allConnections;
??????????? retValue = true;
??????????? allConnections = freeConnections.elements();
????????????? goto _L1
_L3:
??????????? Connection con = (Connection)allConnections.nextElement();
??????????? con.close();
??????????? continue; /* Loop/switch isn't completed */
??????????? SQLException e;
??????????? e;
??????????? DBConnectionManager.log.error("不能關(guān)閉連接!");
_L1:
??????????? if(allConnections.hasMoreElements()) goto _L3; else goto _L2
_L2:
??????????? freeConnections.removeAllElements();
??????????? if(checkedOut != 0)
??????????? {
??????????????? retValue = false;
??????????????? DBConnectionManager.log.warn("DBConnectionManager: 內(nèi)置的連接池沒(méi)有正確配置好");
??????????? }
??????????? checkedOut = 0;
??????????? return retValue;
??????? }
??????? public DBConnectionPool(String URL, String user, String password, int maxConn)
??????? {
??????????? checkedOut = 0;
??????????? freeConnections = new Vector();
??????????? this.maxConn = 0;
??????????? this.password = null;
??????????? this.URL = null;
??????????? this.user = null;
??????????? this.URL = URL;
??????????? this.user = user;
??????????? this.password = password;
??????????? this.maxConn = maxConn;
??????? }
??? }
??? private static final int TIME_BETWEEN_RETRIES = 500;
??? static Class class$fiyucore$db$DBConnectionManager; /* synthetic field */
??? private static DBConnectionManager instance = null;
??? private static Log log;
??? private DBConnectionPool pool;
??? private DBConnectionManager(DBOptions option)
??? {
??????? pool = null;
??????? Class.forName(option.driverClassName).newInstance();
??????? break MISSING_BLOCK_LABEL_59;
??????? Exception e;
??????? e;
??????? log.fatal("DBConnectionManager: 不能加載驅(qū)動(dòng) = " + option.driverClassName);
??????? pool = new DBConnectionPool(option.databaseURL, option.databaseUser, option.databasePassword, option.maxConnection);
??????? return;
??? }
??? static Class class$(String x0)
??? {
??????? return Class.forName(x0);
??????? ClassNotFoundException x1;
??????? x1;
??????? throw new NoClassDefFoundError(x1.getMessage());
??? }
??? void freeConnection(Connection con)
??? {
??????? pool.freeConnection(con);
??? }
??? Connection getConnection(long time)
??? {
??????? return pool.getConnection(time);
??? }
??? Connection getConnection()
??? {
??????? return pool.getConnection();
??? }
??? public static synchronized DBConnectionManager getInstance(DBOptions option)
??? {
??????? if(instance == null)
??????? {
??????????? if(option == null)
??????????????? option = new DBOptions();
??????????? instance = new DBConnectionManager(option);
??????? }
??????? return instance;
??? }
??? public static synchronized DBConnectionManager getInstance()
??? {
??????? if(instance == null)
??????? {
??????????? DBOptions option = new DBOptions();
??????????? instance = new DBConnectionManager(option);
??????? }
??????? return instance;
??? }
??? boolean release()
??? {
??????? return pool.release();
??? }
??? static
??? {
??????? log = LogFactory.getLog(class$fiyucore$db$DBConnectionManager != null ? class$fiyucore$db$DBConnectionManager : (class$fiyucore$db$DBConnectionManager = class$("fiyucore.db.DBConnectionManager")));
??? }
}
這程序初看起來(lái)是多么的恐怖啊!多次用到goto,混亂。關(guān)于流程控制的方法,c++,java都提供了很好的語(yǔ)法:
分支語(yǔ)句 :if-else,break,switch, return.
循環(huán)語(yǔ)句 :while,do-while,for, continue.
例外處理語(yǔ)句 :try-catch-finally,throw
最后我們簡(jiǎn)單介紹一下注釋語(yǔ)句
分
支語(yǔ)句
分支語(yǔ)句提供了一種控制機(jī)制,使得程序的執(zhí)行可以跳過(guò)某些語(yǔ)句不執(zhí)行,而轉(zhuǎn)去執(zhí)行特定的語(yǔ)句。
條件語(yǔ)句if-else.
if-else語(yǔ)句根據(jù)判定條件的真假來(lái)執(zhí)行兩種操作中的一種,格式為:
if(boolean-expression)
statement1;
[else statement2;]
1.布爾表達(dá)式boolean-expression是任意一個(gè)返回布爾型數(shù)據(jù)的達(dá)式(這比C、 C++的限制要嚴(yán)格)。
2.每個(gè)單一的語(yǔ)句后都必須有分號(hào)。
3.語(yǔ)句statement1,statement2可以為復(fù)合語(yǔ)句,這時(shí)要用大括號(hào){}。建議對(duì)單一的語(yǔ)句也用大括號(hào)括起,這樣程序的可讀性強(qiáng),而且有利于程序的擴(kuò)充(可以在其中填加新的語(yǔ)句)。{}外面不加分號(hào)。
4.else子句是任選的。
5.若布爾表達(dá)式的值為true,則程序執(zhí)行statement1,否則執(zhí)行statement2。
6.if-else語(yǔ)句的一種特殊形式為:
if(expression1){?
statement1?
}else if (expression2){?
statement2?
}……?
}else if (expressionM){?
statementM?
}else {?
statementN?
}?
[else子句不能單獨(dú)作為語(yǔ)句使用,它必須和if配對(duì)使用。else總是與離它最近的if配對(duì)。可以通過(guò)使用大括號(hào){}來(lái)改變配對(duì)關(guān)系。]
多分支語(yǔ)句switch
switch語(yǔ)句根據(jù)表達(dá)式的值來(lái)執(zhí)行多個(gè)操作中的一個(gè),它的般格式如下:
switch (expression){
casevalue1:statement1;
break;
casevalue2:statement2;
break;
…………
casevalueN:statemendN;
break;
[default:defaultStatement;]
}
1.表達(dá)式expression可以返回任一簡(jiǎn)單類型的值(如整型、實(shí)數(shù)型、字符型),多分支語(yǔ)句把表達(dá)式返回的值與每個(gè)case子句中的值相比。如果匹配成功,則運(yùn)行該case子句后的語(yǔ)句序列。
2.case子句中的值values必須是常量,而且所有case子句中的值是不同的。
3.default子句是任選的。當(dāng)表達(dá)式的值與任一case子句中的都不匹配時(shí),程序執(zhí)行default后面的語(yǔ)句。如果表達(dá)式的值與任一case子句中的值都不匹配且沒(méi)有default子句,則程序不作任何操作,而是直接跳出switch語(yǔ)句。
4.break語(yǔ)句用來(lái)在執(zhí)行完一個(gè)case分支后,使程序跳出switch語(yǔ)句,即終止switch語(yǔ)句的執(zhí)行。因?yàn)閏ase子句只是起到一個(gè)標(biāo)號(hào)的作用,用來(lái)查找匹配的入口,從此處開(kāi)始執(zhí)行,對(duì)后面的case子句不再進(jìn)行匹配,而是直接執(zhí)行其后的語(yǔ)句序列,因此該在每個(gè)case分支后,要用break來(lái)終止后面的case分支語(yǔ)句的執(zhí)行。
在一些特殊情況下,多個(gè)不同的case值要執(zhí)行一組相同的操作,這時(shí)可以不用break。
5.case分支中包括多個(gè)執(zhí)行語(yǔ)句時(shí),可以不用大括號(hào){}括起。
6.switch語(yǔ)句的功能可以用if-else來(lái)實(shí)現(xiàn),但在某些情況下,使switch語(yǔ)句更簡(jiǎn)煉,可讀性強(qiáng),而且程序的執(zhí)行效率提高。
break語(yǔ)句
1.在switch語(yǔ)中,break語(yǔ)句用來(lái)終止switch語(yǔ)句的執(zhí)行。使程序switch語(yǔ)句后的第一個(gè)語(yǔ)句開(kāi)始執(zhí)行。
2.在Java中,可以為每個(gè)代碼塊加一個(gè)括號(hào),一個(gè)代碼塊通常用大括號(hào){}括起來(lái)的一段代碼。加標(biāo)號(hào)的格式如下:
BlockLabel:{codeBlock}
break語(yǔ)句的第二種使用情況就是跳出它所指定的塊,并從緊挨該塊的第一條語(yǔ)句處執(zhí)行。其格式為:
break BlockLabel;
例如:
a:{……//標(biāo)記代碼塊a
b:{……//標(biāo)記代碼塊b
c:{……//標(biāo)記代碼塊c
break b;
…… //willnotbeexecuted
}
…… //willnotbeexecuted
}
…… //willnotbeexecuted
}
…… /executefromhere
}
3.與C、 C++不同,Java中沒(méi)有g(shù)oto語(yǔ)句來(lái)實(shí)現(xiàn)任意的跳轉(zhuǎn),因?yàn)間oto語(yǔ)句破壞程序的可讀性,而且影響編譯的優(yōu)化。但是從上例可以看出,Java用break來(lái)實(shí)現(xiàn)goto語(yǔ)句所特有的一些優(yōu)點(diǎn)。如果break后所指定的標(biāo)號(hào)不是一個(gè)代碼塊的標(biāo)號(hào),而是一個(gè)語(yǔ)句,則這時(shí)break完全實(shí)現(xiàn)goto的功能。不過(guò)應(yīng)該避免這種方式的使用。
返回語(yǔ)句return
return語(yǔ)句從當(dāng)前方法中退出,返回到調(diào)用該方法的語(yǔ)句處,繼續(xù)程序的執(zhí)行。返回語(yǔ)句有兩種格式:
1.return expression
返回一個(gè)值給調(diào)用該方法的語(yǔ)句,返回值的數(shù)據(jù)類型必須用方法聲明中的返回值類型一致。可以使用強(qiáng)制類型轉(zhuǎn)換來(lái)使類型一致。
2.return
當(dāng)方法說(shuō)明中用void聲明返回類型為空時(shí),應(yīng)使用這種格式,不返回任何值。
return語(yǔ)句通常用在一個(gè)方法體的最后,以退出該方法并返一個(gè)值。Java中,單獨(dú)的return語(yǔ)句用在一個(gè)方法體的中間時(shí),會(huì)產(chǎn)生編譯錯(cuò)誤,因?yàn)檫@時(shí)有一些語(yǔ)句執(zhí)行不到。但
可以通過(guò)把return語(yǔ)句嵌入某些語(yǔ)句(如if-else)來(lái)使程序在未執(zhí)行完方法中的所有語(yǔ)句時(shí)退出,例如:
int method (int num) {?
∥ return num; ∥will cause compile time error?
if (num>0)?
return num;?
…… ∥ may or may not be executed?
∥depending on the value of num?
循環(huán)語(yǔ)句
循環(huán)語(yǔ)句的作用是反復(fù)執(zhí)行一段代碼,直到滿足終止循環(huán)條件為止,一個(gè)循環(huán)一般應(yīng)包括四部分內(nèi)容:
1.初始化部分(initialization):用來(lái)設(shè)置循環(huán)的一些初始條件,計(jì)數(shù)器清零等。
2.循環(huán)體部分(body):這是反復(fù)循環(huán)的一段代碼,可以是單一一條語(yǔ)句,也可以是復(fù)合語(yǔ)句。
3.迭代部分(iteration):這是在當(dāng)前循環(huán)結(jié)束,下一次循環(huán)開(kāi)始執(zhí)行的語(yǔ)句,常常用來(lái)使計(jì)數(shù)器加1或減1。
4.終止部分(termination):通常是一個(gè)布爾表達(dá)式,每一次循環(huán)要對(duì)該表達(dá)式求值,以驗(yàn)證是否滿足循環(huán)終止條件。
Java中提供的循環(huán)語(yǔ)句有:while語(yǔ)句,do-while語(yǔ)句和for語(yǔ)句,下分別介紹。
while語(yǔ)句
while語(yǔ)句實(shí)現(xiàn)"當(dāng)型"循環(huán),它的一般格式為;
[initialization]
while (termination){
body;
[iteration;]
}
1.當(dāng)布爾表達(dá)式(termination)的值為true時(shí),循環(huán)執(zhí)行大括號(hào)中語(yǔ)句。并且初始化部分和迭代部分是任選的。
2.while語(yǔ)句首先計(jì)算終止條件,當(dāng)條件滿足時(shí),才去執(zhí)行循環(huán)當(dāng)中的語(yǔ)句。這是"當(dāng)型"循環(huán)的特點(diǎn)。
do-while語(yǔ)句
do-while語(yǔ)句實(shí)現(xiàn)"直到型"循環(huán),它的一般格式為:
[initialization]
do{
body;
[iteration;]
}while (termination);
1.do-while語(yǔ)句首先執(zhí)行循環(huán)體,然后計(jì)算終止條件,若結(jié)果為true,則循環(huán)執(zhí)行大括號(hào)中的語(yǔ)句,直到布爾表達(dá)式的結(jié)果為false。
2.與while語(yǔ)句不同的是,do-while語(yǔ)句的循環(huán)體至少執(zhí)行一次,這是"直到型"循環(huán)的特點(diǎn)。
for語(yǔ)句
for語(yǔ)句也用來(lái)實(shí)現(xiàn)"當(dāng)型"循環(huán),它的一般格式為:
for(initialization;termination; iteration){
body;
}
1.for語(yǔ)句執(zhí)行時(shí),首先執(zhí)行初始化操作,然后判斷終止條件否滿足,如果滿足,則執(zhí)行循環(huán)體中的語(yǔ)句,最后執(zhí)行迭代部分。完成一次循環(huán)后,重新判斷終止條件。
2.可以在for語(yǔ)句的初始化部分聲明一個(gè)變量,它的作用域?yàn)橐粋€(gè)for語(yǔ)句。
3.for語(yǔ)句通常用來(lái)執(zhí)行循環(huán)次數(shù)確定的情況(如對(duì)數(shù)組元素進(jìn)行操作),也可以根據(jù)循環(huán)結(jié)束條件執(zhí)行循環(huán)次數(shù)不確定的情況。
4.在初始化部分和迭代部分可以使用逗號(hào)語(yǔ)句,來(lái)進(jìn)行多個(gè)操作。逗號(hào)語(yǔ)句是用逗號(hào)分隔的語(yǔ)句序列。例如:
for(i=0,j=10;i<j;i++, j--){
……
}
5.初始化、終止以及迭代部分都可以為空語(yǔ)句,三者均為空的時(shí)候,相當(dāng)于一個(gè)無(wú)限循環(huán)。
continue語(yǔ)句
1.continue語(yǔ)句用來(lái)結(jié)束本次循環(huán),跳過(guò)循環(huán)體中下面尚未執(zhí)的語(yǔ)句,接著進(jìn)行終止條件的判斷,以決定是否繼續(xù)循環(huán)。對(duì)于for語(yǔ)句,在進(jìn)行終止條件判斷前,還要先執(zhí)行迭代
語(yǔ)句。它的格式為:
continue;
2.也可以用continue跳轉(zhuǎn)到括號(hào)指明的外層循環(huán)中,這時(shí)的格為
continue outerLable;?
例 如 :?
outer: for( int i=0; i<10; i++ ){ ∥外層循環(huán)?
for( int j=0; j<20; j++ ){ ∥內(nèi)層循環(huán)?
if( j>i ){?
……?
continue outer;?
}?
……?
}?
……?
}?
該例中,當(dāng)滿足j>i的條件時(shí),程序執(zhí)行完相應(yīng)的語(yǔ)句后跳轉(zhuǎn)到外層循環(huán),執(zhí)行外層循環(huán)的迭代語(yǔ)句i++;然后開(kāi)始下一次循環(huán)。
可以從中來(lái)比較這三種循環(huán)語(yǔ)句,從而在不同的場(chǎng)合選擇合適的語(yǔ)句。
例外處理語(yǔ)句
例外處理語(yǔ)句包括try、catch、finally以及throw語(yǔ)句
注釋語(yǔ)
Java中可以采用三種注釋方式:
1∥ 用于單行注釋。注釋從∥開(kāi)始,終止于行尾。
2/*…*/用于多行注釋。注釋從/*開(kāi)始,到*/結(jié)束,且這種注釋不能互相嵌套。
3/**…*/是Java所特有的doc注釋。它以/**開(kāi)始,到*/結(jié)束。這種注釋主要是為支持JDK工具javadoc而采用的。javadoc能識(shí)別注釋中用標(biāo)記@標(biāo)識(shí)的一些特殊變量,并把doc注釋加入它所生成的HTML文件。