控制执行流程

本文深入讲解Java中的流程控制语句,包括if-else、while、do-while、for、return、break、continue及switch等关键字的使用方法。通过具体实例演示了如何运用这些语句来控制程序的执行路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第4章 控制执行流程

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

在Java中,流程控制所涉及的关键字包括:if-else、while、do-while、for、return、break以及选择语句switch。然而,Java并不支持goto语句,但仍然可进行类似goto的跳转,不过相比goto有了更多限制。。

4.1 true和false

所有条件语句都利用条件表达式的真或假来决定执行路径。所有的关系操作符都可用于构造条件语句,其结果为一个布尔值。如果在布尔测试中使用一个非布尔值,那么必须用一个条件表达式将其转换成布尔值。

4.2 if-else

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

    if(Boolean-expression)
        statement

或
    if(Boolean-expression)
        statement
    else
        statement

布尔表达式必须产生一个布尔结果,statement指用分号结尾的简单语句或复合语句(封闭在花括号内的一组简单语句)。

通过下例,我们可以更清楚地了解if-else的使用:

public class IfElse {
    static int result = 0;

    static void test(int testval, int target) {
        if (testval > target)
            result = 1;
        else if (testval < target)
            result = -1;
        else
            result = 0;
    }

    public static void main(String[] args) {
        test(10, 5);
        print(result);
        test(5, 10);
        print(result);
        test(5, 5);
        print(result);
    }
}

在test()方法中的 else if 并非新的关键字,其仅仅是在else后紧跟了另一个新的if-else语句。

尽管Java是格式自由的语言,但为了更加方便地确定起始与终止,还是将流程控制语句的主体部分进行缩进排列。

4.3 迭代

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

while循环在刚开始会计算一次布尔表达式的值,在语句的下一次迭代前会再次计算,格式如下:

while(Boolean-expression)
    statement

下面的例子可一直产生随机数,直到符合特定条件为止:

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

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

上例使用了Math库里的静态方法random(),可产生0和1之间的一个double值。while的条件表达式表示的意思为:只要condition()返回的为true,即result为true,即产生的随机数小于0.99,就重复执行循环体中的语句。

4.3.1 do-while

do-while的格式如下:

do
    statement
while(Boolean-expression);

从格式可以看出,do-while比while少进行一次表达式计算,即do-while循环体中的语句至少会执行一次。

4.3.2 for

for循环可能是最经常使用的迭代形式,其在第一次迭代前需进行初始化,随后进行条件测试,并且在每次迭代结束后,进行步进。 for循环格式如下:

for(initialization; Boolean-expression; step)
    statement

for循环常用于执行计数任务:

public class ListCharacters {
    public static void main(String[] args) {
        for (char c = 0; c < 128; c++) {
            if (Character.isLowerCase(c)) {
                System.out.println("value: " + (int) c + " Character: " + c);
            }
        }
    }
}

注意,Java是在整个块的范围内分散变量声明,在真正需要的地方加以定义。变量c在for循环的控制表达式里被定义,所以它的作用域就是for控制的表达式的范围内。

4.3.3 逗号操作符

在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);
        }
    }
}

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

4.4 Foreach语法

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

例如,我们需要选取一个float数组中每一个元素:

public class ForEachFloat {
    public static void main(String[] args) {
        Random random = new Random(66);
        float f[] = new float[10];
        for (int i = 0; i < f.length; i++) {
            f[i] = random.nextFloat();
        }
        for (float x : f) {
            System.out.println(x);
        }
    }
} 

由于在组装数组时,必须按索引访问,所以,我们一般使用for循环进行组装数组,使用foreach进行遍历数组。我们可以看到foreach语法为:

for(float x : f)
    statement

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

任何返回一个数组的方法都可以使用foreach。range()方法为自定义类Range中的静态方法,它可以自动生成恰当的数组:

public class ForEachInt {
    public static void main(String[] args) {
        for (int i : range(10))
            printnb(i + " ");
        print();
        for (int i : range(5, 10))
            printnb(i + " ");
        print();
        for (int i : range(5, 20, 3))
            printnb(i + " ");
        print();

    }
}

foreach语法不仅在录入代码时可以节省时间,而且容易阅读。

4.5 return

在Java中有多个关键词表示无条件分支,它们只是表示这个分支无需任何测试即可发生。这些关键字包括:return、break、continue。

return关键词有两方面的用途:

  • 指定一个方法的返回值。
  • 导致当前方法退出,并返回那个值。

我们可以通过使用return改写前面的test()方法:

public class IfElse2 {
    static int test(int testval, int target) {
        if (testval > target)
            return 1;
        else if (testval < target)
            return -1;
        else
            return 0;
    }

    public static void main(String[] args) {
        print(test(10, 5));
        print(test(5, 10));
        print(test(5, 5));
    }
}

对于方法返回值类型的不同,return语句有不同的限制:

  • 返回值类型为void,即使不写return,在方法的结尾处也会有一个隐式的return。

  • 返回值类型不是void,那么必须确保每一条代码路径都将返回一个该类型的值。

