天天看點

《Java 7程式設計入門經典》一3.14 像使用goto語句一樣使用break語句

除了用于switch語句和循環外,break語句也可以用提供像goto語句一樣的用法。由于goto語句是一種改變程式流的非結構化方法,是以java并沒有goto語句。使用了很多goto語句的程式一般難以了解和維護。但是,有一些使用goto語句的地方是有用且合理的。例如,在退出一組嵌套很深的循環時就是這樣。為了應對這種情況,java定義了break語句的擴充形式。例如,通過使用這種形式的break語句,可以從多層代碼塊退出。這些代碼塊不必是循環或是switch的一部分。它們可以是任意的代碼塊。另外,還可以精确指定執行恢複的位置,因為break的這種形式使用了标簽。break語句具有goto語句的優點,還避免了goto語句的一些問題。

這種有标簽的break語句的一般形式如下:

這裡,label是标簽名,辨別一句代碼或一個代碼塊。當這種形式的break語句執行時,控制權從标記的語句或塊中轉移出。标記的語句或塊必須包含break語句,但是它不一定是最近的語句或塊。例如,這意味着,可以用有标簽的break語句退出一系列嵌套代碼塊。但不能使用break語句将程式控制權轉移到不含break語句的塊中。

為了給語句和塊起個名字,可以在其開始處加标簽。标簽(label)是後加冒号的任意有效java辨別符。一旦為語句和塊加了标簽,就可以将這個标簽作為break語句的目标。這樣做可以執行語句或塊後的語句。例如,下面的程式有三個嵌套的循環。

《Java 7程式設計入門經典》一3.14 像使用goto語句一樣使用break語句
《Java 7程式設計入門經典》一3.14 像使用goto語句一樣使用break語句

程式的輸出如下所示:

《Java 7程式設計入門經典》一3.14 像使用goto語句一樣使用break語句

讓我們仔細看看這個程式,以了解為什麼生成這樣的輸出。當i為1時,第一個if語句成功,使break跳轉到由标簽one定義的代碼塊的末尾。這使得程式輸出“after block one”。當i為2時,第二個if語句成功,使控制權轉移到由标簽two标注的塊的末尾。這使程式順序輸出“after block two”和“after block one”。當i為3時,第三個if語句成功,控制權轉移到标記為three的語句的末尾。這時,三條消息都顯示。

再看一個例子。這個例子使用break語句從一系列嵌套的for循環中跳出。當内層運作的break語句執行時,程式控制權跳轉到外層for循環定義的塊的末尾,這個塊标記為done。這使得三重循環的剩餘部分不再執行。

程式輸出如下所示:

《Java 7程式設計入門經典》一3.14 像使用goto語句一樣使用break語句

在何處精确放置标簽十分重要,特别是當涉及循環時。例如,考慮下面的程式:

《Java 7程式設計入門經典》一3.14 像使用goto語句一樣使用break語句
《Java 7程式設計入門經典》一3.14 像使用goto語句一樣使用break語句
《Java 7程式設計入門經典》一3.14 像使用goto語句一樣使用break語句

在程式中,兩個嵌套的循環隻有一點不同。在第一個嵌套循環中,标簽在外層for語句的前面。在這種情況下,當執行break語句時,将控制權轉移到整個for塊的末尾,跳過外層循環疊代的其他代碼。在第二個嵌套循環中,标簽在外層for語句的左花括号前。于是,當執行break stop2時,控制權轉移到外層for語句塊的末尾,而不是循環的末尾。這引起下一次疊代的發生。

注意,不能跳轉到不是為包括break語句的語句或塊定義的标簽。例如,下面程式是無效的,不能編譯。

《Java 7程式設計入門經典》一3.14 像使用goto語句一樣使用break語句

因為标注為one的for循環不包括在第二個for循環中的break語句,是以不可能将控制權轉移到那個标簽。

《Java 7程式設計入門經典》一3.14 像使用goto語句一樣使用break語句