Java 软件设计基础 3. 流程控制
3.1 语句控制结构 语句类型 变量声明语句 用来声明变量, 格式为 : 表达式语句 在一个表达式的最后加上一个分号构成的语句, 分号是语句不可缺少的部分, 格式为 : 变量 = 表达式 ; 复合语句 [ 修饰符 ] 类型名变量名 1[, 变量名 2][, ]; [ 修饰符 ] 类型名变量名 1[= 初值 1][, 变量名 2][= 初值 2][, ]; 将相关语句组合在一起就构成复合语句, 复合语句用 { } 括起来
空语句 空语句是什么都不做的语句, 形式为 : 方法调用语句 方法是一系列相关的程序语句的集合, 能实现一定的功能 可以直接调用已定义好的方法来简化程序的编写 格式为 : package 和 import 语句 泛指包含 package( 包 ) 和 import 的语句, 与类 对象有关 控制语句 (control statement) 通常源文件中的语句按照它们出现的顺序从头到尾执行, 但是控制语句通过使用决策 循环和分支来改变执行流程, 使程序按照条件执行特定的代码块 控制语句分为以下几类 : ; 定位标识. 方法名 ( 参数列表 );
顺序结构 : 在程序执行时, 根据程序中语句的书写顺序依次执行的命令序列 语句 1 语句 2 分支结构 : 又成为选择结构, 是在程序执行时, 根据不同的条件, 选择执行不同的程序语句, 用来解决有选择 有转移等诸多问题, 完成应用程序中的智能判断功能 T 条件? F 语句 1 语句 2
循环结构 : 使某些语句或程序段按条件重复执行若干次, 直至该特定条件不满足为止 循环有以下特点 : a. 只有一个入口和出口 ; b. 结构内的每部分都有机会被执行 ; c. 结构内没有 死循环, 即无终止循环或无限循环 语句 T 条件? F
3.2 分支结构 if 条件语句 if-then 语句 是所有控制语句中最基础的语句, 只有特定检测结果为 true 时, 它才通知程序执行特定的代码段 if-then-else 语句 说明 当 if 子句的计算结果为 false 时, 该语句提供第二个执行路径 条件表达式是任意一个返回布尔型数据的表达式 ; 简单语句可以省略前面的花括号 决定什么时候省略括号是个人的习惯, 但会导致代码更加脆弱 如果以后在 then 语句后面加入第二个语句, 常见的错误是忘记加上必须的括号 编辑器不能识别这样的错误, 将会得到错误的结果 以上两种条件语句的结构和格式如下 :
true 1 false if-then if ( 条件表达式 ) { 语句块 ; } 首先计算布尔表达式, 若为真, 则执行语句 1, 否则就直接转入 if 语句的后续语句 if false true 1 2 首先计算布尔表达式, 若为真, 则执行语句 1, 否则执行语句 2, 然后转入 if 语句的后续语句
上述语句不能产生正确的结果 该错误很难发现, 因为这并非编译错误或者是运行时错误 这属于逻辑错误 复合条件 若 if 语句的布尔表达式由一个简单判断给出, 称为简单条件 ; 若由多个简单条件经过逻辑运算而得到, 称为复合条件
嵌套条件语句 Java 中没有提供象 elseif 这样的关键字来进行多条件分支 三种选择或以上的分支就需要利用 if 语句的嵌套来实现 程序从上往下依次判断布尔表达式的条件, 一旦某个条件满足, 就执行相关语句, 然后就不再判断其余的条件, 直接转到 if 语句的后续语句去执行 else 总是与离它最近的 if 语句配对
优秀的书写方式 : if(score>=90) grade= A ; else if(score>=80) grade= B ; else if(score>=70) grade= C ; else if(score>=60) grade= D ; else grade= E ;
switch 多分支语句 允许使用任意数量的可能执行路径, 当分支过多时, 比嵌套条件语句更具有直观性 便捷性 格式如下 : switch 语句 switch( 表达式 ) { case 常量 1: [ 语句块 1; break;] case 常量 2: [ 语句块 2; break;] case 常量 n: [ 语句块 n; break;] [default: 语句块 n+1;break;] }
说明 显然, 通过 if-else 语句的嵌套也能实现 switch 语句的功能, 但通常使用 switch 语句更简练, 而且可读性强, 程序的执行效率也高 ; 表达式的返回类型必须是 byte,short,char 和 int 四种类型, 或者是以后将讨论的枚举类型 (enumerated type), 还可以是 包装 特定原始类型的几个特殊类 :Character,Byte,Short 和 Integer; case 子句中的值必须是常量, 且值应该不相同 ; case 的分支中有多个执行语句时不必用 { } 括起 ; default 子句是可选的, 它处理没有被任何 case 语句显式处理的值 若表达式中的值与所有 case 都不相配, 且没有 default 子句, 则跳出 switch 语句 ; break 语句的作用是执行完一个 case 分支后使程序跳出 switch 语句, 它是可选的, 如果没有这条语句, 流程控制将一个接一个的执行后续的 case 操作, 这样分支语句将变得效率极低且容易误操作
在一些特殊情况下, 多个不同的 case 值要执行一组相同的操作, 可以写成如下形式 : 执行过程 case 语句 case 常量 n: case 常量 n+1: 语句块 ; [break;] 计算表达式的值, 同 case 分支比较, 如果相同则执行相应的语句块, 否则继续向下比较, 直至找到相同的 case 值或者到达 default 分支 ; 在 default 分支不存在的情况下, 则跳出整个 switch 语句 ; Switch 语句的每一个 case 判断, 都只负责指明流程分支的入口点, 而不负责分支的出口点, 分支的出口点需要编程人员用相应的跳转语句来标明
3.3 循环语句 while 语句 是 Java 最基本的循环语句, 格式如下 : 其中,while 是关键字, 布尔表达式是循环条件, 语句为循环体 执行过程如下 : 首先判断布尔表达式, 若为真, 则执行循环体, 然后再判断条件, 直到布尔表达式的值为假, 停止执行语句
注意 : 该语句是先判断后执行, 若一开始条件就不成立, 则不执行循环体 ; 在循环体内部一定要有改变条件的语句, 否则是死循环 do-while 语句 格式 : do-while 语句是 先执行后判断 型, 先执行一次循环体中的语句, 然后测试布尔表达式的值, 若为 true, 则继续执行循环, 否则执行 do-while 语句的后续语句
例程
for 语句 是三种循环语句中功能较强 形式灵活 使用较频繁的循环语句结构, 尤其适合于循环次数清晰的场合
执行过程 : 1 按表达式 1 将初值赋给循环控制变量 ; 2 按布尔表达式判断循环是否成立, 即判断控制变量的值是否满足布尔表达式的条件, 若条件不成立, 则转步骤 5; 若条件成立, 则执行循环 ; 3 按表达式 3 修改控制变量 ; 4 返回步骤 2; 5 结束循环, 执行 for 语句的后续语句 for 语句中循环控制变量必须是有序类型 循环控制变量初值和终值通常是与控制变量类型相一致的常量, 也可以是表达式 对控制变量的初始化只执行一次, 而循环次数由初值和终值决定 其他形式 : 当 表达式 1 表达式 2 表达式 3 都为空的时候, 相当于一个无限循环, 如 :
有时,for 语句在 表达式 1 和 表达式 3 的位置上需要包含多个语句, 由于不能在 for 语句的 ( ) 中使用 { } 来定义复合语句, 因此提供了用逗号分隔的语句系列 如 : 在 for 语句的圆括号的后面加个分号, 则相当于 for 语句的循环体为空语句 例如 :
for 例程 public class ForDemo { public static void main(string[] args) { for(int i=1; i<11; i++) { System.out.println("Count is: " + i); } } } 注意 : 初始化表达式中声明变量的代码 该变量的作用域从其声明开始直到 for 循环控制块的结束 如果在循环之外不需要用到该变量, 那么最好在初始化表达式中声明, 这样就限制了它们的生存周期并且减少了错误的可能
增强的 for 语句 用于在集合和数组之中进行迭代, 可以使循环更加紧凑和容易阅读 注意 : 在这个程序中, 变量 item 保存从数字数组获得的当前值 只要情况允许, 尽量使用 for 循环的增强形式
循环嵌套 一个循环体内又包含另一个完整的循环结构, 称为循环的嵌套 内嵌的循环中还可以嵌套循环, 这就是多重循环 while do-while for 之间都可以互相嵌套使用
3.4 跳转语句 跳转语句用来实现程序执行过程中流程的转移 goto 语句使程序结构混乱, 可读性差 ; Java 语言取消了 goto 语句, 通过 break 语句 continue 语句和 return 语句实现流程的转移 break 语句 使程序的流程从一个封闭语句块 ( 如 switch) 中跳出来, 也可以用于退出一个循环 ( 如 do for while), 此外, 还可以跳到相应的标记位 分类 : 不带标号的 break 语句 从它所在的 switch 分支或最内层循环中跳出来, 执行分支或循环体后面的语句 不能用于循环语句和 switch 语句之外的其他任何语句中
带标号的 break 语句 break 语句的语法格式如下 : 设置标记的语句格式 : break 标号 ; 标号 : 语句 标号 是程序中设置好的标记名, 程序跳到标号所在的语句或者语句块的下一句开始执行 break 语句必须在加标记的代码块的内部才可以跳到标记位 break 终止带加标记的语句, 不是把控制流转移到标记位置, 而是转移到紧跟在标记的语句 ( 块 ) 后面的语句 可以把标号设置在任意的语句或语句块之前
带标号 break 例程 public class BreakWithLabelDemo { public static void main(string[] args) { int[][] arrayofints = {{32,87,3,589},{12,1076,2000,8},{622,127,77,955}}; int searchfor = 12; int i; int j = 0; boolean foundit = false; search: for (i = 0; i < arrayofints.length; i++) { for (j = 0; j < arrayofints[i].length; j++) { if (arrayofints[i][j] == searchfor) { foundit = true; break search; } } } if (foundit) { System.out.println("Found " + searchfor + " at " + i + ", " + j); } else { System.out.println(searchfor + " not in the array"); } } }
continue 语句 continue 语句只能在循环语句中使用 它和 break 语句的区别是 :continue 语句只终止本次循环, 而不是终止整个循环 ; 而 break 语句则是结束整个循环语句的执行 continue 语句同样有两种格式 : 不带标号 终止本次循环, 即跳过循环体中 continue 语句后面的语句, 回到循环体的条件测试部分继续执行 注意 : 只能跳过本次循环的剩余语句 带标号的情况 continue 标号 ; 标号 : 语句 跳过标号指出的语句块中的所有余下语句部分, 回到标号所指语句块的条件测试部分继续执行 标号应该定义在程序中外层循环语句的前面, 用来标志这个循环结构 带标号的 continue 语句使程序的流程直接转入标号标明的循环层次
continue 例程 public class ContinueDemo { public static void main(string[] args) { String searchme = "peter piper picked a peck of pickled peppers"; int max = searchme.length(); int numps = 0; for (int i = 0; i < max; i++) { if (searchme.charat(i)!= 'p') continue; numps++; } System.out.println("Found " + numps + " p's in the string."); } }
return 语句 用来从当前方法中退出, 可使正在执行的分支程序返回到调用它的方法的相应语句处, 并从紧跟该语句的下一条语句继续执行, 格式如下 : return [ 表达式 ]; 说明 : 表达式的值就是被调用方法的返回值, 如果方法没有返回值, 则 return 语句中的表达式可以省略 ; 如果方法中没有出现 return 语句, 则执行完方法中的最后一条语句后自动返回调用它的方法