Java开发笔记(二十二)神奇的冒号

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

相关文章
相关标签/搜索