控制执行流程

 

 就像有知觉的生物一样,程序必须在执行过程中控制它的世界,并做出选择。在Java中,你要使用执行控制语句来做出选择。

        Java 使用了C的所有流程控制语句,所以如果读者以前用过C或C++编程,那么应该非常熟悉了。大多数过程型编程语言都有某些形式的控制语句,它们通常在各种语言间是交迭的。

         在Java总,设计的关键字包括:if-else、do-while、for、return、break以及选择语句switch。

         然而,Java并不支持goto语句(该语句引起许多反对意见,但它仍是解决某些特殊问题的最便利的方法)。

          在Java中,仍然可以进行类似goto那样的跳转,但比起典型的goto,有了很多限制。

    4.1 true和false

          所有条件语句都利用条件表达式的真或假来决定执行路径。这里有一个条件表达式的例子:

          a==b。

           注意Java不允许我们将一个数字作为布尔型值使用,虽然这在C和C++是允许的(在这些语言里,“真”是非零,而“假”是零)。

        4.2 if-else

          if-else语句是控制程序流程最基本的形式。其中的else是可选的,所以可按下述两种形式来使用if:

          if(boolean-expression)

               statement

            或

                if(boolean-expression)

                  statement

                else

                   statement

        布尔表达式必须产生必须产生一个布尔结果,statement指用分号结尾的简单语句,或复合语句——封闭在花括号内的一组简单语句。在本书任何地方,只要提及“ 语句 ”这个词,就指的是简单语句或符合语句。

条件语句

 

          可以看到“ else if”,那并非新的关键字,而仅仅只是一个else后面紧跟另一个新的if语句。

          尽管Java与它之间产生的C和C++一样,都是“ 格式自由 ”的语言,但习惯上还是将流程控制语句的主体部分缩进排列,使读者能方便地确定起始与终止。

         4.3 迭代

        while、do-while和for用来控制循环,有时将它们划分为 迭代语句(iteration statement)。语句会重复执行,知道起控制作用的布尔表达式(booleanexpression)得到“ 假 ”的结果为止。

        while循环的格式如下:

        while(boolean-expression)

            statment

        在循环刚开始时,会计算第一次布尔表达式的值,而在语句的下一次迭代开始前会再计算一次。

       4.3.1 do-while

        do-while的格式如下:

        do 

              statement

         while(boolean-expression)

         while和do-while唯一的区别就是do-while的语句至少执行一次,即便表达式第一次被计算为false。而在while循环结构中,如果条件第一次就是false,那么其中的语句根本不会执行。在实际应用总,while比do-while更常用一些。

      4.3.2 for

        for循环可能是最经常使用的迭代形式,这种在第一次迭代之前要进行初始化。随后,它会进行条件测试,而且在每一次迭代结束时,进行某种形式的“ 步进 ”。for循环的格式如下:

        for(initialization;boolean-expression;step)

            statement

    初始化(initialization)表达式、布尔表达式(boolean-expression),或者步进(step)运算,都可以为空。

    每次迭代前会测试布尔表达式。若获得的结果是false,就会执行for语句后面的代码行。每次循环结束,会执行一次步进。

    注意,变量c是在程序用到它的地方被定义的,也就是在for循环的控制表达式里,而不是在main()开始的地方定义的。c的作用域就是for控制的表达式的范围内。

    对于像C语言那样的传统的过程型语言,要求所有变量都在一个块的开头定义,以便编译器在创建这个块的时候,可以为哪些变量分配空间。

     而在Java和C++中,则可在整个块的范围内分散变量申明,在真正需要的地方才加以定义。这样便可形成更自然的编程风格,也更易理解。

      4.3.3 逗号操作符

      本章前面已经提到了逗号操作符(注意不是逗号分隔符,逗号用作分隔符时用来分隔函数的不同参数),Java里唯一用到逗号操作符的地方就是for循环的控制表达式。在控制表达式的初始化和步进控制部分,可以使用一系列由逗号分隔的语句;而且哪些语句均会独立执行。

      通过使用逗号操作符,可以在for语句内定义多个变量,但是它们必须具有相同的类型。

逗号操作符

          可以看到,无论在初始化还是在步进部分,语句都是顺序执行的。此外,初始化部分可以有任意数量的同一类型的定义。

        4.4 Foreach语法

         Java SE5引入了一种新的更加简洁的for语法用于数组和容器,即Foreach语法,表示不必创建int变量去对由访问构成的序列进行计数,foreach将自动产生每一项。

         假如,假设有一个float数组,我们要选取该数组中的每一个元素:

     

数组循环用for

     这个数组是用旧式的for循环组装的,因为在组装时必须按索引访问它。

     在下面看到foreach语法:

       for(float x:f){} 

        这条语句定义了一个float类型的变量x,继而将每个f的元素赋值给x。

        任何返回一个数组的方法都可以使用foreach。

       foreach语法不仅在录入代码时可以节省时间,更重要的是,它阅读起来要容易的多,它说明您正在努力做什么,而不是给出你正在如何做的细节(例如正在创建索引,因此可以使用它来选取数组中的每一个元素)。

     4.5 return

      在Java中有多个关键字表示无条件分支,它们只是表示这个分值无需任何测试即可发生。

      这些关键词包括 return、break、continue和一种与其他语言中的goto类似的跳转到标号语句的方式。

     return 关键词有两个方面的用途:一方面指定一个方法返归什么值(假设它没有void返回值),另一方面它会导致当前的方法退出,并返回那个值。可据此改写上面的test()方法,使其利用这些特点:

   

