读thinking in java笔记(三):控制执行流程

    就像有知觉的生物一样,程序必须在执行过程中控制它的世界,并做出选择。在Java中你要执行控制语句来做出选择。
    java中使用了C的所有流程控制语句。在Java中涉及的关键字包括if-else、while、do-while、for、return、break以及选择语句switch。然而,Java并不支持goto语句,(该语句引起很多反对意见,但它仍是解决某些特殊问题的最便利的方法)。在Java中,仍然可以进行类似goto那样的跳转,但比起典型的goto,有了很多限制。

1. true和false
    所有条件语句都利用条件表达式的真或假来决定执行路径。在前面介绍的所有关系操作符,都可拿来构造条件语句。注意Java不允许我们将一个数字作为布尔值来使用,虽然这在C和C++里是允许的(在这些语言里,“真”是非零,而“假”是零)。如果想在布尔测试中使用一个非布尔值,比如在if(a)中,那么首先必须用一个条件表达式将其转换成布尔值,例如if(a!=0)。
2. if-esle
    if-else语句是控制程序流程最基本的形式。其中的else是可选的,所以可按下面两种形式来使用if:

ifBoolean-expression)
    statement
或
ifBoolean-expression)
    statement
else
    statement

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

例子:告诉您,您猜的数是大于、小于还是等于目标数。
public class IfElse {

    public static void main(String[] args) {
        testVal(6, 2);
        testVal(4, 8);
        testVal(5, 5);
    }

    public static void testVal(int testVal, int target) {
        if (testVal > target) {
            System.out.println("您输入的值大于目标值,请重新输入!");
        } else if (testVal < target) {
            System.out.println("您输入的值小于目标值,请重新输入!");
        } else {
            System.out.println("恭喜您猜对了!");
        }
    }
}

2. 迭代
    while、do-while和for用来控制循环,有时将它们划分为迭代语句(iteration statement)。语句会重复执行,直到起控制作用的布尔表达式(Boolean-expression)得到“假”的结果为止。
  2.1 while
   while格式如下:

whileBoolean-expression)
    statement

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

例子:产生随机数,直到符合特定的条件为止。
public class WhileTest {

    public static void main(String[] args) {
        while (condition()) {
            System.out.println("inside while");
        }
        System.out.println("outside while");
    }

    public static boolean condition(){
        boolean result = Math.random() < 0.99;
        System.out.println(result + ",");
        return result;
    }
}

    condition()方法用到了Math库里的static(静态)方法random(),该方法的作用是产生0和1之间(包含0,不含1)的一个double值(这个double值小数点后有16位)。result的值是通过比较操作符<而得到的,这个操作符将产生double类型的结果。while条件表达式的意思是说:“只要condition()返回true,就重复执行循环体重的语句”。
  2.2 do-while
   do-while格式如下:

do
    statement
while(boolean-expression);

    while和do-while唯一区别就是do-while中的语句至少会执行一次,即便表达式第一次就被计算为false。而在while循环结构中,如果条件第一次就为false,那么其中的语句根本不会执行。在实际应用中,while比do-while更常用一些。其实之所以do-while至少会执行一次是因为它是先执行一次再判断的布尔表达式。
  2.3 for
    for循环可能是最经常使用的迭代形式,这种在第一次迭代之前要进行初始化。随后它会进行条件测试,而且在每一次迭代结束时,进行某种形式的“步进”。for循环的格式如下:

for(initialization; boolean-expression; step)
    statement

    初始化(initialization)表达式、布尔表达式(Boolean-expression),步进(step);每次迭代前会测试布尔表达式。若获得的结果为false,就会执行for语句后面的代码行,每次循环结束后,会执行一次步进。

例子:
public class ListCharacters {

    public static void main(String[] args) {
        for (char c = 0; c < 100; c++) {
            if (Character.isLowerCase(c)) {
                System.out.println("value:" + (int)c + "  characters: " + c);
            }
        }
    }
}
//备注:Character.isLowerCase();判断是否为一个小写字母;
//if(布尔表达式)

    注意:变量c是在程序用到它的地方被定义的,也就是在for循环的控制表达式里,而不是在main()开始的地方定义的。c的作用域就是for控制表达式的范围内。
    这个程序也使用了java.lang.Character包装器类,这个类不但能把char基本类型的值包装进对象,还提供了一些别的有用的方法。这里用到了static isLowerCase();来检查问题中的字符是否为小写字母。

