天天看點

Java 中break和continue結合标簽标示符中斷循環示例詳解(附源碼)臭名昭著的goto标簽是什麼示例源碼輸出結果源碼解析

臭名昭著的goto

       程式設計語言中一開始就有 goto關鍵詞了。事實上, goto起源于彙編語言的程式控制:“若條件 A成立,則跳到這裡;否則跳到那裡”。如果閱讀由編譯器最終生成的彙編代碼,就會發現程式控制裡包含了許多跳轉。( Java編譯器生成它自己的“彙編代碼”,但是這個代碼是運作在 Java虛拟機上的,而不是直接運作在 CPU硬體上。)         goto語句是在源碼級上的跳轉,這使其招緻了不好的聲譽。若一個程式總是從一個地方跳到另一個地方,還有什麼辦法能識别程式的控制流程呢?自從Edsger Dijkstra發表了著名論文 《Goto considered harmful》( Goto有害),衆人開始痛斥 goto的不是,甚至建議将它從關鍵字集合中掃地出門。        對于這個問題,中庸之道是最好解決方法。真正的問題并不在于使用 goto,而在于 goto的濫用;而且少數情況下, goto還是組織控制流程的最佳手段。

标簽是什麼

      盡管 goto仍是 Java中的一個保留字,但在語言中并未使用它; Java沒有 goto。然而, Java也能完成一些類似于跳轉的操作,這與 break和 continue這兩個關鍵詞有關。它們其實不是一個跳轉,而是中斷疊代語句的一種方法。之是以把它們納入 goto問題中一起讨論,是由于它們使用了相同的機制:标簽。        标簽是後面跟有冒号的标示符,就像下面這樣:

label1:
           

      在 Java中,标簽起作用的唯一的地方剛好是在疊代語句之前。“剛好之前”的意思表明,在标簽和疊代之間置入任何語句都不好。而在疊代之前設定标簽的唯一理由是:我們希望在其中嵌套另一個疊代或者一個開關。這是由于 break和 continue關鍵詞通常隻是中斷目前循環,但若随同标簽一起使用,它們就會中斷循環,直到标簽所在的地方:

label1:
		outer-iteration{
			inner-iteration{
				//...
				break;//(1)
				//...
				continue;//(2)
				//...
				continue label1;//(3)
				//...
				break label1;//(4)
			}
		}
           

      在(1)中, break中斷内部疊代,回到外部疊代。在(2)中, continue使執行點移回内部疊代的起始處。在(3)中, continue label1同時中斷内部疊代及外部疊代,直接轉到 label1處;随後,它實際上是繼續疊代過程,但卻從外部疊代開始。在(4)中, break label1也會中斷所有疊代,并回到 label1處,但并不重新進入疊代。也就是說,它實際是完全中止了兩個疊代。

示例源碼

下面是标簽用于 for循環和 while循環的例子:

package com.mufeng.thefourthchapter;

public class Labeled {
	public static void main(String[] args) {
		System.out.println("标簽用于for循環的例子");
		int i = 0;
		outer: // Can't have statements here 這裡不能有陳述
		for (; true;) {// infinite loop 無限循環
			inner: // Can't have statements here 這裡不能有陳述
			for (; i < 10; i++) {
				System.out.println("i = " + i);
				if (i == 2) {
					System.out.println("continue");
					continue;
				}

				if (i == 3) {
					System.out.println("break");
					i++;// Otherwise i never gets incremented 否則i不會得到增量
					break;
				}

				if (i == 7) {
					System.out.println("continue outer");
					i++;// Otherwise i never gets incremented 否則i不會得到增量
					continue outer;
				}

				if (i == 8) {
					System.out.println("break outer");
					break outer;
				}

				for (int k = 0; k < 5; k++) {
					if (k == 3) {
						System.out.println("continue inner");
						continue inner;
					}
				}

			}
		}
		System.out.println("标簽用于while循環的例子");

		i = 0;
		outer: while (true) {
			System.out.println("Outer while loop");
			while (true) {
				i++;
				System.out.println("i = " + i);

				if (i == 1) {
					System.out.println("continue");
					continue;
				}

				if (i == 3) {
					System.out.println("continue outer");
					continue outer;
				}

				if (i == 5) {
					System.out.println("break");
					break;
				}

				if (i == 7) {
					System.out.println("break outer");
					break outer;
				}
			}
		}

	}

}
           

輸出結果

标簽用于for循環的例子
i = 0
continue inner
i = 1
continue inner
i = 2
continue
i = 3
break
i = 4
continue inner
i = 5
continue inner
i = 6
continue inner
i = 7
continue outer
i = 8
break outer
标簽用于while循環的例子
Outer while loop
i = 1
continue
i = 2
i = 3
continue outer
Outer while loop
i = 4
i = 5
break
Outer while loop
i = 6
i = 7
break outer
           

源碼解析

       注意, break會中斷 for循環,而且在抵達 for循環的末尾之前,遞增表達式不會執行。由于 break跳過了遞增表達式,是以在 i==3的情況下直接對 i執行遞增運算。在 i==7的情況下, continue outer語句會跳到循環頂部,而且也會跳過遞增,是以這裡也對 i直接遞增。        如果沒有 break outer語句,就沒辦法從内部循環裡跳出外部循環。這是由于 break本身隻能中斷最内層的循環( continue同樣也是如此)。        當然,如果想在中斷循環的同時退出,簡單地用一個 return即可。        同樣的規則亦适用于 while:

  • 一般的continue會退回最内層循環的開頭(頂部),并繼續執行。
  • 帶有标簽的continue會到達标簽的位置,并重新進入緊接在那個标簽後面的循環。
  • 一般的break會中斷并跳出目前循環。
  • 帶标簽的break會中斷并跳出标簽所指的循環。

        要記住的重點是:在 Java裡需要使用标簽的唯一理由就是因為有循環嵌套存在,而且想從多層嵌套中 break或 continue。