4.1 return
关键字return有两方面的用途:一方面指定一个方法结束时返回一个值;一方面强行在return位置结束整个方法,如下所示:
char test(int score) { if (score >= 90) return 'A'; if (score >= 80) return 'B'; if (score >= 70) return 'C'; if (score >= 60) return 'D'; else //if (score < 60) return 'E'; }
如上,如果变量score大于或等于90,则在第 3 行结束整个方法,并返回字符'A',如果大于或等于80,则在第5行结束整个方法,并返回字符'B',以此类推,如果score小于60,则在第11行结束整个方法,并返回字符'E'。注意上面的注释,尽管去掉注释后,逻辑上讲得通,但是计算机可不懂人类的这点逻辑,所以当方法是有返回值的时候(视void方法为无返回值的方法),if语句要与else连用。
如果是在返回值为void的方法,return会使方法在当前位置提前结束,如果没有加上return,那么方法的结尾会有隐式的return
void test(int e) { if (e == 1) return;// 如果e等于1,下面的e++就不会执行了 e++; }
4.2 if-else
if-else的语法已经在上一节展示出来了,需要强调的是不可拿数字来做条件判断,while、do-while和for循环的条件判断也不可是数字,尽管我们知道C和C++可以用数字来判断true或false
4.3 迭代(while、do-while、for)
之所以说while、do-while和for语句是迭代语句,是因为它们的语句会重复执行,直到起控制作用的布尔表达式得到“假”的结果为止。
while的循环格式如下:
while (Boolean-expression) statement
do-while的循环格式如下:
do statement while (Boolean-expression);// 不要忘了分号;
NOTE:while和do-while唯一的区别就是do-while中的语句至少会执行一次,即便表达式第一次就被计算为false。而在while循环结构中,如果条件第一次就为false,那么其中的语句根本就不会执行。
for循环的格式如下:
for (initialization; Boolean-expression; step) statement
其实相当于while循环:
initialization while (Boolean-expression) { statement step }
初始化表达式(initialization)、布尔表达式(Boolean-expression)和步进运算(step)都可以为空。
逗号操作符(非逗号分隔符)
Java里唯一用到逗号操作符的地方就是for循环的控制表达式。在控制表达式的初始化和步进控制部分,可以使用一系列由逗号分隔的语句;而且那些语句均会独立运行
public class CommaOperator { public static void main(String[] args) { for (int i = 1, j = i + 10; i < 5; i++, j = i * 2) { out.println("i = " + i + "j = " + j); } } }/* i = 1 j = 11 i = 2 j = 4 i = 3 j = 6 i = 4 j = 8 */
for语句中的int定义覆盖了 i 和 j,在初始化部分实际上可以拥有任意数量的具有相同类型的变量定义。在一个控制表达式中,定义多个变量的这种能力只限于for循环适用,在其他任何选择语句中都不能使用这种方式。
可以看到,无论是在初始化还是步进部分,语句都是顺序执行的。此外,初始化部分可以有任意数量的同一类型的定义。
4.4 Foreach语法
foreach访问数组和容器时会显得更加简洁和高效,这里展示访问数组的例子
int[] a = new int[10]; for (int i = 1; i <= 10; i++) a[i - 1] = i; for (int e : a) out.println(e);
4.5 break和continue
break用于强行退出当前循环,不执行剩余的迭代;而continue则停止执行当前的迭代,然后退回循环开始初,继续下一次迭代。
for (int i = 0; i < 100; i++) { if (i == 74) break;// 若等于74,退出for循环 if (i % 9 != 0) continue;// 若不是9的整数倍,跳过下面的语句,继续下一次迭代 out.println(i + " "); } println(); int i = 0; while (true) { i++; int j = i * 27; if (j == 1269) break;// 若j等于1269,退出while循环 if (i % 10 != 0) continue;// 若i不是10的整数倍,跳过下面的语句,继续下一次迭代 out.println(i + " "); }
break和continue也可以像goto关键字那样使用标签,不过还是少用好一点。格式如下
label1://标签,注意千万不可在label1和outer-iteration之间写任何代码 outer-iteration {//外部迭代 inner-iteration {//内部迭代 // ... break;// (1) // ... continue;// (2) // ... continue label1;// (3) // ... break label1;// (4) } }
在(1)中,break中断内部迭代(inner-iteration),回到外部迭代(outer-iteration);
在(2)中,continue跳过下面的语句,回到内部迭代(inner-iteration)的起始处,继续下一次内部迭代(inner-iteration);
在(3)中,continue label1同时中断内部迭代(inner-iteration)和外部迭代(outer-iteration),直接跳转到label1处,随后它实际上是继续迭代过程,但却是从外部迭代(outer-iteration)开始;
在(4)中,break label1将中断所有迭代,并回到label1除,但不再进入迭代了。
下面这个例子展示了带有标签的break和continue
int i = 0; outer: for (; true;) { inner: for(; i < 10; i++) { println("i = " + i); if (i == 2) { out.println("continue"); continue; } if (i == 3) { out.println("break"); i++; break; } if (i == 7) { out.println("continue outer"); i++; continue outer; } if (i == 8) { out.println("break outer"); break outer; } for (int k = 0; k < 5; k++) { if (k == 3) { out.println("continue inner"); continue inner; } } } }/*输出结果 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迭代。
要记住的重点是:在Java里需要使用标签的唯一理由无非因为有循环嵌套存在,而且想方便地从多层嵌套中break和continue。
4.6 switch
switch有时也被划归为一种选择语句。根据整数表达式的值,switch语句可以从一系列代码中选出一段去执行。它的格式如下:
switch (selector) { case value1 : statement;break; case value2 : statement;break; case value3 : statement;break; // ... default: statement; }
其中,selector(选择因子)是一个能够产生整型数(或String类型)的表达式,switch能将这个表达式的结果与每个value相比较。若发现相符的,就执行对应的语句(单一的语句或多条语句,其中并不需要括号的)。若没有发现相符的,就执行default语句。关于selector,在jdk1.7以前不能是String类型,而从jdk1.7开始,就既能是整型类型,也能是String类型了。
在上面的定义中,大家会注意到每个case均以一个break结尾,这样可使执行流程跳转到switch主体的结尾。这是构建switch语句的一种传统方式,但break是可选的。若省略break,会继续执行后面的case语句(如果有的话),直到遇到一个break为止。注意最后的default语句没有break,因为执行流程已到了break的跳转目的地,当然,自己完全可以在default语句的末尾放置一个break,尽管这样做没有任何用处。
public class VowelsAndConsonants { public static void main(String[] args) { Random random = new Random(1972); for (int i = 0; i < 5; i++) { int c = random.nextInt(26) + 'a'; out.println((char)c + ", " + c + ": "); switch (c) { case 'a' : case 'e' : case 'i' : case 'o' : case 'u' : out.println("vowel"); break; case 'y' : out.println("Sometimes a vowel"); break; default: out.println("Consonant"); } } } }
从这个例子,可以看到case语句可以堆叠在一起,为一段代码形成多重匹配。这时也要注意将break语句置与特定的case的末尾,否则控制流程会简单的往下移,处理后面的case