练习1:打印1100的值。
public class PrintVal {
    public static void main(String[] args) {
        for (int i = 0; i <= 100; i++) {
            System.out.println(i);
        }
    }
}

  2.4 逗号操作符
    本章前面已经提到了逗号操作符(注意不是逗号分隔符,逗号用作分隔符时用来分隔函数的不同参数),Java里唯一用到逗号操作符的地方就是for循环的控制表达式。在控制表达式的初始化和步进控制部分,可以使用一系列有逗号分隔的语句;而且那些语句均会独立执行。通过使用逗号操作符,可以在for语句内定义多个变量,但是它们必须具有相同的类型。控制表达式(初始化表达+布尔表达式+步进)

例子:
public class CommaOperator {
  public static void main(String[] args) {
    for(int i = 1, j = i + 10; i < 5; i++, j = i * 2) {
      System.out.println("i = " + i + " j = " + j);
    }
  }
} /* Output:
i = 1 j = 11
i = 2 j = 4
i = 3 j = 6
i = 4 j = 8
*/

    for语句中的int定义涵盖了i和j,在初始化部分实际上可以拥有任意数量的具有相同类型的变量定义。在一个控制表达式中,定义多个变量的这种能力只限于for循环使用,在其他任何选择或迭代语句中都不能用这种方式。可以看到,无论在初始化部分还是在步进部分,语句都是顺序执行的。此外,初始化部分可以有任意数量的同一类型的定义。
3. foreach语法
    JavaSE5引入了一种新的更加简洁的for语法用于数组和容器,即foreach语法,表示不必创建int变量去对由访问项构成的序列进行计数,foreach将自动产生每一项。

例子:假设有一个float数组,我们要选取该数组中的每一个元素
public class ForeachFloat {

    public static void main(String[] args) {
        Random rand = new Random(12);
        float[] farr = new float[10];
        for (int i = 0; i < farr.length; i++) {
            farr[i] = rand.nextInt(100);
        }
        for (float f : farr) {
            System.out.println(f);
        }
    }
}

    这个数组是用旧式的for循环组装的,因为在组装时必须按索引访问它。上面我们看到了foreach的语法:for (float f : farr) 这条语句定义了一个float类型的变量f,继而将每一个farr的元素赋值给x。任何一个返回数值的方法都可以使用foreach,例如:String类有一个方法toCharArray(),它返回一个char数组,我们可以很容易的迭代在字符串中的字符。

public class ForeachString {

    public static void main(String[] args) {
        for (char ch : "this is String".toCharArray()) {
            System.out.print(ch + " ");
        }
    }
}
//备注:println();换行    print();不换行

4. return
    在Java中有多个关键词表示无条件分支,它们只是表示这个分支无需任何测试即可发生。这些关键词包括return、break、continue。
    return关键词有两方面的用途:1.指定一个方法返回什么值(假设返回的不是void);2.它会导致当前方法的退出,并返回那个值。

public class IfElse2 {

    public static int testVal(int testVal,int target){
        if(testVal > target){
            return -1;
        }else if(testVal < target){
            return +1;
        }else{
            return 0;
        }
    }
    public static void main(String[] args) {
        System.out.println(testVal(6, 2));
        System.out.println(testVal(2, 4));
        System.out.println(testVal(3, 3));
    }
}

    如果在返回void的方法中没有return语句,那么在该方法的结尾处会有一个隐式的return,因此在方法中并非总是要有一个return语句。但是,如果一个方法声明它将返回void之外的其他东西,那么必须确保每一条代码路径都将返回一个值。
5. break和continue
    在任何迭代语句的主体部分,都可用break和continue控制循环的流程。其中,break用于强行退出循环,不执行循环中剩余的语句。而continue则停止执行当前的迭代,然后退回循环起始处,开始下一次迭代。