return关键词

    不必加上else,因为方法在执行了return后不再继续执行。

     如果在返回void的方法中没有return语句,那么在该方法的结尾处会有一个隐式的return,因此在方法中并非总是必须要有一个return语句。但是,如果一个方法声明它将返回void之外的其他东西,那么必须确保每一条代码路径都将返回一个值。

     4.6 break和continue

      在任何迭代语句的主体部分,都可用break和continue控制循环的流程。

      其中,break用于强行退出,不执行循环中剩余的语句。

      而continue则停止执行当前的迭代,然后退出循环起始处,开始下一次迭代。

       下面这个程序向大家展示了break和continue在for和while循环中的例子:

       

break、continue

 

 

        无穷循环的第一种形式:while

         无穷循环的第二种形式:for(;;)

         编译器将while(true)与for(;;)看作是同一回事。所以具体选用哪个取决于自己的编程习惯。

     4.7 臭名昭著的 goto

        编程语言中一开始就有goto关键词了。事实上,goto起源于汇编语言的程序控制:“ 若条件A成立,则跳到这里;否则跳到那里 ”。如果阅读由编译器最终生成的汇编代码,就会发现程序控制里包含了许多跳转。(Java编译器生成它自己的“ 汇编代码 ”),但是这个代码是运行在Java虚拟机上的,而不是直接运行在CPU硬件上)。

         goto语句是在源码级上的跳转,这使其导致了不好的声誉。若一个程序总是从一个地方调到另一个地方,还有什么办法能识别程序的控制流程呢?自从Edsger Dijkstra发表了著名论文《Goto considered harmful》 (Goto有害),众人开始痛斥goto的不是,甚至建议将它从关键词集合中扫地出门。

        对于这个问题,中庸之道是最好解决方法。真正的问题并不在于使用goto,而在于goto的滥用;而且少数情况下,goto还是组织控制流程的最佳手段。

       尽管goto仍是Java的一个保留字,但在语言中并未使用它;Java没有goto。然而,Java也能完成一些类似于跳转的操作,这与break和continue这两个关键词有关。它们其实不是一个跳转,而是中断迭代语句的一种方法。之所以把它们纳入goto问题中一起讨论,是由于它们使用了相同的机制:标签

       标签是后面跟有冒号的标识符,就像下面这样:

       label1:

       在Java中,标签起作用的唯一的地方刚好是在迭代语句之前。“ 刚好之前 ”的意思表明,在标签和迭代之间的置入任何语句都不好。而在迭代之前设置标签的唯一理由是:我们希望在其中嵌套另一个迭代或者一个开关(你很快就会学习到它)。这是由于break和continue关键词通常只中断当前循环,但若随同标签一起使用,它们就会中断循环,直到标签所在的地方:

        label1:

        outer-iteration{

         inner-iteration{

        //...

        break;//(1)

        //...

        continue;//(2)

         //...

          continue label1;//(3)

          //...

           break label1; // (4)

}

}

 

       

label

         同样的规则亦适用于while:

         1)一般的continue会退回最内层循环的开头(顶部),并继续执行。

         2)带标签的continue会达标签的位置,并重新进入紧接在那个标签后面的循环。

         3)一般的break会中断并跳出当前循环。 

         4)带标签的break会中断并跳出标签所指的循环。

       要记住的重点是:Java里需要使用标签的唯一理由就是因为循环嵌套存在,而且想从多层嵌套中break或continue。

        在Dijkstra的《Goto有害》的论文中,他最反对的就是标签,而非goto。他发现在一个程序里随着标签的增多,产生的错误也会越来越多,并且标签和goto使得程序难以分析。但是,Java的标签不会造成这种问题,因为他们的应用场合已经收到了限制,没有特别的方式用于改变程序的控制。由此也引出了一个有趣的现象:通过限制语句的能力,反而能使一项语言特性更加有用。

       4.8 switch

       switch有时也被归为一种选择语句。根据整数表达式的值,switch语句可以从一系列代码中选出一段去执行。它的格式如下:

      

switch语句

        其中:Integral-selector(整数选择因子)是一个能够产生数值的表达式,switch能将这个表达式的结果与每个integral-value(整数值)相比较。若发现相符的,就执行对应的语句(单一语句或多条语句,其中并不需要括号)。若没有发现相符的,就执行default(默认)语句。

       在上面的定义中,大家会注意到每个case均以一个break结尾,这样可使执行流程跳转至switch主体的末尾。这是构建switch语句的一种传统方式,但break是可选的。若省略break,会继续执行后面的case语句,直到遇到一个break为止。尽管通常不想出现这种情况,但对有经验的程序员来说,也许能够改善加利用这种情况。注意最后的default语句没有break,因为执行流程已经到了break的跳转的目的地。

       当然,如果考虑到编程风格方面的原因,完全可以在default语句的末尾放置一个break,尽管它并没有任何实际的用处。

       switch语句是实现多路选择(也就是说从一系列执行路径中挑选一个)的一种干净利落的方法。

       但它要求使用一个选择因子,并且必须是int或char那样的整数值。

       例如: 

       假若一个字符串或者浮点数作为选择因子使用,那么它们在switch语句中是不会工作的。对于非整数类型,则必须使用一系列if语句。

      

switch控制语句

    4.9 总结

        本章介绍了大多数编程语言都具有的基本特性:运算、操作符优先级、类型转换以及选择和循环等等。

        现在我们已经做好了准备,以使自己更靠近面向对象的程序设计世界。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值