概述
流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组 合成能完成一定功能的小逻辑模块。 其流程控制方式采用结构化程序设计中规定的三种基本流程结构,即:
在正式学习流程控制之前,我们先来了解一下Scanner类吧。如何从键盘获取不同类型的变量:需要使用Scanner类
/*
具体实现步骤:
1.导包:import java.util.Scanner;
2.Scanner的实例化:Scanner scan = new Scanner(System.in);
3.调用Scanner类的相关方法(next() / nextXxx()),来获取指定类型的变量
注意:
需要根据相应的方法,来输入指定类型的值。如果输入的数据类型与要求的类型不匹配时,会报异常:InputMisMatchException
导致程序终止。
*/
//1.导包:import java.util.Scanner;
import java.util.Scanner;
class ScannerTest{
public static void main(String[] args){
//2.Scanner的实例化
Scanner scan = new Scanner(System.in);
//3.调用Scanner类的相关方法
System.out.println("请输入你的姓名:");
String name = scan.next();
System.out.println(name);
System.out.println("请输入你的芳龄:");
int age = scan.nextInt();
System.out.println(age);
System.out.println("请输入你的体重:");
double weight = scan.nextDouble();
System.out.println(weight);
System.out.println("你是否相中我了呢?(true/false)");
boolean isLove = scan.nextBoolean();
System.out.println(isLove);
//对于char型的获取,Scanner没有提供相关的方法。只能获取一个字符串
System.out.println("请输入你的性别:(男/女)");
String gender = scan.next();//"男"
char genderChar = gender.charAt(0);//获取索引为0位置上的字符
System.out.println(genderChar);
}
}
如果你在键盘输入过程中,遇到java.util.InputMismatchException,说明你输入的数据类型与接收数据的变量的类型不匹配。Scanner类中的next()方法遇到空格等空白符,就认为输入结束。nextLine()方法:遇到回车换行,就认为输入结束.。随机数公式也是我们做案例必须先掌握的。
/*
随机数公式:(int)(Math.random()*(n-m+1)+m); 返回一个[m,n]之间的随机数
n:较大的数
m:较小的数
*/
//生成一个44 到 55 之间的随机数。包括44 和 55
int num = (int)(Math.random()*(55-44+1)+44);
顺序结构
顺序结构是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行, 程序中大多数的代码都是这样执行的。
// 顺序结构
public class Demo01Sequence {
public static void main(String[] args) {
//程序从上到下逐行地执行,中间没有任何判断和跳转。
System.out.println("今天天气不错");
System.out.println("挺风和日丽的");
System.out.println("我们下午没课");
System.out.println("这的确挺爽的");
}
}
顺序结构执行流程图:
根据条件,选择性地执行某段代码。 有if…else和switch-case两种分支语句。
if语句第一种格式
执行流程:
- 首先判断条件表达式看其结果是true还是false
- 如果是true就执行语句体
- 如果是false就不执行语句体
- if分支执行完毕后,会继续执行后面的语句内容
执行流程图:
// 单if语句
public class Demo02If {
public static void main(String[] args) {
System.out.println("今天天气不错,正在压马路……突然发现一个快乐的地方:网吧");
int age = 19;
//首先计算关系表达式的age >= 18值
if (age >= 18) {
//如果关系表达式的值为true就执行语句体
System.out.println("进入网吧,开始high!");
System.out.println("遇到了一群猪队友,开始骂街。");
System.out.println("感觉不爽,结账走人。");
}
//继续执行后面的语句内容
System.out.println("回家吃饭");
}
}
if语句第二种格式: if…else
在某些简单的应用中,if语句是可以和三元运算符互换使用的。
执行流程:
- 首先计算关系表达式的值
- 如果关系表达式的值为true就执行语句体1
- 如果关系表达式的值为false就执行语句体2
- 继续执行后面的语句内容
执行流程图:
代码示例
// 标准的if-else语句
public class Demo03IfElse {
public static void main(String[] args) {
int num = 666;
// 首先计算关系表达式的值,如果除以2能够余数为0则为true否则为false,
if (num % 2 == 0) {
// 如果关系表达式的值为true就执行语句体1
System.out.println("偶数"); //偶数
} else {
// 如果关系表达式的值为false就执行语句体2
System.out.println("奇数");
}
}
}
if语句第三种格式: if…else if …else
执行流程:
- 首先判断关系表达式1看其结果是true还是false
- 如果是true就执行语句体1,然后结束当前多分支
- 如果是false就继续判断关系表达式2看其结果是true还是false
- 如果是true就执行语句体2,然后结束当前多分支
- 如果是false就继续判断关系表达式…看其结果是true还是false
- …
- 如果没有任何关系表达式为true,就执行语句体n+1,然后结束当前多分支。
执行流程图
/*
岳小鹏参加Java考试,他和父亲岳不群达成承诺:
如果:
成绩为100分时,奖励一辆BMW;
成绩为(80,99]时,奖励一台iphone xs max;
当成绩为[60,80]时,奖励一个 iPad;
其它时,什么奖励也没有。
请从键盘输入岳小鹏的期末成绩,并加以判断
*/
import java.util.Scanner;
class IfTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入岳小鹏期末成绩:(0-100)");
int score = scan.nextInt();
if(score == 100){
System.out.println("奖励一辆BMW");
}else if(score > 80 && score <= 99){
System.out.println("奖励一台iphone xs max");
}else if(score >= 60 && score <= 80){
System.out.println("奖励一个 iPad");
}else{
System.out.println("什么奖励也没有");
}
}
}
if分支语句注意事项:
- 条件表达式必须是布尔表达式(关系表达式或逻辑表达式)、布尔变量.
- if语句的小括后面, 不要写分号
- 语句块只有一条执行语句时,一对{ }可以省略,但建议保留。
- 当if-else结构是“多选一”时,最后的else是可选的,根据需要可以省略
- 当多个条件是“互斥”关系时,条件判断语句及执行语句间顺序无所谓
- 当多个条件是“包含”关系时,“小上大下 / 子上父下
- else 语句不能单独使用 必须依附于某个if
所有的控制语句都是可以进行嵌套使用的
/*
编写程序:由键盘输入三个整数分别存入变量num1、num2、num3,
对它们进行排序(使用 if-else if-else),并且从小到大输出。
*/
import java.util.Scanner;
class IfTest2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入第一个整数:");
int num1 = scanner.nextInt();
System.out.println("请输入第二个整数:");
int num2 = scanner.nextInt();
System.out.println("请输入第三个整数:");
int num3 = scanner.nextInt();
if(num1 >= num2){
if(num3 >= num1)
System.out.println(num2 + "," + num1 + "," + num3);
else if(num3 <= num2)
System.out.println(num3 + "," + num2 + "," + num1);
else
System.out.println(num2 + "," + num3 + "," + num1);
}else{
if(num3 >= num2)
System.out.println(num1 + "," + num2 + "," + num3);
else if(num3 <= num1)
System.out.println(num3 + "," + num1 + "," + num2);
else
System.out.println(num1 + "," + num3 + "," + num2);
}
}
}
什么是if..else嵌套?
- 在if的语句块中,或者是在else语句块中, 又包含了另外一个条件判断(可以是单分支、双分支、多分支)
执行的特点:
- 如果是嵌套在if语句块中的 只有当外部的if条件满足,才会去判断内部的条件
- 如果是嵌套在else语句块中的 只有当外部的if条件不满足,进入else后,才会去判断内部的条件
分支结构之switch语句
switch 语句和 if 语句一样,都属于选择语句(分支语句),不再赘述,我们直接来看一下 一个比较完整的 switch 语句结构是怎样的,请看下图:
执行流程:
- 首先计算表达式的值。
- 当switch(表达式)的值与case后面的某个常量值匹配,就从这个case进入;
- 当switch(表达式)的值与case后面的所有常量值都不匹配,寻找default分支进入;不管default在哪里
- 一旦从“入口”进入switch,就会顺序往下执行,直到遇到“出口”,即可能发生贯穿
- 自然出口:遇到了switch的结束丶中断出口:遇到了break等
执行流程图
代码示例
public class Demo {
public static void main(String[] args) {
String season = "summer";
switch (season) {
case "spring":
System.out.println("春暖花开");
break;
case "summer":
System.out.println("夏日炎炎");//夏日炎炎
break;
case "autumn":
System.out.println("秋高气爽");
break;
case "winter":
System.out.println("冬雪皑皑");
break;
default:
System.out.println("季节输入有误");
break;
}
}
}
注意事项:
- 在switch语句中,如果case控制的语句体后面不写break,将出现穿透现象,在不判断下一个case值的情况下,向下运行,直到遇到break,或者整体switch语句结束
- break,可以使用在switch-case结构中,表示一旦执行到此关键字,就跳出switch-case结构
- switch结构中的表达式,只能是如下的6种数据类型之一: byte 、short、char、int、枚举类型(JDK5.0新增)、String类型(JDK7.0新增)
- case 之后只能声明常量。不能声明范围。且值不能重复
- break关键字是可选的。
- default:相当于if-else结构中的else. default结构是可选的,而且位置是灵活的。
在有些情况,我们可以使用case穿透来实现我们的代码,例如:
/*
从键盘分别输入年、月、日,判断这一天是当年的第几天
注:判断一年是否是闰年的标准:
1)可以被4整除,但不可被100整除
或
2)可以被400整除
说明:
1. 凡是可以使用switch-case的结构,都可以转换为if-else。反之,不成立。
2. 我们写分支结构时,当发现既可以使用switch-case,(同时,switch中表达式的取值情况不太多),
又可以使用if-else时,我们优先选择使用switch-case。原因:switch-case执行效率稍高。
*/
import java.util.Scanner;
class SwitchCaseExer {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入year:");
int year = scan.nextInt();
System.out.println("请输入month:");
int month = scan.nextInt();
System.out.println("请输入day:");
int day = scan.nextInt();
//定义一个变量来保存总天数
int sumDays = 0;
switch(month){
case 12:
sumDays += 30;
case 11:
sumDays += 31;
case 10:
sumDays += 30;
case 9:
sumDays += 31;
case 8:
sumDays += 31;
case 7:
sumDays += 30;
case 6:
sumDays += 31;
case 5:
sumDays += 30;
case 4:
sumDays += 31;
case 3:
//sumDays += 28;
//判断year是否是闰年
if((year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0){
sumDays += 29;
}else{
sumDays += 28;
}
case 2:
sumDays += 31;
case 1:
sumDays += day;
}
System.out.println(year + "年" + month + "月" + day + "日是当年的第" + sumDays + "天");
}
}
循环语句
在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语 句。一组被重复执行的语句称之为循环体,能否继续重复,取决于循环的终止条件。循环结构 是在一定条件下反复执行某段程序的流程结构,被反复执行的程序被称为循环体。java 中的循环语句共包括三个,分别是:for 循环、 while 循环、do..while 循环。循环语句的四个组成部分
循环结构的组成:
- 初始化语句: 用于表示循环开启时的起始状态,简单说就是循环开始的时候什么样
- 条件判断语句:用于表示循环反复执行的条件,简单说就是判断循环是否能一直执行下去
- 循环体语句: 用于表示循环反复执行的内容,简单说就是循环反复执行的事情
- 条件控制语句:用于表示循环执行中每次变化的内容,简单说就是控制循环是否能执行下去,最后执行的语句。
循环结构对应的语法:
- 初始化语句: 这里可以是一条或者多条语句,这些语句可以完成一些初始化操作。可以声明多个变量,但必须是同一个类型,用逗号分隔
- 条件判断语句:这里使用一个结果值为boolean类型的表达式,这个表达式能决定是否执行循环体。例如:a<3
- 循环体语句: 这里可以是任意语句,这些语句将反复执行
- 条件控制语句:这里通常是使用一条语句来改变变量的值,从而达到控制循环是否继续向下执行的效果。常见i++,i–这样的操作。可以有多个变量更新,用逗号分隔
循环结构之for循环
for循环语句格式:
如果循环条件语句②省略的话,就默认为循环条件成立
执行流程:
- 第一步:执行初始化语句①,完成循环变量的初始化;
-
第二步:执行循环条件语句②,看循环条件语句的值是true,还是false;
- 如果是true,执行第三步;
- 如果是false,循环语句中止,循环不再执行。
- 第三步:执行循环体语句③
- 第四步:执行迭代语句④,针对循环变量重新赋值
- 第五步:根据循环变量的新值,重新从第二步开始再执行一遍
执行流程图:
/*
循环结构的4个要素
① 初始化条件
② 循环条件 --->是boolean类型
③ 循环体
④ 迭代条件
二、for循环的结构
for(①;②;④){
③
}
执行过程:① - ② - ③ - ④ - ② - ③ - ④ - ... - ②
*/
//例题:遍历100以内的偶数,输出所有偶数的和,输出偶数的个数
class ForTest {
public static void main(String[] args) {
//记录所有偶数的和
int sum = 0;
//记录偶数的个数
int count = 0;
for (int i = 1; i <= 100; i++) {
// 判断是不是偶数
if (i % 2 == 0) {
//输出所有的偶数
System.out.println(i);
//求和
sum += i;
//求个数和
count++;
}
}
System.out.println("总和为:" + sum);
System.out.println("个数为:" + count);
}
}
注意:
- 环中, 控制循环的变量, 可以作为逻辑组织到循环体中进行使用的.
- 循环的 条件控制语句, 不要局限的认为只能是++,可以是任何合法的表达式
循环结构之while循环
while循环语句标准格式:
执行流程:
- 第一步:执行循环条件语句①,看循环条件语句的值是true,还是false;
-
第二步:执行循环体语句②;
- 如果是true,执行第二步;
- 如果是false,循环语句中止,循环不再执行。
- 第三步:循环体语句执行完后,重新从第一步开始再执行一遍
while循环语句扩展格式:
执行流程:
- 第一步:执行初始化语句①,完成循环变量的初始化;
-
第二步:执行循环条件语句②,看循环条件语句的值是true,还是false;
- 如果是true,执行第三步;
- 如果是false,循环语句中止,循环不再执行。
- 第三步:执行循环体语句③
- 第四步:执行迭代语句④,针对循环变量重新赋值
- 第五步:根据循环变量的新值,重新从第二步开始再执行一遍
需求:输出 1~100内偶数和
public class Demo10While {
public static void main(String[] args) {
int sum = 0;
//1.起始点 初始化条件 ①
int i = 1;
while (i <= 100) {//循环条件②
//循环体③
if (i % 2 == 0) {
sum += i;
}
//迭代条件④
i++;
}
System.out.println("1-100偶数和:" + sum);
}
}
执行流程图:
/*
珠穆朗玛峰
需求:
世界最高山峰是珠穆朗玛峰(8844.43米=8844430毫米),假如我有一张足够大的纸,它的厚度是0.1毫米。
请问,我折叠多少次,可以折成珠穆朗玛峰的高度?
*/
public class WhileTest {
public static void main(String[] args) {
//定义一个计数器,初始值为0
int count = 0;
//定义纸张厚度
double paper = 0.1;
//定义珠穆朗玛峰的高度
int zf = 8844430;
//因为要反复折叠,所以要使用循环,但是不知道折叠多少次,这种情况下更适合使用while循环
//折叠的过程中当纸张厚度大于珠峰就停止了,因此继续执行的要求是纸张厚度小于珠峰高度
while(paper <= zf) {
//循环的执行过程中每次纸张折叠,纸张的厚度要加倍
paper *= 2;
//在循环中执行累加,对应折叠了多少次
count++;
}
//打印计数器的值
System.out.println("需要折叠:" + count + "次");
}
}
循环结构之do-while循环
do…while循环语句标准格式
执行流程:
- 第一步:执行循环体语句①;
-
第二步:执行循环条件语句②,看循环条件语句的值是true,还是false;
- 如果是true,执行第三步;
- 如果是false,循环语句终止,循环不再执行。
- 第三步:循环条件语句执行完后,重新从第一步开始再执行一遍
do…while循环语句扩展格式
执行流程:
- 第一步:执行初始化语句①,完成循环变量的初始化;
- 第二步:执行循环体语句②;
- 第三步:执行迭代语句③,针对循环变量重新赋值;
-
第四步:执行循环条件语句④,看循环条件语句的值是true,还是false;
- 如果是true,根据循环变量的新值,重新从第二步开始再执行一遍;
- 如果是false,循环语句中止,循环不再执行。
执行流程图
import java.util.Scanner;
public class Demo13DoWhile {
public static void main(String[] args){
//随机生成一个100以内的整数
int num = (int)(Math.random()* 100);
//声明一个变量,用来存储猜的次数
int count = 0;
Scanner input = new Scanner(System.in);
int guess;//提升作用域
do{
System.out.print("请输入100以内的整数:");
guess = input.nextInt();
//输入一次,就表示猜了一次
count++;
if(guess > num){
System.out.println("大了");
}else if(guess < num){
System.out.println("小了");
}
}while(num != guess);
System.out.println("一共猜了:" + count+"次");
}
}
注意:
- 如果记录的是总的变化(循环结束之后才有结果)则在循环的外面定义变量。
- 如果记录的是单个个体的变化 则定义在循环的内部
循环语句的区别
-
从循环次数角度分析
- do…while循环至少执行一次循环体语句
- for和while循环先循环条件语句是否成立,然后决定是否执行循环体,至少执行零次循环体语句
-
从循环变量的生命周期角度分析
- for循环的循环变量在for()中声明的,在循环语句结束后,不可以被访问;
- while和do…while循环的循环变量因为在外面声明的,所以while和do…while结束后可以被继续使用的;
-
如何选择
- 遍历有明显的循环次数(范围)的需求,选择for循环
- 遍历没有明显的循环次数(范围)的需求,循环while循环
- 如果循环体语句块至少执行一次,可以考虑使用do…while循环
本质上:三种循环之间是可以互相转换的,都能实现循环的功能
死循环
最简单“无限” 循环格式:while(true) , for(;;),无限循环存在的原因是并不知道循环多少次,需要根据循环体内部某些条件,来控制循环的结束。
- for(;;) { }
- while(true) { }
- do{ }while(true);
嵌套循环
- 将一个循环放在另一个循环体内,就形成了嵌套循环。其中, for ,while ,do…while均可以作为外层循环或内层循环。
- 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的 循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开 始下一次的循环。
- 设外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n次。当然可以是三种循环任意互相嵌套。
格式:
嵌套循环执行流程:
- 执行顺序:①②③④⑤⑥>④⑤⑥>⑦②③④⑤⑥>④⑤⑥
- 外循环一次,内循环多次。
- 比如跳绳:一共跳5组,每组跳10个。5组就是外循环,10个就是内循环。
public class LoopHourAndMinute {
public static void main(String[] args) {
// 外层控制小时
for (int hour = 0; hour < 24; hour++) {
// 内层控制小时之内的分钟
for (int minute = 0; minute < 60; minute++) {
System.out.println(hour + "点" + minute + "分");
}
}
}
}
break关键字
- break语句用于终止某个语句块的执行,关键字后面不能声明执行语句
- 使用 break 这一个单词就可以在 java 语言中自成一条 java 语句
- break语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是 哪一层语句块。
- 只能出现在switch或者循环中,离开使用场景的存在是没有意义的 。
-
使用在 switch 语句当中,用来终止 switch 语句的执行,使用在循环语句当中,用来终止/跳出循环。
/*
键盘录入n个整数
统计 一共有多少个正数
多少个负数
*/
class BreakTest2{
public static void main(String [] args){
// 键盘录入n个整数 统计 一共有多少个正数 多少个负数
//创建Scanner对象
java.util.Scanner in = new java.util.Scanner(System.in);
//定义变量 记录正数的个数
int zhengShu = 0;
//定义变量 记录负数的个数
int fuShu = 0;
//有一个循环
while(true){
//不断地接收键盘录入的数
System.out.println("请您输入一个数");
int num = in.nextInt();
//对输入的数进行校验 判断是正数 还是负数
if(num > 0){
//是正数 正数个数+1
zhengShu++;
}else if(num <0){
//是负数 负数个数+1
fuShu++;
}else {
//当输入0的时候 终止循环
break;
}
}
//输出结果
System.out.println("正数个数有:"+zhengShu+"\n负数个数有:"+fuShu);
}
}
break 语句默认情况下只能终止离它“最近”的“一层”循环。我们可以通过标记来终止指定的循环
public class Demo {
public static void main(String[] args) {
first:for (int j = 1; j <= 2; j++) {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break first;
}
System.out.println("i = " + i);
}
}
}
}
执行结果:
- continue 语句也是单个单词自成一条 java 语句,例如“continue;”,它和 break 语句都是用 来控制循环的,break 语句是用来终止循环的执行。
- continue 语句则是用来终止当前本次循环,直接进入下一次循环继续执行
- continue 语句后面的代码不在执行,直接更新步进表达式,判断循环条件。
- continue只能使用在循环结构中
- continue语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环
/*
另一种循环控制语句是continue关键字。
一旦执行,立刻跳过当前次循环剩余内容,马上开始下一次循环。
*/
public class Demo15Continue {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i == 4) { // 如果当前是第4层
continue; // 那么跳过当前次循环,马上开始下一次(第5层)
}
System.out.println(i + "层到了。");
}
}
}
总结一下:
- break只能用于switch语句和循环语句中。
- continue 只能用于循环语句中。
- 二者功能类似,但continue是终止本次循环,break是终止本层循环。
- break、continue之后不能有其他的语句,因为程序永远不会执行其后的语句。
- 标号语句必须紧接在循环的头部。标号语句不能用在非循环语句的前面。
- 很多语言都有goto语句,goto语句可以随意将控制转移到程序中的任意一条 语句上,然后执行它。但使程序容易出错。Java中的break和continue是不同 于goto的。