4.6 break和continue

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

  • break:强行退出循环,不执行循环中剩余部分的语句。
  • continue:停止当前的迭代,退回循环起始处,开始下一次迭代。

下例展示了break和continue在for和while循环中的作用:

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 + " ");
        }
        System.out.println();
        for (int i : range(100)) {
            if (i == 74)    break;
            if (i % 9 != 0) continue;
            System.out.print(i + " ");
        }
        System.out.println();
        int i = 0;
        while(true){
            i ++;
            int j = i * 27;
            if(j == 1269)   break;
            if(i % 10 != 0) continue;
            System.out.print(i + " ");
        }
    }
}

在for循环中,一旦i到达74,break语句就会中断循环。只要i不能被9整除,continue语句就会结束本次循环,直到能够整除时将值打印出来。

在while循环中的条件始终为true,我们称其为无限循环,循环内部有一个break可中断循环。

4.7 臭名昭著的goto

goto起源于汇编语言的程序控制:若条件A成立,跳转至这里,否则跳转到那里。 通过阅读由编译器最终生成的汇编代码,可以发现程序控制里包含了许多跳转。(Java编译器生成它自己的汇编代码,运行在Java虚拟机上而非直接运行在CPU硬件上。)

Java没有goto,但可以通过break和continue完成类似跳转的操作。实际上它们不是跳转,而是中断迭代语句的一种方式。它们和goto的相同之处在于,都使用了标签

标签是后面跟有冒号的标识符:

label:

在Java中,标签起作用的唯一的地方就是迭代语句之前,用于在一个迭代语句中嵌套另一个迭代或者一个开关。

下面是标签用于for循环的例子:

public class LabeledFor {
    public static void main(String[] args) {
        int i = 0;
        outer:
        for (; ; ) {
            inner:
            for (; i<10; i++) {
                System.out.println("i = " + i);
                if(i == 2 ){
                    System.out.println("continue");
                    continue;
                }
                if(i == 3 ){
                    System.out.println("break");
                    i++;
                    break;
                }
                if(i == 7 ){
                    System.out.println("continue outer");
                    i++;
                    continue outer;
                }
                if(i == 8 ){
                    System.out.println("break outer");
                    break outer;
                }
                for (int k = 0; k < 5; k++) {
                    if(k == 3){
                        System.out.println("continue inner");
                        continue inner;
                    }
                }
            }
        }
    }
}

在使用标签后,break和continue分别的作用为:

  • break label:结束标签为label的循环语句。
  • continue label:停止标签为label的本次循环,跳到该循环的起始处,开始下一次循环。

注意,在抵达for循环末尾之前,递增表达式不会执行。

下面的例子展示了带标签的break以及continue语句在while循环中的用法:

public class LabeledWhile {
    public static void main(String[] args) {
        int i = 0;
        outer: 
        while(true){
            System.out.println("Outer while loop");
            while(true){
                i++;
                System.out.println("i = " + i);
                if (i == 1) {
                    System.out.println("continue");
                    continue;
                }
                if (i == 3) {
                    System.out.println("continue outer");
                    continue outer;
                }
                if (i == 5) {
                    System.out.println("break");
                    break;
                }
                
                if (i == 7) {
                    System.out.println("break outer");
                    break outer;
                }
            }
        }
    }
}

break与continue小结:

  • 一般的continue会退回最内层循环的开头,并继续执行。
  • 带标签的continue会到达标签位置,并重新进入标签后的循环。
  • 一般的break会中断并跳出当前循环。
  • 带标签的break会中断并跳出标签所指的循环。

在Java中需要使用标签的唯一原因就是:对多层循环嵌套进行控制。

4.8 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是可选的:

  • 以break结尾,可以使执行流程跳转至switch主体的末尾。
  • 省略break,则会继续执行后面的case语句,直到遇到break或执行到default语句。
  • default语句后是否省略break,switch语句在执行完default后都会结束。

switch语句是实现多路选择的一种干净利落的方法,限制是选择因子必须为整数值。但Java SE5的新特性enum也可以和switch协调工作。

下面的例子可随机生成字母,并判断它们是元音还是辅音字母:

public class VowelsAndConsonants {
    public static void main(String[] args) {
        Random rand = new Random(66);
        for (int i = 0; i < 100; i++) {
            int c = rand.nextInt(26) + 'a';
            System.out.print((char) c + ", " + c + ": ");
            switch (c) {
                case 'a':
                case 'e':
                case 'i':
                case 'o':
                case 'u':
                    System.out.println("vowel");
                    break;
                case 'y':
                case 'w':
                    System.out.println("Sometimes a vowel");
                    break;
                default:
                    System.out.println("consonant");
                    break;
            }
        }
    }
}

在case语句中,使用单引号引起的字符也会产生用于比较的整数值。

从上例中可以看出,case语句能够堆叠在一起,为一段代码形成多重匹配,即只要符号多种条件的一种,就执行那段特别的代码。

4.9 总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值