Java 程序设计基础之流程控制
关于 Java 程序设计语言的 基础语法 部分,前面我们已经详细了解过了 Java 中的字面值,变(常)量,数据类型以及操作符,这里我们来看 Java 基础语法的另一个重要组成部分——Java 中的流程控制语句,它决定程序要进入什么流程,即“做什么”以及“怎么做等。
流程控制结构
从结构化程序设计角度出发,编程语言一般会有 3 种结构:
- 顺序结构
- 分支结构
- 循环结构
若是在程序中没有给出特别的执行流程控制,系统则默认自上而下一行一行地执行该程序,这类程序的结构就称为顺序结构。
但事实上,现实事物的发展往往不会遵循早就设想好的轨迹进行,此时需要引入:分支结构,循环结构。
分支结构
Java 支持两种选择语句:
- if 语句:使用 布尔表达式或布尔值 作为分支条件,来进行程序执行分支控制
- switch 语句:用于对多个 整型值、字符串值 进行匹配,从而实现程序执行分支控制。
下面会分别对上述的两种选择(分支)语句进行解读:
if 语句
1 –> if 结构
if 语句的最简语法格式如下,表示:“如果条件表达式为 true,就执行语句块”。
1 | if (条件表达式) { |
if 条件语句的运行流程如下:
实例:
1 | public class HelloWorld { |
–> 多表达式与一个表达式
1 | public class HelloWorld { |
2 –> if-else 结构
if-else 结构语法格式如下,表示:“如果条件(表达式)正确则执行 –> 语句块1,否则执行 –> 语句块2”。
1 | if (表达式) { |
if-else 结构的运行流程如下:
实例:
1 | public class HelloWorld { |
3 –> 多条件 if-else-if 结构
if-else-if 结构是多条件判断,语法格式如下:
1 | if(表达式1) { |
表现为:依次判断表达式的值,当某个分支的条件表达式的值为 true 时,则执行该分支对应的语句块,然后跳到整个 if 语句之外继续执行程序。如果所有的表达式均为 false,则执行语句块 n+1,然后继续执行后续程序。
if-else-if 结构的运行流程如下:
实例:
1 | public class HelloWorld { |
4 –> if 嵌套结构
if 条件结构里嵌套另一个 if 结构。同样,if…else 结构语句和 if…else if 结构语句中也可以嵌套另一个 if 结构的语句,以完成更深层次的判断(一般不要超过 3 层)。
嵌套 if 的语法格式如下:
1 | if(表达式1) { |
switch 语句
switch 语句是 Java 中的多路分支语句,提供了一种基于一个表达式的值来使程序执行不同部分的简单方法。
switch 提供了一个比一系列 if-else-if 语句更好的选择。
switch 语句的基本语法形式如下所示:
1 | switch(表达式) { |
switch 语句的执行过程如下:表达式的值与每个 case 语句中的常量作比较。如果发现了一个与之相匹配的,则执行该 case 语句后的代码。如果没有一个 case 常量与表达式的值相匹配,则执行 default 语句。
default 语句是可选的。
如果没有相匹配的 case 语句,也没有 default 语句,则什么也不执行。
注意:重复的 case 值是不允许的。
=================================================
使用注意:
- switch 关键字后面小括号里的值:要放一个整型变量或字符型变量;表达式必须为 byte,short,int,char类型;
- case 关键字后的值,可以是:类型为 char、byte、 short 或 int 的常量表达式;enum 常量;或字符串字面量;
- break:一般语句块后均需要加 break;如果在 case 分支语句的末尾没有 break 语句,那么就会接着执行下一个 case 分支语句。这种情况相当危险,常常会引发错误。
- default:表示“默认”,即其他情况都不满足;default 块和 case 块的先后顺序可以变动,不会影响程序执行结果。通常,default 块放在末尾,也可以省略不写。
- switch 语句中也支持嵌套,但一般不这么用
- if 语句可计算任何类型的布尔表达式。也就是 switch 语句只能寻找 case 常量间某个值与表达式的值相匹配。
循环结构
所有流行的编程语言中都有循环语句。Java 中采用的循环语句与C语言中的循环语句相似,主要有:
- while
- do-while
- for
Java 5 之后,还推出了 for-each 循环语句。它是专门为数组、集合遍历而设计的。但 for-each 并不是一个关键字。
while 语句
while 语句是 Java 最基本的循环语句,是一种先判断的循环结构。while 循环语句的语法结构如下:
1 | while(条件表达式) { |
其中语句块中的代码可以是一条或者多条语句,而条件表达式是一个有效的 boolean 表达式,它决定了是否执行循环体。当条件表达式的值为 true 时,就执行大括号中的语句块。
循环语句的执行流程如下:
实例:
1 | public class HelloWorld { |
do…while语句
如果 while 循环一开始条件表达式就是假的,那么循环体就根本不被执行。然而,有时需要在开始时条件表达式即使是假的情况下,while 循环至少也要执行一次。
do-while 循环语句的特点是先执行循环体(循环至少也要执行一次),然后判断循环条件是否成立,成立后继续执行。
do-while 语句的语法格式如下:
1 | do { |
do-while 循环语句执行流程如下:
实例(图书列表中保存了 50 条信息,现在需要让它每行显示 10 条,分 5 行进行显示):
1 | public static void main(String[] args) { |
for 语句
for 循环,和 while 循环一样,只是表达方式不一样。
for 语句语法格式如下所示:
1 | for(条件表达式1;条件表达式2;条件表达式3) { |
for 关键字后面括号中的 3 个条件表达式必须用 “;” 隔开。
for 循环中 3 个表达式的含义:
表达式 | 形式 | 功能 | 举例 |
---|---|---|---|
条件表达式 1 | 赋值语句 | 循环结构的初始部分,为循环变量赋初值 | int i=1 |
条件表达式 2 | 条件语句 | 循环结构的循环条件 | i>40 |
条件表达式 3 | 迭代语句,通常使用 ++ 或 – 运算符 | 循环结构的迭代部分,通常用来修改循环 变量的值 | i++ |
1 | public static void main(String[] args) { |
==================================================
特别:
for 语句中初始化、循环条件以及迭代部分都可以为空语句(但分号不能省略),三者均为空的时候,相当于一个无限循环。但无论缺少哪部分条件表达式,都可以在程序的其他位置补充,从而保持 for 循环语句的完整性,使循环正常进行。
1 –> 条件表达式 1 为空
例如,使用 for 语句的这种形式计算 1~100 所有奇数的和。
1 | public static void main(String[] args) { |
2 –> 条件表达式 2 为空
当 for 语句中条件表达式 2 为空时,将没有循环的终止条件。为了使循环达到某种条件时退出,需要在语句块中进行逻辑判断,并使用 break 语句来跳出循环,否则将产生死循环。
同样是计算 1~100 所有奇数的和,使用这种方式的代码如下。
1 | public static void main(String[] args) { |
3 –> 条件表达式 3 为空
当 for 语言中条件表达式 3 为空时,也就没有设置控制变量的表达式,即每次循环之后无法改变变量的值,此时也无法保证循环正常结束。
同样是计算1~100 所有奇数的和,使用这种方式的代码如下:
1 | public static void main(String[] args) { |
4 –> 3 个条件表达式都为空
事实上,在 for 循环语句中,无论缺少哪部分条件表达式,都可以在程序的其他位置补充,从而保持 for 循环语句的完整性,使循环正常进行。
但是,对于这种情况,读者在使用时应该尽量避免。
例如,计算 1~100 所有奇数的和,使用这种方式的代码如下:
1 | public static void main(String[] args) { |
循环嵌套
和其他编程语言一样,Java 允许循环嵌套。如果把一个循环放在另一个循环体内,那么就可以形成嵌套循环。
嵌套循环既可以是 for循环嵌套 while 循环,也可以是 while 循环嵌套 do-while 循环 …… 即各种类型的循环都可以作为外层循环,也可以作为内层循环。
假设外层循环的循环次数为 n 次,内层循环的循环次数为 m 次,那么内层循环的循环体实际上需要执行 n×m 次。
for、do-while 和 while 的区别:
名称 | 概念 | 适用场景 |
---|---|---|
for | 根据循环次数限制做多少次重复操作 | 适合循环次数是已知的操作 |
while | 当满足什么条件的时候,才做某种操作 | 适合循环次数是未知的操作 |
do-while | 先执行一次,在判断是否满足条件 | 适合至少执行一次的循环操作 |
foreach 语句
foreach 循环语句是 Java 1.5 的新特征之一,在 遍历数组、集合 方面,foreach 为开发者提供了极大的方便。
foreach 循环语句的语法格式如下:
1 | for(类型 变量名:集合) { |
其中,“类型”为集合或数组中 元素的类型,“变量名”表示集合或数组中的每一个元素,“集合”是被遍历的集合对象或数组。
样例,假设有一个数组,采用 for 语句遍历数组的方式如下:
1 | // 声明并初始化数组 |
关于数组集合会在教程后面详细介绍,这里我们只需要大概了解就可以。numbers.length 是获得数组的长度,length 是数组的属性,numbers[i] 是通过数组下标访问数组元素。
那么采用 for-each 循环语句遍历数组的方式如下:
1 | // 声明并初始化int数组 |
从示例中可以发现,item 不是循环变量,它保存了集合中的元素,for-each 语句将集合中的元素一一取出来,并保存到 item 中,这个过程中不需要使用循环变量,通过数组下标访问数组中的元素。可见 for-each 语句在遍历集合的时候要简单方便得多。
–> 注意:foreach 循环迭代数组(集合)元素时,并不能改变数组(集合)元素的值
当使用 foreach 循环来迭代输出数组元素或集合元素时,通常不要对循环变量进行赋值,虽然这种赋值在语法上是允许的,但没有太大的实际意义,而且极容易引起错误。例如下面程序。
1 | public static void main(String[] args) { |
运行上边程序,将看到如下结果:
1 | 时下流行的编程语言: |
可以发现,由于在 foreach 循环中对数组元素进行赋值,结果导致不能正确遍历数组元素,不能正确地取出每个数组元素的值。而且当再次访问第一个数组元素时,发现数组元素的值依然没有改变。
===================================================
原理解析:
当使用 foreach 来迭代访问数组元素时,foreach 中的循环变量相当于一个临时变量,系统会把数组元素依次赋给这个临时变量,而这个临时变量并不是数组元素,它只是保存了数组元素的值。因此,如果希望改变数组元素的值,则不能使用这种 foreach 循环。
break 语句
某些时候需要在某种条件出现时强行终止循环,而不是等到循环条件为 false 时才退出循环。此时,可以使用 break 来完成这个功能。
Java 中,break 语句有 3 种作用:
- break,可用于直接结束当前循环
- 在 switch 语句中终止一个语句序列
- 实现 goto 的功能
直接结束当前循环
使用 break 语句直接强行退出循环的示例如下:
1 | public class HelloWorld { |
输出如下:
1 | 1 |
break 语句能用于任何 Java 循环中,包括人们有意设置的无限循环。
在一系列嵌套循环中使用 break 语句时,它将仅仅终止最里面的循环
1 | public static void main(String[] args) { |
break 带标签实现 goto 功能
Java 提供了一种带标签的 break 语句,用于跳出多重嵌套的循环语句,可以实现 goto 的功能。
通过使用扩展的 break 语句,可以终止执行一个或者几个任意代码块,这些代码块不必是一个循环或一个 switch 语句的一部分。同时这种扩展的 break 语句带有标签,可以明确指定从何处重新开始执行。
标签 break 语句的通用格式如下:
break label;
label 是标识代码块的标签。被加标签的代码块必须包围 break 语句,但是它不需要直接包围 break 的块。也就是说,可以使用一个加标签的 break 语句来退出一系列的嵌套块,但是不能使用 break 语句将控制权传递到不包含 break 语句的代码块。
用标签(label)可以指定一个代码块,标签可以是任何合法有效的 Java 标识符,后跟一个冒号。
下面是使用带标签的break 语句的示例。
1 | public class GotoDemo { |
程序执行结果:
1 | 0 |
可以发现,加上标签的代码块可以作为 break 语句的对象,使程序在加标签的块的结尾继续执行。
标签语句必须和循环匹配使用,使用时书写在对应的循环语句的上面,标签语句以冒号结束。如果需要中断标签语句对应的循环,可以采用 break 后面跟标签名的方式。
但注意,标签语句可以独立使用, Java 不会报错
switch 语句中终止一个语句序列
break 在 switch 语句中可终止一个语句序列,就是在每个 case 子句块的最后添加语句 “break;”,具体使用可见分支结构中的 switch 语句。
continue 语句
与 break 语句一样, 它将中断正常的控制流程。与 break 语句的区别在于:continue 并不是中断循环语句,而是中止当前迭代的循环,进入下一次的迭代。
简单来讲,continue 是忽略循环语句的当次迭代。
1 | public class HelloWorld { |
程序输出:
1 | 1 |
–> continue label
同 break 语句一样,continue 语句同样可以配合 label 使用。
带标签的 continue 语句示例代码如下:
1 | public class GotoDemo { |
注意,与 break label 使用时的区别。
输出如下:
1 | 0 |
install_url
to use ShareThis. Please set it in _config.yml
.