JAVA编程讲义.Java控制结构
第3章 Java控制结构
在前面的学习中,我们编写的程序都是按照编写顺序一行一行地执行的。然而,现实世界中事物的发展变化却并不一定是按顺序进行,往往需要在某些节点处做出选择或者需要循环运行某些过程。程序存在的意义是模拟现实,简单地按顺序执行显然无法满足要求,这就需要用到流程控制语句。事实上,对于任何一门程序设计语言来说,流程控制语句都是其实现代码执行顺序控制的基本工具。本章我们就来学习Java语言的控制语句。
3.1 Java程序结构
编程的目的在于模拟现实,以实现现实生活中所需的功能。通过前面的学习我们知道,我们编写的代码都是从上到下逐条执行的。那么,这种执行顺序能否满足需求呢?答案是不一定,对于简单的程序设计,从上到下逐条执行可以满足需求;但是只要程序的逻辑稍微复杂一点,从上到下逐条执行就显得力不从心,要么需要编写很多行代码,要么根本无法实现。就拿我们最熟悉的放学回家这件事情来说吧,从准备走出教学楼开始,我们就要做一系列的选择:可以乘坐电梯下楼,也可以走楼梯下楼;到达楼下后,又需要考虑以哪种方式回家,乘坐公共汽车、骑自行车还是步行;无论选择如何回家,走到十字路口时,又需要根据交通信号灯来决定是走是停,红灯停、绿灯行、黄灯亮了等一等,而同样的等红灯动作又需要经历n次。所以,在放学回家的过程中,大家需要面临多种选择,重复n次等红灯操作。使用简单的从上到下逐条执行的方式编写程序来模拟这一过程,显然是力不从心的。Java语言提供了三种程序结构,分别是顺序结构、选择结构、循环结构来协助完成复杂的程序设计。
1.顺序结构
所谓顺序结构,具体指的是程序从上往下按照代码的顺序依次执行,一条语句执行完之后继续执行下一条语句,一直到程序的末尾,在一次执行过程中不会有哪条语句被重复执行两次,也不会有哪条语句被跳过不执行,无论执行多少次情况都是如此。顺序结构是程序设计中最常使用、最简单的结构,大部分程序都是按照顺序结构设计的。顺序结构的运行结构流程,如图3.1所示。
2.选择结构
选择结构也称为分支结构,主要由分支语句构成。选择结构通常需要先明确判断条件,在程序的执行过程中,当遇到选择结构的时候,会根据预设的判断条件来确定接下来应该执行的语句块(一条或者多条语句的集合)。如果条件成立,则执行满足条件时的语句块,反之则执行另外的语句块。选择结构的运行结构流程,如图3.2所示。
3.循环结构
在实际的生活中也会遇到很多具有规律性的重复操作,比如让学生抄写n遍单词,那么抄写这些单词的动作就要重复地进行n遍。如果用程序来模拟就是相同的代码要写n次,对于计算机程序而言,这样肯定是不合理的,此时就可以引入循环结构来完成这个功能。所谓循环结构,具体指的是在满足一定条件的情况下,反复去执行某段代码,从而实现代码的复用。这个条件称为循环条件,这个重复执行的代码称为循环体,每一次循环都要对循环变量(判断条件中的变量)进行重新赋值,这个动作称为循环变量更替。也就是说,循环结构有3大要素:循环变量、循环体、循环条件。循环结构的运行流程,如图3.3所示。
图3.1 顺序结构 图3.2 选择结构 图3.3 循环结构
上述3种结构是今后程序设计过程中最常用的基本结构,它们有以下共同特点:
• 结构的入口都只有一个(单入口)。
• 结构的出口也只有一个(单出口)。
• 结构内的每一部分都有可能被执行到。
• 结构内部不存在“死循环”。
3.2 选择语句
在Java语言中,选择结构通过选择语句来实现,它通过给定的条件进行判断,从而决定执行多个分支中的哪一个。本节就来详细讲解Java的选择语句:if条件语句与switch条件语句。
3.2.1 if条件语句
if条件语句用来控制程序在满足某些条件的情况下执行某段特定的代码,不满足条件的时候转而执行其他的语句。if条件语句有3种形式:简单if语句、if-else语句、else if多分支语句,接下来分别对这3种形式做详细讲解。
1.简单if语句
简单if语句包含一个判断条件和该条件成立的情况下需要执行的语句块,具体语法结构如下:
if(判断条件){
语句块;
}
简单if语句的执行流程如图3.4所示,其中判断条件可以是布尔型变量、常量或者布尔表达式,也可以是多个条件的组合,但判断条件的结果必须为布尔类型。当判断条件的结果为true时,程序将会执行if后紧邻的语句块,如果该语句块由多条语句组成则使用“{}”将其包括起来,如果只有一条语句则“{}”可以不写;当判断条件的结果为false时,则会结束当前if语句,跳过条件成立时所需执行的语句块,继续执行后续的代码。
根据以上语法,实现案例:输入小明的考试成绩,如果成绩大于等于80分,输出“考的不错,给个鸡腿以示奖励”,如例3-1所示。
例3-1 Demo0301.java
1 package com.aaa.p030201;
2 import java.util.Scanner;
3
4 public class Demo0301 {
5 public static void main(String[] args) {
6 Scanner sca = new Scanner(System.in);
7 System.out.println("------请输入小明的考试成绩-----");
8 double score = sca.nextDouble(); // 定义变量接收小明的录入成绩
9 if (score >= 80){
10 System.out.println("考的不错,给个鸡腿以示奖励");
11 }
12 System.out.println("考好不要骄傲,考坏不要气馁,继续加油!!!");
13 }
14 }
运行程序,输入小明的成绩为90分,运行结果如下:
------请输入小明的考试成绩-----
90
考的不错,给个鸡腿以示奖励!
考好不要骄傲,考坏不要气馁,继续加油!!!
再次运行程序,输入小明的成绩为70分,运行结果如下:
------请输入小明的考试成绩-----
70
考好不要骄傲,考坏不要气馁,继续加油!!!
例3-1中,第8行中定义变量来接收小明的考试成绩。第9~11行是一个简单if语句,第9行中的“score >= 80”是判断条件(布尔表达式)。当表达式成立(返回结果为true)的时候,将会执行该if后紧邻的语句块,也就是“{}”中的第10行语句;当表达式不成立(返回结果为false)的时候,程序将会结束if语句,执行第12行语句。
对比两次运行结果,我们可以看到:第1次输入小明的成绩为90分时,判断条件“score >= 80”成立,即表达式结果返回为true,此时程序执行了第10行的语句,“考的不错,给个鸡腿以示奖励”先被打印出来,而后又执行了第12行语句打印了“考好不要骄傲,考坏不要气馁,继续加油!!!”。第2次输入小明的成绩为70分时,判断条件“score >= 80”不成立,即表达式结果返回为false,此时程序跳过了第10行的语句,转而执行了第12行的语句打印了“考好不要骄傲,考坏不要气馁,继续加油!!!”
注意:如果条件后的语句块只有一条的情况下,{}可以省略,但为了保证可读性,一般不建议省略。
2. if-else语句
简单if语句只表明了在条件成立的情况下应该执行什么样的处理,但是条件不成立的时候,语句就结束了,程序也将继续执行后续的代码。那么,如果我们在条件不成立的时候也需要进行其他的处理,应该怎么做呢?这时候我们可以使用if-else语句来处理,if-else语句称为双分支语句。所谓双分支,具体指的是在条件成立的时候执行某些处理,在条件不成立的时候会执行另外的处理,然后才会结束语句,继续执行后续的代码。if-else语句的语法结构如下:
if (判断条件){
语句块1;
}else{
语句块2;
}
if-else语句的执行流程如图3.5所示,在该语句中,判断条件的要求与简单if语句一样,其结果必须为布尔类型,当结果为true时,将会执行紧邻if后的语句块1,当结果为false时执行else后的语句块2。if-else语句与简单if语句的区别在于,如果条件不成立,则会执行else后的语句块2而不是直接结束语句,也就是说语句块1和语句块2必定有一个会被执行。
注意:if可以单独存在,而else不能单独存在,必须配合if使用。
根据以上语法,对例3-2进行优化:输入小明的考试成绩,如果考试大于等于80分,输出“考的不错,给个鸡腿以示奖励”,否则输出“考试结果不理想,今天晚上不准看电视”,如例3-2所示。
例3-2 Demo0302.java
1 package com.aaa.p030201;
2 import java.util.Scanner;
3
4 public class Demo0302 {
5 public static void main(String[] args) {
6 Scanner sca = new Scanner(System.in);
7 System.out.println("------请输入小明的考试成绩-----");
8 double score = sca.nextDouble(); // 定义变量接收小明的录入成绩
9 if (score >= 80){
10 System.out.println("考的不错,给个鸡腿以示奖励!");
11 }else{
12 System.out.println("考试结果不理想,今天晚上不准看电视!");
13 }
14 System.out.println("考好不要骄傲,考坏不要气馁,继续加油!!!");
15 }
16 }
运行程序,输入小明的成绩为90分,运行结果如下:
------请输入小明的考试成绩-----
90
考的不错,给个鸡腿以示奖励!
考好不要骄傲,考坏不要气馁,继续加油!!!
再次运行程序,输入小明的成绩为70分,运行结果如下:
------请输入小明的考试成绩-----
70
考试结果不理想,今天晚上不准看电视!
考好不要骄傲,考坏不要气馁,继续加油!!!
例3-2中,第8行中定义变量来接收小明的考试成绩,第9~13行是一个if-else语句,第9行中的“score >= 80”是判断条件(布尔表达式)。当表达式成立(返回结果为true)的时候,将会执行该if后紧邻的语句块,也就是执行第10行语句;当表达式不成立(返回结果为false)的时候,程序将会跳过if后紧邻的语句块,转而执行else后紧邻的语句块,也就是执行第12行语句。
对比两次运行结果,我们可以看到:第1次输入小明的成绩为90分时,判断条件“score >= 80”成立,即表达式结果返回为true,此时程序执行了第10行的语句,“考的不错,给个鸡腿以示奖励”先被打印出来,而后又执行了第14行语句打印了“考好不要骄傲,考坏不要气馁,继续加油!!!”。第2次输入小明的成绩为70分时,判断条件“score >= 80”不成立,即表达式结果返回为false,此时程序跳过了第10行的语句,转而执行了第12行else后紧邻的语句打印了“考试结果不理想,今天晚上不准看电视!”,最后又执行了第14行语句打印了“考好不要骄傲,考坏不要气馁,继续加油!!!”。
知识点拨:Java中提供了三元运算符(三目运算符),该运算符的符号表示为“?:”,语法为:布尔表达式?语句1:语句2。因为在使用该运算符的时候需要三个操作元,所以被称为三元运算符,该运算符要求返回一个结果。三元运算符的执行逻辑为:首先计算布尔表达式的结果,如果结果为true则执行语句1否则执行语句2。多数情况下三元运算符可以和双分支的if-else语句进行互换,不同之处在于三元运算符要求必须返回一个结果,而if-else语句不一定需要返回值。
例如,String result = 2 < 1 ? "表达式成立": "表达式不成立",其中三元运算符的优先级高于赋值运算符,因此首先进行布尔表达式值2 < 1的判断,如果结果为true则返回“表达式成立”赋值给result变量,否则返回“表达式不成立”赋值给result。
3.else if多重分支语句
if语句可以称之为单分支语句,if-else语句可以称之为双分支语句,而else-if语句则是多重分支语句,用来完成判断条件多于两个的逻辑处理。在else-if语句中,当满足判断条件1时执行语句块1;当不满足判断条件1却满足判断条件2时执行语句块2,…,以此类推进行多重条件判断。else-if语句的语法结构如下:
if (判断条件1){
语句块1;
}else if(判断条件2){
语句块2;
}else if (判断条件3){
语句块3;
}…
else{
语句块n+1;
}
else if语句的执行流程如图3.6所示。else if语句不能独立存在,需配合if语句进行使用。在else if语句中,可以有多个判断条件,首先进行if后的判断条件1的计算,当结果为true时,执行if后紧邻的语句块1,执行完毕后结束语句;当if后的判断条件1的结果为false时,则按照顺序执行else if中的判断条件2,如果结果为true则执行该else if后的语句块2,否则继续执行后续else if的条件判断3,…,以此类推。如果所有的判断条件都不成立,则执行最后else后的语句块n+1。
图3.6 else-if流程图
根据以上语法,对例3-2进行进一步优化:输入小明考试成绩,如果满分输出“奖励学习机一部”,如果考试大于等于80分输出“考的不错,给个鸡腿以示奖励”,如果成绩大于等于60分,输入“刚及格,下次努力”,否则输出“不及格,晚上加班”,如例3-3所示。
例3-3 Demo0303.java
1 package com.aaa.p030201;
2 import java.util.Scanner;
3
4 public class Demo0303 {
5 public static void main(String[] args) {
6 Scanner sca = new Scanner(System.in);
7 System.out.println("------请输入小明的考试成绩-----");
8 int score = sca.nextInt (); // 定义变量接收小明的录入成绩
9 if (score == 100){
10 System.out.println("奖励学习机一部!");
11 }else if( score >= 80){
12 System.out.println("考的不错,给个鸡腿以示奖励!");
13 }else if( score >= 60 ){
14 System.out.println("刚及格,下次努力!");
15 }else{
16 System.out.println("不及格,晚上加班!");
17 }
18 }
19 }
运行程序,输入小明的成绩为100分,运行结果如下:
------请输入小明的考试成绩-----
100
奖励学习机一部!
再次运行程序,输入小明的成绩为90分,运行结果如下:
------请输入小明的考试成绩-----
90
考的不错,给个鸡腿以示奖励!
再次运行程序,输入小明的成绩为70分,运行结果如下:
------请输入小明的考试成绩-----
70
刚及格,下次努力!
再次运行程序,输入小明的成绩为50分,运行结果如下:
------请输入小明的考试成绩-----
50
不及格,晚上加班!
例3-3中,程序的第8行中定义变量来接收小明的考试成绩,第9~16行是一个else-if的多重分支语句。第9行if中的“score == 100”是第1个判断条件,当该条件成立时会执行其后的第9行语句,打印“奖励学习机一部!”;当不成立时,按照顺序计算第2个判断条件(score >= 80)的结果。第11行else if中的“score >= 80”为第2个判断条件,当第1个判断条件不成立时,按照顺序进行该条件的计算,如果该条件成立则会执行其后的第12行语句,打印“考的不错,给个鸡腿以示奖励!”;不成立则继续计算下一个判断条件(score >= 60)的结果。第13行else if中的“score >= 60”为第3个判断条件,当第1个判断条件(score == 100)和第2个判断条件(score >= 80)均不成立时,会计算该条件的结果,如果该条件成立则会执行其后的第14行语句,打印“刚及格,下次努力!”。当第1个判断条件(score == 100)和第2个判断条件(score >= 80)以及第3个判断条件(score >= 60)均不成立时,则执行else后得第16行语句,打印“不及格,晚上加班!”。
通过上边的案例可以看出,输入不同成绩会输出不同的结果,第10、12、14、16语句码会根据是否满足条件而选择其中一行执行。每一个条件都是有隐含的条件,比如第一行的判断条件“score == 100”的隐含条件就是不成立的情况,即score成绩不等于100,因此该写法要注意书写顺序。
注意:else可要可不要;每一个条件的隐含条件即前边的不成立,因此注意书写的顺序。
3.2.2 switch条件语句
switch语句和我们所学的else if语句类似,称为开关语句,是另外一种可以实现多重分支结构的语句。具体语法结构如下:
switch (表达式){
case 值1:
语句块1;
[break;]
case 值2:
语句块2;
[break;]
case 值3:
语句块3;
[break;]
…
case 值n:
语句块n;
[break;]
default:
语句块;
}
switch语句的执行流程如图3.7所示。switch语句中表达式结果的数据类型可以是byte、short、 char、int以及其包装类,也可以是Enum枚举类,JDK7之后也可以是String类型,而else if中表达式的结果是布尔类型。尽管switch语句中表达式的结果扩充了多种数据类型,但是其底层只支持4种基本数据类型,其他的数据类型都是经过了间接的转换。
switch语句在执行时,会首先计算表达式的结果,将计算结果与第1个case后的值1做比对,如果比对结果相等则执行该case后的语句块1,如果比对结果不一样则继续和第2个case后的值2做比对,…,以此类推,如果所有case后的值都不匹配则执行default后的语句块。在此需要注意,case只是提供switch语句匹配成功后的执行入口,case后的语句块并没有“{}”来标注整体,因此程序执行时并不知道何时该语句块执行完毕。如果匹配上某个case后的值,则会从该case分支后的语句块一直执行下去,如果没有break语句,则后续的case分支的语句块也将会执行,直到碰到break语句。
综上所述,switch语句和else if语句的不同之处在于else if的判断条件可以是等值判断也可以是其他复杂的条件判断而switch只能做等值判断,并且语法结构上来看switch语句更简练,表达更清晰。
图3.7 switch语句流程图
接下来通过一个案例演示switch语句的用法:输入当前是周几,如果是一、三、五则输出“今天学习”,如果是二、四、六则输出“今天打球”,如果是周日则输出“看电影去,放松一下”,如果都不是则输出“输入错误”,如例3-4所示。
例3-4 Demo0304.java
1 package com.aaa.p030202;
2 import java.util.Scanner;
3
4 public class Demo0304{
5 public static void main(String[] args) {
6 Scanner sca = new Scanner(System.in);
7 System.out.println("-------请输入今天周几---------");
8 String week = sca.next();
9 switch(week){
10 case "周一" :
11 System.out.println("今天学习");break;
12 case "周二" :
13 System.out.println("今天打球");break;
14 case "周三" :
15 System.out.println("今天学习");break;
16 case "周四" :
17 System.out.println("今天打球");break;
18 case "周五" :
19 System.out.println("今天学习");break;
20 case "周六" :
21 System.out.println("今天打球");break;
22 case "周日" :
23 System.out.println("看电影去,放松一下");break;
24 default :
25 System.out.println("输入错误");
26 }
27 System.out.println("switch执行完毕");
28 }
29 }
运行程序,输入“周三”,运行结果如下:
-------请输入今天周几---------
周三
今天学习
switch执行完毕
再次运行程序,输入“周二”,运行结果如下:
-------请输入今天周几---------
周三
今天打球
switch执行完毕
再次运行程序,输入“星期三”,运行结果如下:
-------请输入今天周几---------
星期三
输入错误
switch执行完毕
例3-4中,第7行是一个提示语句,用来做输入提示使用。第8行声明了一个变量week用来接收录入的值,即周几。第9行switch后的表达式返回的是一个字符串,会和{}中的case进行逐一比对。首先与第10行的第1个case后的值做比对,第1次运行录入的是周三,明显“周一”不等于“周三”,因此第一个case后的代码块不会执行。再比对第12行的case后的值,结果仍然不相等,因此该case后的代码块也不执行。再比对第14行的case后的值,此时等值匹配结果为true,将会从该case后的代码块开始执行,输出“今天学习”,输出后有一个break语句,因此switch语句将运行结束,运行后续代码,即输出“switch执行完毕”。再次运行程序指的是自己重新点击运行重新执行程序,当第3次录入“星期三”时,也将会依次和各个case后的值进行比对,很明显都不匹配,最终执行了default后的代码,即输出“输入错误”。对比3次执行结果,发现输入不同的值会有不同结果,switch会从case中选择一个进行执行,如果都不匹配将执行default子句后的代码。
在以上案例中,我们可以发现多个case语句后的执行语句其实是一样的,即一、三、五输出的都是“今天学习”,二四六输出都是“今天打球”。我们知道switch语句中如果某个case后的值匹配成功,将会从该case后语句块一直执行下去,直到遇到break语句,因此可以根据这一特点对以上案例进行优化,如例3-5所示。
例3-5 Demo0305.java
1 package com.aaa.p030202;
2 import java.util.Scanner;
3
4 public class Demo0305 {
5 public static void main(String[] args) {
6 Scanner sca = new Scanner(System.in);
7 System.out.println("-------请输入今天周几---------");
8 String week = sca.next();
9 switch(week){
10 case "周一" :
11 case "周三" :
12 case "周五" :
13 System.out.println("今天学习");break;
14 case "周二" :
15 case "周四" :
16 case "周六" :
17 System.out.println("今天打球");break;
18 case "周日" :
19 System.out.println("看电影去,放松一下");break;
20 default :
21 System.out.println("输入错误");
22 }
23 System.out.println("switch执行完毕");
24 }
25 }
运行程序,输入“周三”,运行结果如下:
-------请输入今天周几---------
周三
今天学习
switch执行完毕
再次运行程序,输入“星期三”,运行结果如下:
-------请输入今天周几---------
星期三
输入错误
switch执行完毕
对比例3-5和例3-4,可以看出在输入相同值时运行结果是一样的。执行过程也基本一样,输入“周三”,与第2个case后的“周三”相等,将执行“周三”后的代码块,但是该case后没有相应的语句块,并且没有“break”语句,因此继续执行后续代码,即下一个case后的代码。该代码中输出了“今天学习”,还有一个“break语句”,因此在13行执行完毕后退出switch语句,执行第23行代码。第2次输入“星期三”,与所有case后的值都不匹配,将执行default子句后的代码。
在此需要注意,default子句的书写并不一定在所有case的最后,它只要在switch中即可,可以在所有case前,也可以在最后,也可以在穿插在case中间。调整例3-5中default子句的位置,将其放到“周四”之前,代码如下:
1 package com.aaa.p030202;
2 import java.util.Scanner;
3
4 public class Demo0305 {
5 public static void main(String[] args) {
6 Scanner sca = new Scanner(System.in);
7 System.out.println("-------请输入今天周几---------");
8 String week = sca.next();
9 switch(week){
10 case "周一" :
11 case "周三" :
12 case "周五" :
13 System.out.println("今天学习");break;
14 case "周二" :
15 case "周四" :
16 default:
17 System.out.println("输入错误");
18 case "周六" :
19 System.out.println("今天打球");break;
20 case "周日" :
21 System.out.println("看电影去,放松一下");break;
22 }
23 System.out.println("switch执行完毕");
24 }
25 }
运行程序,输入“星期三”,运行结果如下:
-------请输入今天周几---------
星期三
输入错误
今天打球
switch执行完毕
从程序运行结果可发现,当所有case后的值都不匹配的情况下它一样执行了default子句后的代码,但是default后的代码执行完毕之后又执行了switch中后续的代码,即第19行的语句,直到碰到的break语句才结束了switch语句,再次验证了switch中每个分支匹配上后执行该分支后的代码,直到碰到break为止。因此,即使default不在最后,同样需要添加break语句。修改代码如下:
1 package com.aaa.p030202;
2 import java.util.Scanner;
3
4 public class Demo0305 {
5 public static void main(String[] args) {
6 Scanner sca = new Scanner(System.in);
7 System.out.println("-------请输入今天周几---------");
8 String week = sca.next();
9 switch(week){
10 case "周一" :
11 case "周三" :
12 case "周五" :
13 System.out.println("今天学习");break;
14 case "周二" :
15 case "周四" :
16 default:
17 System.out.println("输入错误");break;
18 case "周六" :
19 System.out.println("今天打球");break;
20 case "周日" :
21 System.out.println("看电影去,放松一下");break;
22 }
23 System.out.println("switch执行完毕");
24 }
25 }
运行程序,输入“星期三”,运行结果如下:
-------请输入今天周几---------
星期三
输入错误
switch执行完毕
根据以上案例的讲解,再次书写一个案例来巩固switch的用法:输入年份和月份,输出对应月份的天数。实现思路:如果输入的是1、3、5、7、8、10、12,那么天数是31天;如果输入的是2,判断年份是否是闰年,闰年是29天非闰年是28天;如果输入的是4、6、9、11,那么天数是30天。如例3-6所示。
例3-6 Demo0306.java
1 package com.aaa.p030202;
2 import java.util.Scanner;
3
4 public class Demo0306 {
5 public static void main(String[] args) {
6 Scanner scanner = new Scanner(System.in);
7 System.out.println("------输入年份-----");
8 int year = scanner.nextInt(); // 获取输入的年份
9 System.out.println("输入月份"); // 获取输入的月份
10 int month = scanner.nextInt();
11 int day = 0; // 声明天数变量
12 switch (month){
13 case 1 :
14 case 3 :
15 case 5 :
16 case 7 :
17 case 8 :
18 case 10 :
19 case 12 :
20 day = 31; // 1、3、5、7、8、10、12天数31天
21 break;
22 case 4 :
23 case 6 :
24 case 9 :
25 case 11 :
26 day = 30; // 4、6、9、11天数3天
27 break;
28 case 2 : // 2月判断是否是闰年
29 if ((year%4 == 0&&year%100 != 0)||(year%400 == 0)){
30 day = 29;
31 }else{
32 day = 28;
33 }
34 break;
35 default :
36 System.out.println("输入月份错误");
37 }
38 System.out.println(year + "年" + month + "月,一共是" + day + "天");
39 }
40 }
程序运行结果如下:
------输入年份-----
2021
------输入月份-----
2
2021年2月,一共是28天
例3-6中,第12行,switch中为输入的月份,将会和switch中的case逐一进行比较。第13~19行,case 1、3、5、7、8、10、12共用了一个赋值语句“day = 31”,然后执行break语句退出了switch语句。第22~25行,case 4、6、9、11共用一个赋值语句“day = 30”,然后执行break语句退出switch语句。第28行,如果输入月份为2,则先判断年份是否是闰年,如果是闰年则天数为29天,如果不是天数则为28天。如果所有月份都不匹配,执行default子句。
注意:同一个switch中case中的数值必须每一个都不同。
default(默认)子句为可选语句,并且该语句位置可以不放到最后。
switch语句只能做等值比较,即用switch的表达式结果和各个case子句的值对比,如果相等则执行case后的语句,否则判断下一个。
3.3 循环语句
Java中提供了4种类型的循环语句来实现循环结构,即while语句、do-while语句、for语句以及针对集合遍历的foreach语句。鉴于目前尚未学习数组和集合,本节只讲解前3种的详细用法,foreach语句后续章节再进行讲解。
3.3.1 while循环语句
while循环语句需要先进行循环条件(布尔表达式)判断,即计算该循环条件的值,结果为true时进入循环体(重复执行的语句块),结果为false时退出循环。具体语法结构如下:
while(循环条件){
重复执行语句块……
}
while循环语句的执行流程如图3.8所示。其执行逻辑为:计算循环条件的结果,如果结果为true,执行“重复执行的语句块”即循环体,如果结果为false时退出循环;循环体执行完毕后重新回到循环条件判断。使用while循环时,需要注意以下几点:
• 循环条件结果只能为true或者false。
• 如果循环体只有一条语句则“{}”可以省略。
• 如果开始第一次循环时循环条件计算的值为false,那么循环体将不会执行。
• 一般需要在循环体中更改循环变量(循环条件中的变量)的值,使循环趋于结束,否则如果进入循环,循环条件的结果将始终为true,从而造成死循环。
知识点拨:所谓“死循环”指的是一个无法终止的程序,即该循环会一直执行下去,无法退出。
根据以上语法,编写一个案例:小明罚抄《咏鹅》3遍。实现思路: 循环体为输出咏鹅的4句诗;循环条件是输出3次;根据循环条件可知,循环变量就是次数,初始次数应为0次;循环变量更替应该是每循环一次次数加1。如例3-7所示。
例3-7 Demo0307.java
1 package com.aaa.p030301;
2
3 public class Demo0307 {
4 public static void main(String[] args) {
5 int num = 0; // 抄写次数初始值为0
6 while( num < 3 ) { // 循环条件为抄写次数不足3
7 System.out.print("鹅鹅鹅,");
8 System.out.print("曲项向天歌。");
9 System.out.print("白毛浮绿水,");
10 System.out.println("红掌拨清波。"); // 循环体,输出咏鹅诗句
11 num++; // 循环次数递增
12 System.out.println("完成了" + num + "次");
13 }
14 }
15 }
程序运行结果如下:
鹅鹅鹅,曲项向天歌。白毛浮绿水,红掌拨清波。
完成了1次
鹅鹅鹅,曲项向天歌。白毛浮绿水,红掌拨清波。
完成了2次
鹅鹅鹅,曲项向天歌。白毛浮绿水,红掌拨清波。
完成了3次
例3-7中,第5行是循环变量初始化,该变量是根据循环条件推断出来的。第6行是循环条件,其作用是控制循环何时终止。如果条件返回值为true则进入循环体,即执行第7~12行,如果条件返回值为false则终止循环。第7~12行是重复执行的代码,即循环体,顺序执行。其中第10行“num++”是循环变量更替,如果此处不写该语句,那么num值将一直保持初始值0,循环条件结果将一直为true,就会造成死循环。当第12行执行完毕即循环体执行完毕后,重新执行第6行的条件判断,即重新进行前面的步骤,直到条件判断结果为false,即num等于3时终止循环。
接下来再编写一个案例来巩固循环的使用:计算1+2+3+…+100的结果并输出,如例3-8所示。
例3-8 Demo0308.java
1 package com.aaa.p030301;
2
3 public class Demo0308 {
4 public static void main(String[] args) {
5 int sum = 0; // 初始化和为0
6 int i = 1; // i为当前需要加到和中的数字,从1开始
7 while ( i <= 100 ){ // 计算1-100,如果大于100退出循环
8 sum += i; // sum+i作为计算到当前值的和
9 i++; // 循环变量更替
10 }
11 System.out.println("1+2+3+…+100的结果:" + sum);
12 }
13 }
程序运行结果如下:
1+2+3+…+100的结果:5050
例3-8中,第5行是初始化和为0,如果sum变量不进行声明和初始化,后续无法直接参与sum = sum + i的运算。第6行是循环变量i的初始化,因为1到100之和是从1开始加的,因此初始值为1。第7行是循环条件,如果i<=100返回true说明没有加到100,循环继续,否则循环终止。第8行“sum += i”等价于sum = sum + i,将之前的和加上当前的i的值,重新赋值给sum。第9行“i++”为循环变量更替,计算完毕后重新回到第7行进行条件判断,重复执行。
整体运行过程如下:第一次i = 1,计算累计到1的和为1,赋值给sum,然后执行i++结果为2,循环体执行完毕后进行“i <= 100”判断,结果为true,重新进入循环体计算累计到2的和,赋值给sum后执行i++结果为3,然后重新进行条件判断结果为true,重新进入循环体,以此类推,一直到累计100之和,i更新为101,循环条件的结果为false,退出循环。
3.3.2 do...while循环语句
do-while循环称之为直到型循环。具体语法结构如下:
do{
重复执行语句块。
} while(循环条件); // 注意后边有
do-while循环语句的执行流程如图3.9所示。do-while语句与while语句非常类似,区别在于循环条件判断和循环体执行顺序不同。while循环语句是先判断循环条件,后执行循环体,循环体有可能一次都不执行;而do-while循环语句是先执行循环体,再进行循环条件判断,循环体至少执行一次。
接下来,使用do-while来计算1+2+3+……+100的结果并输出,如例3-9所示。
例3-9 Demo0309.java
1 package com.aaa.p030302;
2
3 public class Demo0309 {
4 public static void main(String[] args) {
5 int sum = 0; // 初始化和为0
6 int i = 1; // i为当前需要加到和中的数字,从1开始
7 do{
8 sum += i;
9 i++;
10 }while ( i <= 100 ); // 注意最后的分号
11 System.out.println("1+2+3+…+100运算结果为:" + sum);
12 }
13 }
程序运行结果如下:
1+2+3+…+100运算结果为:5050
例3-9中,第5行和第6行初始化和例3-8相同。第7行,循环的开始以do打头是固定语法。第8、9行是循环体,第9行完成循环变量的更替。循环体执行完毕执行后,将执行第10行中的循环条件判断,注意后边一个“;”。如果条件判断结果为true重新回到第7行,继续下一次循环,否则退出循环。
从执行过程可以看出do-while循环语句是先执行循环体后进行循环条件判断,循环体至少执行一次。
3.3.3 for循环语句
学过while循环语句和do-while循环语句之后我们来学习for循环语句,for循环语句要更加灵活,是最常用的一种循环语句。Java提供了常规的for循环和基于数组集合的foreach循环,foreach循环是简化增强版for循环,本节讲解常规for循环语句。
for循环语句的语法结构如下:
for (循环变量初始化;循环条件;循环变量更替){
循环体;
}
for后面括号内存在3个表达式语句,执行过程是首先执行循环变量初始化,再执行循环条件,然后执行循环体,最后执行循环变量更替,执行完毕后重新回到循环条件进行判断,然后重复执行循环体、循环变量更替、循环条件,一直到循环条件的判断结果为false退出循环为止,for循环语句的执行流程如图3.10所示。
接下来,使用for循环结构来计算1+2+3+…+100的结果并输出,如例3-10所示
例3-10 Demo00310.java
1 package com.aaa.p030303;
2
3 public class Demo0310 {
4 public static void main(String[] args) {
5 int sum = 0;
6 for(int i = 1 ; i <= 100 ; i++){
7 sum = sum + i;
8 }
9 System.out.println("1+2+3+…+100运算结果为:" + sum);
10 }
11 }
程序运行结果如下:
1+2+3+…+100运算结果为:5050
例3-10中,第5行在进行sum变量的初始化。第6~8行为一个for循环语句,首先执行for后()内的第1个语句int i = 1,进行循环变量初始化。然后执行for后()内的第2个子句i <= 10,进行循环条件判断,如果条件判断结果为true则进入第7行循环体,否则退出循环。第7行为循环体,可以是一句也可以是多句代码组成。循环体执行完毕后进入for后()内的第3个子句i++,完成循环变量更替。第3个子句执行完毕后,重新回到第2个子句进行条件判断,重复执行,一直到循环条件结果为false时退出循环。
从以上执行过程可以看出,标准的for循环执行过程与while基本一致,只是书写更加简洁。
for循环除了标准语法外,还有省略写法,其中for后边()内的3个表达式都可以省略不写。但需要注意的是,循环如果没有循环变量初始化、循环条件、循环变量更替,循环功能将不完整,有可能出现死循环的问题,因此for循环的省略写法仅仅是语法的省略,内容换个形式或换个位置仍然需要书写。
接下来,使用for循环省略写法来计算1~100之和,如例3-11所示。
例3-11 Demo00311.java
1 package com.aaa.p030303;
2
3 public class Demo0311 {
4 public static void main(String[] args) {
5 int sum = 0;
6 int i = 1;
7 for( ; i <= 100 ;){
8 sum = sum + i;
9 i++;
10 }
11 System.out.println("1+2+3+…+100运算结果为:" + sum);
12 }
13 }
程序运行结果如下:
1+2+3+…+100运算结果为:5050
例3-11中,虽然for后边没有写循环变量初始化、循环变量更替,但是在第6行书写了循环变量初始化,在第9行书写了循环变量更替,同样可以达到标准for循环语句的效果。for循环()内只省略了两个表达式,中间的循环条件没有省略。如果省略代表true,将出现死循环。如需省略,则需要配合“break”关键字。
注意:for循环“()”内的3个子句都可以省略,但是“;”不能省略,必须写。如果循环条件不写则代表循环条件为true,此时一般配合“break”关键字使用来终止循环。
3.4 循环嵌套
顾名思义,循环嵌套就是在循环中嵌套一层循环,先执行外层循环,内层循环作为外层循环的循环体。循环嵌套可以是 while循环语句嵌套do-while循环语句,也可以是 for循环语句嵌套 while循环语句,还可以是for循环语句嵌套for循环语句,…….,即各类循环语句都可以作为外层循环,也可以作为内层循环。程序中最常见的是for循环语句嵌套for循环语句。当程序碰到循环嵌套时,先进行外层循环的条件判断,如果成立则开始执行外层循环的循环体,该循环体内包含内层循环,内层循环执行结束且外围循环的循环体也执行完毕时,才可以再次进行外层循环的循环条件判断,决定是否再次进入外层循环的循环体。循环嵌套的执行流程如图3.11 所示。
从图3.11可以看出,循环嵌套就是把内循环作为外层循环的循环体在执行操作。只有内层循环的条件为false时,内层循环才可以结束,外层循环才算完成了一次循环,开始进入下一次循环。
接下来,利用循环嵌套来实现九九乘法表,如例3-12所示。
例3-12 Demo0312.java
1 package com.aaa.p0304;
2
3 public class Demo0312 {
4 public static void main(String[] args) {
5 for (int i = 1; i <= 9; i++) { // 外层循环控制第几行
6 for (int j = 1; j <= i; j++) { // 内循环控制当前行循环几列
7 System.out.print(j + "*" + i + "=" + (i * j) + " ");
8 }
9 System.out.println(); // 一行结束后换行
10 }
11 }
12 }
程序运行结果如下:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
例3-12中,第5~10行是外层循环,使用i来做外层循环的循环变量,初始值为1。外层循环用来控制九九乘法表总共有几行,因此循环条件为i <= 9,即输出9行。第6~8行是内层循环,使用j来做内层循环的循环变量,初始值为1。内层循环用来控制九九乘法表每行应该输出几列。众所周知,九九乘法表第i行的最后就是i*i=乘积,所以内层循环每一次的执行次数就是i的值,因此内层循环的循环条件为j <= i,即内层循环次数随着i的值而变化。第7行是内层循环的循环体,输出i*j的值,注意此处“print”的写法,不带“ln”意为输出不换行,后边的“\t”意为输出制表符。第9行是用来换行的。当内层循环完成一遍循环后,即九九乘法表一行输出完毕,则换行输出下一行,因此换行之后执行外层循环的循环变量更替即“i++”,如果此时i <= 9,则继续输出下一行,否则外层循环结束。
此处是以两层嵌套为例在进行讲解,但实际上,循环嵌套也可以嵌套多层。无论如何嵌套,都可以将内层循环作为外层循环的循环体来看待,只不过这个循环体里包含了重复执行的代码。
3.5 跳转语句
跳转语句可以控制程序的执行方向,在编写循环体比较复杂的情况下经常会被用到。Java语言中提供的跳转语句有break语句、continue语句以及return语句,这3个跳转语句都可以控制程序从一个地方直接跳转到另外一个地方继续执行,使程序更易阅读和理解。
3.5.1 break语句
在分支语句的学习中,大家已经接触过break语句,可以用它来结束switch分支语句的继续执行。除此之外,break还有两种用法,一种是在循环体中强制退出循环,另一种是配合标签使用实现类似C语言goto语句的效果。
1.使用break强制退出循环
在程序中,有时需要强行终止循环,而不是等到循环条件为false时才退出循环。此时,可以使用break语句来实现这种功能。break语句可以出现在循环体中,其作用是使程序立即退出循环,转而执行该循环外的语句。如果break语句出现在嵌套循环中的内层循环,则只会终止当前内层循环,外层循环则不受影响。break语句在3种循环语句中都可以使用,书写在其{}语句块中,一般配合if语句进行使用,执行流程如图3.12所示。
接下来根据break语句的特性,书写一个案例:采用while循环语句来循环输入并打印学生成绩,如果输入成绩为-1则退出循环,如例3-13所示。
例3-13 Demo0313.java
1 package com.aaa.p030501;
2 import java.util.Scanner;
3
4 public class Demo0313 {
5 public static void main(String[] args) {
6 Scanner scanner = new Scanner(System.in);
7 while(true){
8 System.out.println("-------输入学生成绩------");
9 double score = scanner.nextDouble();
10 if(score < 0){
11 break;
12 }
13 System.out.println("学生成绩为:" + score);
14 }
15 System.out.println("循环终止!");
16 }
17 }
程序运行结果如下:
-------输入学生成绩------
90
学生成绩为:90.0
-------输入学生成绩------
-1
循环终止!
例3-13中,第7~14行为一个while循环语句,其中while(true)即循环条件的结果一直都是true,循环将会一直执行,这也就是所谓的死循环。第10行书写了一个if条件语句,当第1次输入成绩为90时,该条件不成立,if中的语句将不会执行,继续执行第13行语句输出该学生的成绩,输出成绩后再次进行循环条件的判断,因为没有循环变量更替,所以该条件的结果恒为true,再次录入学生成绩。第2次输入成绩为-1,第10行中if条件score < 0成立,此时执行了第11行的break语句,循环终止,然后执行了while循环之外的第15行语句。
break语句不仅可以在while循环中使用,也可以在do-while、for循环中使用,方式相同,都是书写在循环体中,碰到break循环终止。此处仅举例了break语句在while循环体中的使用,其他的类似,就不再赘述。
2.break语句配合标签
break语句并不局限于终止一个循环语句或者退出switch分支语句,它还可以配合标签使用,用来终止一个或任意多个代码块,通过它可以实现代码跳转到指定位置继续执行。
标签的命名需要遵循标识符的命名规则,标签名后书写一个冒号,冒号后为标签中要执行的代码块,该代码块中可以使用“break 标签名”来退出该代码块,具体语法如下:
标签名1:{
代码块1中的语句……
if(跳转条件){ // 一般需要配合if使用,否则break语句后不可以书写代码
break 标签名1; // 执行到break语句,将结束该代码块,执行代码块后的代码
}
代码块中1的语句……
}
代码块后续的代码……
接下来,编写一个简单的案例来验证break配合标签使用的语法,如例3-14所示。
例3-14 Demo0314.java
1 package com.aaa.p030501;
2
3 public class Demo0314 {
4 public static void main(String[] args) {
5 labelName:{
6 int i = 1;
7 System.out.println("代码块语句1.....");
8 if(i == 1) { // 此为跳转条件,一般break都配合if使用
9 break labelName;
10 }
11 System.out.println("代码块语句2.....");
12 }
13 System.out.println("代码块后续的代码");
14 }
15 }
程序运行结果如下:
代码块语句1.....
代码块后续的代码
例3-14中,第5行的labelName是标签名,相当于给后边{}中的代码块起了一个名字。第6行声明了一个变量i,初始值为1,作为终止代码块的条件。第8行是一个判断条件,i的初始值为1,因此“1 == 1”这个条件成立,执行if后的break语句,break语句后跟的是刚才的标签名,表示跳出以“labelName”命名的该代码块,此时第11行的语句将不再执行,直接跳转到labelName标签对应的代码块后继续执行,也就是执行13行以后之后的语句。
注意:知识点拨:程序中使用{}将一或者多句代码块括起来即可组成一个代码块,这个代码块并不一定是在分支后或者循环后,可以独立存在。
在此需要注意的是,标签定义的代码块中有可能仍然有标签定义,即代码块是可以进行嵌套的,此时如果break在外层标签的代码块中,那么其后的标签名只能书写外层的标签名,如果break在内层中则可以书写内层标签名也可书写外层的标签名,即break后的标签名只要是包住自己的标签即可。具体语法如下:
标签名1:{
代码块1中的语句……
if(跳转条件){ // 一般需要配合if使用,否则break语句后不可以书写代码
break 标签名1; // 执行到break语句,将结束该代码块,执行代码块后的代码
}
标签名2:{
代码块2中的语句1
if(跳转条件){
break 标签名1/标签名2;
}
代码块2中的语句2
}
代码块中1的语句……
}
代码块后续的代码……
在标签2中包含的break如果跟的是标签名2则终止标签名2的代码块,继续执行后续代码块1中的代码,如果跟的是标签名1则直接退出标签名1的代码,继续执行代码块后续的代码。此处语法仅仅是以两层嵌套进行嵌套,实际可以是很多层,含义与此一样,只要是包住该break语句的标签名都可以使用,即break 配合标签使用,可以用来终止一个或任意多个代码块。利用break配合标签使用,可以用来直接终止多层循环的运行。
接下来,编写一个3层嵌套for循环,循环变量分别为x、y、z,如果x+y+z=10则直接终止所有循环,如例3-15所示。
例3-15 Demo0315.java
1 package com.aaa.p0305;
2
3 public class Demo0315 {
4 public static void main(String[] args) {
5 int x = 1 , y = 1 , z = 1;
6 labelX:for( x = 1 ; x < 100 ; x++ ){
7 lableY:for( y = 1 ; y < 100 ; y++ ){
8 lableZ:for( z = 1 ; z < 100 ; z++ ){
9 if( x + y + z == 10 ){
10 break labelX;
11 }
12 }
13 }
14 }
15 System.out.println("退出循环是x为:" + x);
16 System.out.println("退出循环是y为:" + y);
17 System.out.println("退出循环是z为:" + z);
18 }
19 }
程序运行结果如下:
退出循环是x为:1
退出循环是y为:1
退出循环是z为:8
例3-15中,第6行,labelX是第1层循环起的名字,labelX后正常应该是{}括起来的代码块,但是该代码是一个for循环,是一个整体,除此之外没有其他代码,因此可以省略{}。第7行labelY是第2层循环的名字。第8行labelZ是第3层循环的名字。第9行是一个判断条件,如果x+y+z的结果为10则执行第10行“break labelX”。该代码执行过程,当x=1时进入第1层循环体,第1层的循环体是第2层的循环,此时y=1进入第2层循环的循环体,第2层的循环体是第3层循环,当第3层循环到z=8时,判断条件将成立,此时x=1、y=1、z=8,执行“break labelX”,直接退出labelX的对应的循环,即第1层循环。因此,此时z++、y++、x++那个都不会执行,将直接退出3层循环执行第15行代码。
3.5.2 continue语句
continue语句与break语句类似,都有两种用法,可以在循环体中直接使用,也可以配合标签使用。但两者在使用上的含义不同,continue在循环体中直接使用,用来结束本次循环直接进入下一次循环,配合标签使用则用来实现类似C语言goto语句的效果,实现向前跳转。同时,需要注意continue只能在循环体中。
1.使用continue退出当前循环
continue语句在循环体中直接使用可跳出本次循环体,本次循环体中剩余的语句将不再执行,直接进入下一次循环。换句话说,continue语句可以结束本次循环,跳到循环条件处判断是否进入下一次循环。continue语句可以出现在while循环、do-while循环以及for循环的循环体中,一般配合if语句进行使用,执行流程如图3.13所示。
从图3.13可以看出,程序碰到continue语句之后,之后的语句组2将不再执行,直接回到了循环条件进行判断,根据判断结果来决定进入下一次循环。continue语句类似break语句,两者的区别在于:continue并不是中断整个循环而是终止当前这一次,进入下一次循环,并且continue只能出现在循环体中;break语句出现在循环体中是终止整个循环,也可以出现在switch语句中终止switch判断。
接下来,根据continue的特性,编写一个案例:循环遍历1~10之间的偶数,4不要打印出来,如例3-16所示。
例3-16 Demo0316.java
1 package com.aaa.p030502;
2
3 public class Demo0316 {
4 public static void main(String[] args) {
5 System.out.println("-------循环遍历1~10之间的偶数,4不要打印出来------");
6 for(int i = 1 ; i <= 10 ; i++){
7 if(i % 2 != 0){
8 continue;
9 }
10 if(i == 4){
11 continue;
12 }
13 System.out.print(i + "\t");
14 }
15 }
16 }
程序运行结果如下:
-------循环遍历1~10之间的偶数,4不要打印出来------
2 6 8 10
例3-16中, 第7行是一个判断条件,如果i不是偶数,将执行continue,即终止本次循环,继续下一次循环,意味着在i不是偶数的情况下,第10~13行将不执行,直接执行i++,然后进行i <= 10判断,如果条件成立则进入下一次循环,否则退出循环。第10行同样是一个判断条件,如果i的值为4,则执行continue,即13行不执行直接执行i++,然后进行循环条件判断,如果成立进入下一次循环,否则退出循环。如果i是偶数,并且i不等于4,将执行第13行,即将其输出。
continue语句不仅可以在for循环中使用,也可以在do-while、while循环中使用,方式相同,都是书写在循环体中,碰到continue语句将终止本次循环,进入下一次循环。此处仅举例了continue语句在for循环体中的使用,其他的类似,不再赘述。
2.continue语句配合标签
continue语句可以配合标签使用,该标签必须是为循环指定的名字,不能是普通代码块。当程序执行到continue语句后,程序会回到标记的所在位置继续指定循环的下一次循环。
与break类似,continue所处的循环也可以是嵌套的,continue后所书写的标签名可以是当前循环的标签名,也可以是外层循环的标签名。continue语句可以出现在while、do-while以及for循环中用来控制语句的跳转,在此以for循环为例进行语法的说明,具体语法如下:
标签名1:for(;;){
循环1中的语句……
标签名2:for(;;){
循环2中的语句……
if(跳转条件){
continue 标签名1/标签名2;
}
循环2中中的语句2
}
循环1中语句……
}
代码块后续的代码……
在此,continue如果跟的是标签名2则跳转到标签2对应的循环,即中止循环2的当前循环进入下一次循环,与直接使用continue结果一样;如果跟的是标签1,则跳转到标签1对应的循环,直接结束外层循环的当前循环(循环1中嵌套的循环将直接终止),进入外层循环的下一次循环。此处语法仅仅是以两层嵌套进行嵌套,实际可以是很多层,含义与此一样。
接下来,利用continue配合标签使用实现九九乘法表,如例3-17所示。
例3-17 Demo0317.java
1 package com.aaa.p0305;
2
3 public class Demo0317 {
4 public static void main(String[] args) {
5 System.out.println("-------九九乘法表------");
6 a:for(int i = 1 ; i <= 9 ; i++){
7 b:for(int j = 1;j <= 10;j++){
8 System.out.print( j + "*" + i + "=" + i * j + "\t");
9 if(i == j){
10 System.out.println();
11 continue a;
12 }
13 }
14 }
15 }
16 }
程序运行结果如下:
-------九九乘法表------
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
例3-17中,第6行的a是给外层循环起的名字。第7行的b是给内层循环起的名字。该九九乘法表与之前例3-12有所不同,内层循环不是j <= i而是j <= 10,即从内层循环来看它应该循环10次。第9行是一个判断,如果j和i的值相等,则执行第10行换行和第11行“continue a”。第11行意为继续a命名的循环,即外层循环,执行这句话将结束内层循环,直接进行外层循环的i++,然后进行外层循环的判断,如果条件成立进入外层循环的下一次循环。
从结果很明显可以看出,内层循环并没有执行10次,而是到达i == j的时候就终止了,进入了外层循环的下一次循环。
3.5.3 return语句
return语句可以用来结束循环,但它实际的含义其实是结束一个方法。程序运行碰到return语句时,对应方法将直接终止,而不仅仅是退出循环。并且,return后也可以跟变量、值等作为方法返回值来使用(这个知识点在方法定义中详细讲解)。
接下来,演示return语句的使用,如例3-18所示。
例3-18 Demo0318.java
1 package com.aaa.p0305;
2
3 public class Demo0318 {
4 public static void main(String[] args) {
5 System.out.println("-------循环遍历1~10,碰到4结束------");
6 for(int i = 1 ; i <= 10 ; i++){
7 System.out.println(i + "\t");
8 if(i == 4){
9 return;
10 }
11 }
12 System.out.println("循环外的代码");
13 }
14 }
程序运行结果如下:
-------循环遍历1~10,碰到4结束------
1
2
3
4
例3-18中,第8行是一个判断,如果i == 4,那么将执行return语句。结果中明显可以看出,第12行没有执行,验证了return语句并不是简单的终止循环,而是直接终止了方法。
3.6 本章小结
• 控制结构分为顺序结构、选择结构和循环结构。
• Java中,选择结构由if语句和switch语句来实现。选择结构将程序分为不同的部分,通过一定的条件可以控制程序有不同的走向。
• if语句又分为if单分支语句、if-else双分支语句以及else if多重分支语句。
• switch语句称之为开关语句,也是一种多重分支语句。其中,else if语句和switch语句各有优缺点:else if语句的判断条件为一个布尔表达式,可以是大于、小于、与、或、非等运算结果,比较灵活,但是else if语句需要遍历所有的分支,直到找到条件成立的分支为止,在分支较少的时候,else if语句是更好的选择;switch语句仅适用于等值判断,每个case后都只能是一个常量表达式,但是switch语句比较清晰,并且在分支较多的时候,switch语句的效率相对更高一点。
• Java中循环语句有4种:while语句、do-while语句、for循环语句以及for循环的简化版foreach语句,这些语句都实现了让某段程序重复执行,直到退出循环的条件成立时才会结束。其中while、for循环语句都是先判断后执行循环体,而do-while语句是先执行后判断,循环体至少执行一遍。对于foreach本章没有具体讲解,在集合中会具体介绍。
• while语句、do-while语句、for循环语句以及foreach语句都可以进行相互的嵌套,内层循环可以被视为外层循环的循环体。
• Java中的跳转语句有break语句、continue语句和return语句。其中,break语句可以用来终止当前循环体,或者终止switch语句,也可以配合标签使用,实现终止指定标签的代码块;continue语句用来实现在循环中跳过本次循环(continue语句后未执行完的循环体将不再执行),重新进行条件判断,进入下一次的循环,也可以配合标签使用,实现跳出指定的循环体,进入该循环的下一次循环;return关键字用来终止方法,如果循环中使用则循环终止并且方法也终止。
• 在循环嵌套中,break语句用于跳出当前循环,如果当前循环存在外层循环,则外层循环不受影响,还将会继续执行。但是可以配合标签使用来退出指定的循环。如果使用return语句将会终止当前的方法,也就意味着无论内层循环还是外层循环都将会终止。
3.7 理论测试与实践练习
1.填空题
1.1 程序结构分为: 、 、 。
1.2 处理多重分支的语句有: 、 。
1.3 Java中跳转语句有: 、 、 。
1.4 Java中while循环有可能执行 次,do-while循环有可能执行 次,最少执行 次。
2.选择题
2.1语句while(!e);中的条件 !e 等价于( )
A.e == 0 B.e != 1 C.e != 0 D.~e
2.2 while循环,条件为( )执行循环体
A.False B.True C.0 D.假或真
2.3下边那个数据类型不能用于switch语句的参数( )
A.byte B.boolean C.char D.String
2.4 下边语句说法正常的是:( )
1 String s="a";
2 switch (s){
3 default :
4 System.out.print("default-");
5 case "A":
6 System.out.print("A-");
7 case "b":
8 System.out.print("b-");break;
9 case "c":
10 System.out.print("c-");break;
11 }
A.编译错误,无法运行 B.正常运行,结果为“A-”
C.正常运行,结果为“default-” D.正常运行,结果为“default-A-b”
2.5 下列语句序列执行后,i的值是:( )
1 int i = 10;
2 do { i/=2; } while( i-- > 1 );
A.1 B.5 C.2 D.-1
2.6 下列语句序列执行后,输出结果是:( )
1 for(int i = 0 ; i <= 4 ; i++){
2 if( i%2 == 0 ){
3 continue;
4 }
5 System.out.print(i);
6 }
A.01234 B.0134 C.013 D.13
3.思考题
3.1 请简述break和continue语句的区别?
3.2 请简述while和do-while的区别
3.3 请简述else if和switch处理多重分支的区别
4.编程题
4.1 编写程序,输入一个员工的工资,如果工资大于6000输出“交税”否则输出“不交税”。
4.2 输入一个人的年龄,检查这个人是不是00后,如果是输出“是”否则输出“不是”。
4.3 声明三个变量x、y、z接收录入的数字,将他们由大到小输出
4.4 输入数字1-7,输出周一到周日的对应的中文显示
4.5 编写程序,求1~100之间的偶数之和。
4.6 使用while循环求1到5的平方和。
4.7 编写程序,输入两个数字,计算两个数字的最大公约数和最小公倍数。
4.8 编写程序,输入一个数字,输出这个数字是不是质数。
4.9编写程序,输出以下内容:
*
***
*****
*******
*********
- 点赞
- 收藏
- 关注作者
评论(0)