例子:
public class BreakAndContinue {
    public static void main(String[] args) {
//        for (int i = 0; i < 100; i++) {
//            if (i == 74) break;
//            if(i%9 != 0) continue;
//            System.out.print(i + " ");
//        }
        int i = 0;
        while (true) {
            i++;
            int j = i * 27;
            if(j == 1269) break;
            if(j % 10 != 0) continue;
            System.out.print(i + " ");
        }
    }
    for的结果
    /**
     * 0 9 18 27 36 45 54 63 72
     */

    //while 的结果
    /**
     * 10 20 30 40 
     */
}

    在这个for循环中,i的值永远不会达到100;因为一旦i达到74,break语句就会中断循环。通常,只有在不知道中断条件何时满足时,才需要这样使用break。只要i不能被9整除,continue语句就会使执行过程返回到循环的最开头(这使i值递增)。如果能够整除,则将值显示出来。
    最后,可以看到一个“无穷while循环”的情况。然而,循环内部有一个break语句,可中止循环。除此之外,大家还会看到continue语句执行序列移回道循环的开头,而没有去完成continue语句之后的所有内容。(只有在i值能被10整除时才打印出值),输出结果之所以显示0是因为0%9等于0。
    无穷循环的第二种形式是for(; ;)。编译器将while(true)与for(; ;)看作是同一回事。所以具体使用选用哪个取决于自己的编程习惯。
6. switch
    switch有时也被划归为一种选择语句。根据整数表达式的值,switch语句可以从一系列代码中选出一段去执行。它的格式为:

switch(integral-selector){
    case integral-value1 : statement; break;
    case integral-value2 : statement; break;
    case integral-value3 : statement; break;
    case integral-value4 : statement; break;
    case integral-value5 : statement; break;
    //...
    default: statement;
}

    其中,integral-selector(整数选择因子)是一个能够产生整数值的表达式,switch能将这个表达式的结果与每个integral-value(整数值)相比较。若发现相符,就执行对应的语句(单一语句或多条语句,其中并不需要括号)。若没有发现相符的,就执行default(默认)语句。
    在上面的定义中,大家会注意到每个case均以一个break结尾,这样可使执行流程跳转到switch主体的末尾。这是构建switch语句的一种传统形式,但break是可选的。若省略break,会继续执行后面的case语句,直到遇到一个break为止。尽管通常不想出现这种情况,但对有经验的程序员而言,也许能善加利用这种情况。注意最后的default语句没有break,因为执行流程已到了break的跳转目的地。当然,为了考虑到编程风格的原因,完全可以在default语句的末尾放置一个break,尽管它并没有任何实际的用处。
    switch语句是实现多路选择(也就是说从一系列执行路径中挑选一个)的一种干净利落的方法。但它要求使用一个选择因子,并且必须是int或char那样的整数值。例如:假若将一个字符串或者浮点数作为选择因子使用,那么它们在switch语句里是不会工作的。对于非整数类型,则必须使用一系列if语句。

例子:可随机生成字母,并判断它们是元音还是辅音字母。
public class VowelsAndConsonants {
  public static void main(String[] args) {
    Random rand = new Random(47);
    for(int i = 0; i < 100; i++) {
      int c = rand.nextInt(26) + 'a';
      printnb((char)c + ", " + c + ": ");
      switch(c) {
        case 'a':
        case 'e':
        case 'i':
        case 'o':
        case 'u': print("vowel");
                  break;
        case 'y':
        case 'w': print("Sometimes a vowel");
                  break;
        default:  print("consonant");
      }
    }
  }
} /* Output:
    y, 121: Sometimes a vowel
    n, 110: consonant
    z, 122: consonant
    b, 98: consonant
    r, 114: consonant
    n, 110: consonant
    y, 121: Sometimes a vowel
    g, 103: consonant
    c, 99: consonant
    f, 102: consonant
    o, 111: vowel
    w, 119: Sometimes a vowel
    z, 122: consonant
    ...
    */

    由于Rondom.nextInt(26)会产生0~26之间的一个值,所以在其上加上一个偏移量‘a’,即可产生小写字母。在case语句中,使用单引号引起的字符也会产生用于比较的整数值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值