控制执行流程(2)

一、return

    在java中有许多个关键词表示无条件分支,它们只是表示这个分支无需任何测试即可发生。这些关键词包括return、break、continue。

    return关键词有两方面的用途:一方面指定一个方法返回什么值(假设它没有void返回值),另一方面它会导致当前的方法退出,并返回那个值。例如:

public class IfElse {

	static int test(int testval, int target) {
		if (testval > target)
			return +1;
		else if (testval < target)
			return -1;
		else
			return 0;
	}

	public static void main(String[] args) {
		System.out.println(test(10, 5));
		System.out.println(test(5, 10));
		System.out.println(test(5, 5));
	}
}

    不必加上else,因为方法在执行了return后不再继续执行。

    如果在返回void的方法中没有return语句,那么在该方法的结尾处会有一个隐藏的return,因此在方法中并非总是必须要有一个return语句。但是,如果一个方法声明它将返回void之外的其他东西,那么必须确保每一条代码路径都将返回一个值。

二、break和continue

    在任何迭代语句的主体部分,都可用break和continue控制循环的流程。其中,break用于强行退出循环,不执行循环中剩余的语句。而continue则停止执行当前的迭代,然后退回循环起始处,开始下一次迭代。

    下面这个程序向大家展示了break和continue在for和while循环中的例子:

public class BreakAndContinue {
	public static void main(String[] args) {
		for (int i = 0; i < 100; i++) {
			if (i == 74)
				break;// Out of for loop
			if (i % 9 != 0)
				continue;// Next iteration
			System.out.println(i + " ");
		}

		int i = 0;
		while (true) {
			i++;
			int j = i * 27;
			if (j == 1269)
				break;// Out of loop
			if (i % 10 != 0)
				continue;// Top of loop
			System.out.println(i + " ");
		}
	}
}

    在这个for循环中,i的值永远不会达到100;因为一旦i达到74,break语句就会中断循环。通常,只有在不知道中断条件何时满足时,才需要这样使用break。只要i不被9整除,continue语句就会使执行过程返回到循环的最开头(这使i值递增)。如果能够整除,则将值显示出来。

    第二个可以看到一个“无穷while循环”的情况。然而,循环内部有一个break语句,可终止循环。除此之外,还会看到continue语句执行序列移回到循环的开头,而没有去完成continue语句之后的所有内容。(只有i被10整除时才打印出值。)输出结果之所以显示0,是由于0%9等于0;

    无穷循环的第二种形式是for(;;)。编译器将while(true)与for(;;)看作同一回事。所以具体选用哪个取决于自己的编程习惯。

(1)标签

    在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循环的例子:

public class LabeledFor {
	public static void main(String[] args) {
		int i = 0;
		outer: for (; true;) {
			inner: 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++;
					break;
				}
				if (i == 7) {
					System.out.println("continue outer");
					i++;
					continue outer;
				}
				if (i == 8) {
					System.out.println("break outer");
					i++;
					break outer;
				}
				for (int k = 0; k < 5; k++) {
					if (k == 3) {
						System.out.println("continue inner");
						continue inner;
					}
				}
			}
		}
	}
}

    注意,break会中断for循环,而且在抵达for循环的末尾之前,递增表达式不会执行。由于break跳过了递增表达式,所以在i==3的情况下直接对i执行递增运算。在i==7的情况下,由于continue outer语句会跳到循环顶部,而且也会跳过递增,所以这里也对i直接递增。

    如果没有break outer语句,就没有办法从内部循环里跳出外部循环。这是由于break本身只能中断最内层的循环(continue同样也是如此)。

    当然,如果想在中断循环的同时退出,简单地用一个return即可。

    下面这个例子向大家展示了带标签的break以及continue语句在while循环中的用法:

public class LabeledWhile {
	public static void main(String[] args) {
		int 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;
				}
			}
		}
	}
}

    同样的规则亦适用于while:

  1. 一般的continue会退回最内层循环的开头(顶部),并继续执行。
  2. 带标签的continue会到达标签的位置,并重新进入紧接在那个标签后面的循环。
  3. 一般的break会中断并跳出当前循环。
  4. 带标签的break会中断并跳出标签所指的循环。

    要记住的重点是:java里需要使用标签的唯一理由就是因为有循环嵌套存在,而且想从多层嵌套中break或continue。

三、switch

    switch有时也被规划为一种选择语句。根据整数表达式的值,switch语句可以从一系列代码中选出一段去执行。它的格式如下:

switch(integral-selector) {
	case integral-value1:statement:break;
	case integral-value2:statement:break;
	case integral-value3:statement:break;
	case integral-value4:statement:break;
	case integral-value5:statement:break;
	// ..
	default:statement;
}

    其中,Integral-selector(整数选择因子)是一个能够产生整数值的表达式,switch能将这个表达式的结果与每个integral-value(整数值)相比较。若发现相符的,就执行对应的语句(单一语句或多条语句,其中并不需要括号)。若没有发现相符的,就执行default(默认)语句。

    在上面的定义中,大家会注意到每个case均以一个break结尾,这样可使执行流程跳转至switch主体的末尾。这是构建switch语句的一种传统方式,但break是可选的。若省略break,会继续执行后面的case语句,直到遇到一个break为止。尽管通常不想出现这种情况,但对有经验的程序员来说,也许能够善加利用这种情况。注意最后的default语句没有break,因为执行流程已到了break的跳转目的地。当然,如果考虑到编程风格方面的原因,完全可以在default语句的末尾放置一个break,尽管它并没有任何实际的用处。

    switch语句是来实现多路选择(也就是说从一系列执行路径中挑选一个)的一种干净利落的方法。但它要求使用一个选择因子,并且必须是int或char那样的整数值。在java SE7中支持Stirng类型。enum可以帮助我们减弱这种限制,因为enum可以和switch协调工作。

    下面这个例子可随机生成字母,并判断它们是元音还是辅音字母:

import java.util.Random;

public class VowelsAndConsonants {
	public static void main(String[] args) {
		Random r = new Random(47);
		for (int i = 0; i < 100; i++) {
			int c = r.nextInt(26) + 'a';
			System.out.print((char) c + ", " + c + ":");
			switch (c) {
			case 'a':
			case 'e':
			case 'i':
			case 'o':
			case 'u':
				System.out.println("vowel");
				break;
			case 'y':
			case 'w':
				System.out.println("Sometimes a vowel");
				break;
			default:
				System.out.println("consonant");
			}
		}
	}
}

    由于Random.nextInt(26)会产生0到26之间的一个值,所以在其加上一个偏移量“a”,即可产生小写字母。在case语句中,使用单引号引起的字符也会产生用于比较的整数值。

    请注意case语句能够堆叠在一起,为一段代码形成多重匹配,即只要符合多种条件中的一种,就执行那段特别的代码。这时也应注意将break语句置于特定case的末尾,否则控制流程会简单的下移,处理后面的case。

    在下面语句中:

int c = r.nextInt(26) + 'a';

    r.nextInt(26)将产生0~25之间的一个随机int值,他将被加到“a”上。这表示“a”将自动被转为int以执行加法。为了把c当作字符打印,必须将其转型为char;否则将产生整型输出。

发布了71 篇原创文章 · 获赞 2 · 访问量 6155

猜你喜欢

转载自blog.csdn.net/qq_40298351/article/details/104028402
今日推荐