hi,
??? 今天無意中看到有個兄弟在java程序中多次用到了goto語句,感覺很是怪異,copy來編譯下發現有很多錯誤!
為此,我付出了一下午時間去研究這個塊被人遺忘了的可怕的"魔鬼".
?? “可怕”的goto語句是c和c++的“遺物”,它是該語言技術上的合法部分,引用goto語句引起了程序結構的混亂,不易理解,goto語句子要用于無條件轉移子程序和多結構分支技術。鑒于以廣理由,Java不提供goto語句,它雖然指定goto作為關鍵字,但不支持它的使用,使程序簡潔易讀。在Java中goto語句被完全拋棄了,與此同時,Java又擴大了break語句和continue語句的功能,通過使用break和continue,程序流程被允許在多層循環中跳轉。
大家再看看以下代碼:
?
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: 關閉連接");
??????????? 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("不能在連接池中創建新的連接. 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("不能關閉連接!");
_L1:
??????????? if(allConnections.hasMoreElements()) goto _L3; else goto _L2
_L2:
??????????? freeConnections.removeAllElements();
??????????? if(checkedOut != 0)
??????????? {
??????????????? retValue = false;
??????????????? DBConnectionManager.log.warn("DBConnectionManager: 內置的連接池沒有正確配置好");
??????????? }
??????????? 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: 不能加載驅動 = " + 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")));
??? }
}
這程序初看起來是多么的恐怖啊!多次用到goto,混亂。關于流程控制的方法,c++,java都提供了很好的語法:
分支語句 :if-else,break,switch, return.
循環語句 :while,do-while,for, continue.
例外處理語句 :try-catch-finally,throw
最后我們簡單介紹一下注釋語句
分
支語句
分支語句提供了一種控制機制,使得程序的執行可以跳過某些語句不執行,而轉去執行特定的語句。
條件語句if-else.
if-else語句根據判定條件的真假來執行兩種操作中的一種,格式為:
if(boolean-expression)
statement1;
[else statement2;]
1.布爾表達式boolean-expression是任意一個返回布爾型數據的達式(這比C、 C++的限制要嚴格)。
2.每個單一的語句后都必須有分號。
3.語句statement1,statement2可以為復合語句,這時要用大括號{}。建議對單一的語句也用大括號括起,這樣程序的可讀性強,而且有利于程序的擴充(可以在其中填加新的語句)。{}外面不加分號。
4.else子句是任選的。
5.若布爾表達式的值為true,則程序執行statement1,否則執行statement2。
6.if-else語句的一種特殊形式為:
if(expression1){?
statement1?
}else if (expression2){?
statement2?
}……?
}else if (expressionM){?
statementM?
}else {?
statementN?
}?
[else子句不能單獨作為語句使用,它必須和if配對使用。else總是與離它最近的if配對。可以通過使用大括號{}來改變配對關系。]
多分支語句switch
switch語句根據表達式的值來執行多個操作中的一個,它的般格式如下:
switch (expression){
casevalue1:statement1;
break;
casevalue2:statement2;
break;
…………
casevalueN:statemendN;
break;
[default:defaultStatement;]
}
1.表達式expression可以返回任一簡單類型的值(如整型、實數型、字符型),多分支語句把表達式返回的值與每個case子句中的值相比。如果匹配成功,則運行該case子句后的語句序列。
2.case子句中的值values必須是常量,而且所有case子句中的值是不同的。
3.default子句是任選的。當表達式的值與任一case子句中的都不匹配時,程序執行default后面的語句。如果表達式的值與任一case子句中的值都不匹配且沒有default子句,則程序不作任何操作,而是直接跳出switch語句。
4.break語句用來在執行完一個case分支后,使程序跳出switch語句,即終止switch語句的執行。因為case子句只是起到一個標號的作用,用來查找匹配的入口,從此處開始執行,對后面的case子句不再進行匹配,而是直接執行其后的語句序列,因此該在每個case分支后,要用break來終止后面的case分支語句的執行。
在一些特殊情況下,多個不同的case值要執行一組相同的操作,這時可以不用break。
5.case分支中包括多個執行語句時,可以不用大括號{}括起。
6.switch語句的功能可以用if-else來實現,但在某些情況下,使switch語句更簡煉,可讀性強,而且程序的執行效率提高。
break語句
1.在switch語中,break語句用來終止switch語句的執行。使程序switch語句后的第一個語句開始執行。
2.在Java中,可以為每個代碼塊加一個括號,一個代碼塊通常用大括號{}括起來的一段代碼。加標號的格式如下:
BlockLabel:{codeBlock}
break語句的第二種使用情況就是跳出它所指定的塊,并從緊挨該塊的第一條語句處執行。其格式為:
break BlockLabel;
例如:
a:{……//標記代碼塊a
b:{……//標記代碼塊b
c:{……//標記代碼塊c
break b;
…… //willnotbeexecuted
}
…… //willnotbeexecuted
}
…… //willnotbeexecuted
}
…… /executefromhere
}
3.與C、 C++不同,Java中沒有goto語句來實現任意的跳轉,因為goto語句破壞程序的可讀性,而且影響編譯的優化。但是從上例可以看出,Java用break來實現goto語句所特有的一些優點。如果break后所指定的標號不是一個代碼塊的標號,而是一個語句,則這時break完全實現goto的功能。不過應該避免這種方式的使用。
返回語句return
return語句從當前方法中退出,返回到調用該方法的語句處,繼續程序的執行。返回語句有兩種格式:
1.return expression
返回一個值給調用該方法的語句,返回值的數據類型必須用方法聲明中的返回值類型一致。可以使用強制類型轉換來使類型一致。
2.return
當方法說明中用void聲明返回類型為空時,應使用這種格式,不返回任何值。
return語句通常用在一個方法體的最后,以退出該方法并返一個值。Java中,單獨的return語句用在一個方法體的中間時,會產生編譯錯誤,因為這時有一些語句執行不到。但
可以通過把return語句嵌入某些語句(如if-else)來使程序在未執行完方法中的所有語句時退出,例如:
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?
循環語句
循環語句的作用是反復執行一段代碼,直到滿足終止循環條件為止,一個循環一般應包括四部分內容:
1.初始化部分(initialization):用來設置循環的一些初始條件,計數器清零等。
2.循環體部分(body):這是反復循環的一段代碼,可以是單一一條語句,也可以是復合語句。
3.迭代部分(iteration):這是在當前循環結束,下一次循環開始執行的語句,常常用來使計數器加1或減1。
4.終止部分(termination):通常是一個布爾表達式,每一次循環要對該表達式求值,以驗證是否滿足循環終止條件。
Java中提供的循環語句有:while語句,do-while語句和for語句,下分別介紹。
while語句
while語句實現"當型"循環,它的一般格式為;
[initialization]
while (termination){
body;
[iteration;]
}
1.當布爾表達式(termination)的值為true時,循環執行大括號中語句。并且初始化部分和迭代部分是任選的。
2.while語句首先計算終止條件,當條件滿足時,才去執行循環當中的語句。這是"當型"循環的特點。
do-while語句
do-while語句實現"直到型"循環,它的一般格式為:
[initialization]
do{
body;
[iteration;]
}while (termination);
1.do-while語句首先執行循環體,然后計算終止條件,若結果為true,則循環執行大括號中的語句,直到布爾表達式的結果為false。
2.與while語句不同的是,do-while語句的循環體至少執行一次,這是"直到型"循環的特點。
for語句
for語句也用來實現"當型"循環,它的一般格式為:
for(initialization;termination; iteration){
body;
}
1.for語句執行時,首先執行初始化操作,然后判斷終止條件否滿足,如果滿足,則執行循環體中的語句,最后執行迭代部分。完成一次循環后,重新判斷終止條件。
2.可以在for語句的初始化部分聲明一個變量,它的作用域為一個for語句。
3.for語句通常用來執行循環次數確定的情況(如對數組元素進行操作),也可以根據循環結束條件執行循環次數不確定的情況。
4.在初始化部分和迭代部分可以使用逗號語句,來進行多個操作。逗號語句是用逗號分隔的語句序列。例如:
for(i=0,j=10;i<j;i++, j--){
……
}
5.初始化、終止以及迭代部分都可以為空語句,三者均為空的時候,相當于一個無限循環。
continue語句
1.continue語句用來結束本次循環,跳過循環體中下面尚未執的語句,接著進行終止條件的判斷,以決定是否繼續循環。對于for語句,在進行終止條件判斷前,還要先執行迭代
語句。它的格式為:
continue;
2.也可以用continue跳轉到括號指明的外層循環中,這時的格為
continue outerLable;?
例 如 :?
outer: for( int i=0; i<10; i++ ){ ∥外層循環?
for( int j=0; j<20; j++ ){ ∥內層循環?
if( j>i ){?
……?
continue outer;?
}?
……?
}?
……?
}?
該例中,當滿足j>i的條件時,程序執行完相應的語句后跳轉到外層循環,執行外層循環的迭代語句i++;然后開始下一次循環。
可以從中來比較這三種循環語句,從而在不同的場合選擇合適的語句。
例外處理語句
例外處理語句包括try、catch、finally以及throw語句
注釋語
Java中可以采用三種注釋方式:
1∥ 用于單行注釋。注釋從∥開始,終止于行尾。
2/*…*/用于多行注釋。注釋從/*開始,到*/結束,且這種注釋不能互相嵌套。
3/**…*/是Java所特有的doc注釋。它以/**開始,到*/結束。這種注釋主要是為支持JDK工具javadoc而采用的。javadoc能識別注釋中用標記@標識的一些特殊變量,并把doc注釋加入它所生成的HTML文件。