Java中的標點符號主要有兩類用途,一類是運算符,包括加號+、減號-、乘號*、除號/、取餘號%、等號=、大於號>、小於號<、與號&、或號|、非號!、異或號^等等,另外一類則是分隔符,包括區分代碼塊的花括號{}、容納特定語句的圓括號()、標明數組元素的方括號[]、分隔長句的分號、分隔短句的逗號、分隔包名類名方法名的點號等等。固然還有幾個特殊的分隔符,好比三元運算符「?:」,它的完整形式爲「A?:B:C」,當式子A成立時,獲得式子B的結果,不成立時獲得式子C的結果。這些標點符號之中,尤以冒號最爲特殊,之因此這麼說,是由於Java編程一遇到特殊的分隔場景,基本都拿冒號這個萬金油作標記。java
冒號除了用在三元運算符「?:」之外,至少還有其它三種用法。第二種是在多路分支的時候,猶記得當年switch-case並肩做戰,每一個case帶着數值再拖上具體的處理語句,case條件與處理語句之間但是以冒號分隔的,剩餘的默認狀況default也是經過冒號同處理語句區分開。譬以下面的多路分支代碼,就能看到冒號的分隔做用:編程
// switch容許判斷某個變量的多個取值,並分別進行單獨處理 switch (seq) { case 1: // seq值爲1時進入該分支 System.out.println("涼風有信的謎底是「諷」"); break; // 跳出多路分支。即跳到switch分支的右花括號以後 case 2: // seq值爲2時進入該分支 System.out.println("秋月無邊的謎底是「二」"); break; // 跳出多路分支。即跳到switch分支的右花括號以後 default: // seq值爲其它時進入該分支 System.out.println("您的按鍵有誤"); break; // 跳出多路分支。即跳到switch分支的右花括號以後 }
冒號的第三種用法,則跟數組的循環遍歷有關。要想把某個數組裏的全部元素數值都打印出來,就得經過for循環依次取出數組的每一個元素,再打印該元素的數值。以整型數組爲例,利用for語句遍歷並打印元素的代碼以下所示:數組
int[] primeNumbers = {2, 3, 5, 7}; for (int i = 0; i < primeNumbers.length; i++) { int number = primeNumbers[i]; // 獲取下標爲i的元素,並賦值給名爲number的變量 System.out.println("prime number = " + number); }
上面的循環語句很常規,用法形式也很常見,無非是依次取出數組裏的每一個元素罷了。假若此時不修改元素數值,僅僅是讀取數值的話,那麼能夠簡化成一套通用的循環模板,就像下述的循環語句那樣:oop
int[] primeNumbers = {2, 3, 5, 7}; // 在for循環中,能夠利用「變量類型 變量名稱 : 數組名稱」的形式,直接把數組元素賦值給該變量 for (int number : primeNumbers) { System.out.println("number = "+number); }
上述的Java代碼,把原循環內部的變量number提早放到for後面的圓括號當中,而且number與數組primeNumbers之間用冒號分開,表示每次循環處理以前,都把數組元素逐個賦值給number變量,而後循環內部便可直接處理該變量。如此這般便優化了先前的for循環代碼,免去了冗餘的數組下標、判斷條件以及自增操做。優化
冒號的第四種用法也與循環語句有關,但不限於for循環,而是與for和while都有關聯。前述的循環處理,基本都只有一層循環,然而實際開發經常會遇到多層循環,也就是一個循環內部嵌套了另外一個循環,看起來像是層巒疊嶂、反覆重疊,故又被稱做多重循環。例若有個二維數組,要把它裏面的全部元素都打印出來,這便須要兩層循環才能搞定,第一層循環負責遍歷第一個維度的下標,而第二層循環負責遍歷第二個維度的下標,編碼上則需一個for循環嵌套另外一個for循環,具體的Java實現代碼以下所示:編碼
double[][] triangle = { {-2.0, 0.0}, {0.0, -1.0}, {2.0, 1.0} }; // 下面經過多重循環依次打印二維數組裏面的全部元素 for (int i=0; i<triangle.length; i++) { for (int j=0; j<triangle[i].length; j++) { System.out.println("value = "+triangle[i][j]); } }
可見以上的多重循環代碼仍是挺簡單的,並不涉及到複雜的break和continue操做。即便用到break和continue,處理邏輯也沒有什麼特別之處,由於break語句想固然就是隻能跳出當前層次的循環,不能跳出上個層次的循環,continue語句同理。因此要想從內層循環跳出外層循環,就得設置一個標記,從內層循環跳到外層循環時,經過判斷該標記再決定是否馬上跳出外層循環。仍之前面的二維數組爲例,假設在內層循環找到某個元素爲0.0,則當即結束所有循環(包括外層循環和內層循環),按此思路編寫的代碼例子見下:blog
// 下面的循環要求:一旦發現數組元素等於0.0,就當即從第二層循環跳出第一層循環(跳出兩層循環) for (int i=0; i<triangle.length; i++) { boolean isFound = false; // 該布爾變量用來標記是否找到0.0 for (int j=0; j<triangle[i].length; j++) { if (triangle[i][j] == 0.0) { isFound = true; // 找到了0.0 System.out.println("simple found 0.0"); break; // 跳出第二層循環 } } if (isFound) { break; // 跳出第一層循環 } }
以上代碼當然實現了功能要求,可是兩個break的寫法着實使人憋屈,並且布爾變量isFound純粹是到此一遊。有沒有一種寫法容許讓代碼直接從內層循環跳出外層循環呢?與其讓布爾變量作標記,不如給外層循環加個記號,而後內層循環就能告訴編譯器,接下來的break語句要跳出指定標記的循環。這時冒號便派上用場了,經過形如「標記名稱 : for或者while」的表達式,便可給指定循環起個外號,因而語句「break 標記名稱」便實現了跳出指定循環的需求。那麼使用新寫法改造前面的循環跳出代碼,修改以後的代碼以下所示:開發
// 下面的loop1是一個記號,連同後面的冒號加在for前面,表示它指代這個for循環 loop1 : for (int i=0; i<triangle.length; i++) { for (int j=0; j<triangle[i].length; j++) { if (triangle[i][j] == 0.0) { System.out.println("loop1 found 0.0"); break loop1; // 跳出loop1表明的循環,也就是跳出第一層循環 } } }
如上代碼先在外層的for循環以前添加「loop1 : 」,代表外層循環的綽號叫loop1,而後內層循環的break語句改爲「break loop1;」,表示跳出loop1這個外層循環,這樣只需一個break語句就跳出多重循環了。除了break語句,continue也容許帶上標記名稱,好比「continue loop1」表示繼續loop1這個外層循環的下一次循環處理,而且while循環也一樣承認在break和continue後面添加標記。固然,利用前面介紹的冒號第三種用法,上面的多重循環還能簡化成下述這般代碼:編譯器
// 下面用到了兩種冒號,一種用來標記循環,另外一種用來簡化數組遍歷 loop2 : for (double[] dot : triangle) { // dot等價於前面的triangle[i] for (double coordinate : dot) { // coordinate等價於前面的triangle[i][j] if (coordinate == 0.0) { System.out.println("loop2 found 0.0"); break loop2; // 跳出loop2表明的循環 } } }
如此一來,上述的循環代碼聯合應用了冒號的兩種用法,整個代碼也變得更加精煉了。it