系列中的上一篇
当前教程
控制流语句
系列中的下一篇

系列中的上一篇: 表达式、语句和块

系列中的下一篇: 使用 switch 语句进行分支

控制流语句

 

if-then 语句

if-then 语句是最基本的控制流语句之一。它告诉你的程序仅当特定测试评估为 true 时才执行代码的特定部分。例如,Bicycle 类可以仅当自行车已在运动时才允许制动器降低自行车的速度。applyBrakes() 方法的一种可能的实现如下所示

void applyBrakes() {
    // the "if" clause: bicycle must be moving
    if (isMoving){
        // the "then" clause: decrease current speed
        currentSpeed--;
    }
}

如果此测试评估为 false(表示自行车未在运动),则控制将跳转到 if-then 语句的末尾。

此外,如果“then”子句仅包含一个语句,则可以省略开括号和闭括号

void applyBrakes() {
    // same as above, but without braces
    if (isMoving)
        currentSpeed--;
}

决定何时省略括号是个人喜好问题。省略它们可能会使代码更脆弱。如果稍后将第二个语句添加到“then”子句中,一个常见的错误是忘记添加新需要的括号。编译器无法捕获这种错误;你只会得到错误的结果。

 

if-then-else 语句

if-then-else 语句在“if”子句评估为 false 时提供第二条执行路径。你可以在 applyBrakes() 方法中使用 if-then-else 语句,以便在自行车未在运动时应用制动器时采取一些措施。在这种情况下,该操作只是打印一条错误消息,指出自行车已经停止。

void applyBrakes() {
    if (isMoving) {
        currentSpeed--;
    } else {
        System.err.println("The bicycle has already stopped!");
    }
}

以下程序 IfElseDemo 根据测试分数的值分配等级:90% 或更高的分数为 A,80% 或更高的分数为 B,依此类推。

class IfElseDemo {
    public static void main(String[] args) {

        int testscore = 76;
        char grade;

        if (testscore >= 90) {
            grade = 'A';
        } else if (testscore >= 80) {
            grade = 'B';
        } else if (testscore >= 70) {
            grade = 'C';
        } else if (testscore >= 60) {
            grade = 'D';
        } else {
            grade = 'F';
        }
        System.out.println("Grade = " + grade);
    }
}

程序的输出为

Grade = C

你可能已经注意到,testscore 的值可以满足复合语句中的多个表达式:76 >= 7076 >= 60。但是,一旦满足条件,就会执行相应的语句(grade = 'C';),并且不会评估其余条件。

 

while 和 do-while 语句

while 语句在特定条件为 true 时不断执行语句块。它的语法可以表示为

while (expression) {
     statement(s)
}

while 语句评估表达式,该表达式必须返回 boolean 值。如果表达式评估为 true,则 while 语句执行 while 块中的 statement(s)while 语句继续测试表达式并执行其块,直到表达式评估为 false 为止。使用 while 语句打印从 1 到 10 的值可以像以下 WhileDemo 程序中那样完成

class WhileDemo {
    public static void main(String[] args){
        int count = 1;
        while (count < 11) {
            System.out.println("Count is: " + count);
            count++;
        }
    }
}

你可以使用 while 语句实现无限循环,如下所示

while (true){
    // your code goes here
}

Java 编程语言还提供 do-while 语句,它可以表示为

do {
     statement(s)
} while (expression);

do-whilewhile 之间的区别在于,do-while 在循环底部而不是顶部评估其表达式。因此,do 块中的语句始终至少执行一次,如以下 DoWhileDemo 程序所示

class DoWhileDemo {
    public static void main(String[] args){
        int count = 1;
        do {
            System.out.println("Count is: " + count);
            count++;
        } while (count < 11);
    }
}

 

for 语句

for 语句提供了一种紧凑的方式来迭代一系列值。程序员通常将其称为“for 循环”,因为它是以重复循环直到满足特定条件的方式来实现的。for 语句的一般形式可以表示为

for (initialization; termination; increment) {
    statement(s)
}

使用此版本的 for 语句时,请记住

  • 初始化表达式初始化循环;它在循环开始时执行一次。
  • 终止表达式评估为 false 时,循环终止。
  • 增量表达式在每次循环迭代后调用;此表达式可以增量减量值,这完全可以接受。

以下程序 ForDemo 使用 for 语句的一般形式将数字 1 到 10 打印到标准输出

class ForDemo {
    public static void main(String[] args){
         for(int i = 1; i < 11; i++){
              System.out.println("Count is: " + i);
         }
    }
}

此程序的输出为

Count is: 1
Count is: 2
Count is: 3
Count is: 4
Count is: 5
Count is: 6
Count is: 7
Count is: 8
Count is: 9
Count is: 10

请注意代码如何在初始化表达式中声明一个变量。此变量的作用域从其声明扩展到 for 语句控制的块的末尾,因此它也可以在终止和增量表达式中使用。如果控制 for 语句的变量在循环外部不需要,最好在初始化表达式中声明该变量。名称 ijk 通常用于控制 for 循环;在初始化表达式中声明它们会限制它们的生命周期并减少错误。

for 循环的三个表达式是可选的;可以创建无限循环,如下所示

// infinite loop
for ( ; ; ) {

    // your code goes here
}

for 语句还有另一种形式,专为迭代集合和数组而设计。这种形式有时称为增强 for 语句,可用于使你的循环更紧凑且易于阅读。为了演示,请考虑以下数组,它包含数字 1 到 10

int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

以下程序 EnhancedForDemo 使用增强 for 循环遍历数组

class EnhancedForDemo {
    public static void main(String[] args){
         int[] numbers =
             {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
         for (int item : numbers) {
             System.out.println("Count is: " + item);
         }
    }
}

在此示例中,变量 item 保存来自 numbers 数组的当前值。此程序的输出与之前相同

Count is: 1
Count is: 2
Count is: 3
Count is: 4
Count is: 5
Count is: 6
Count is: 7
Count is: 8
Count is: 9
Count is: 10

我们建议尽可能使用这种形式的 for 语句,而不是使用一般形式。

 

break 语句

break 语句有两种形式:带标签和不带标签。你在之前关于 switch 语句的讨论中看到了不带标签的形式。你还可以使用不带标签的 break 来终止 forwhiledo-while 循环,如以下 BreakDemo 程序所示

class BreakDemo {
    public static void main(String[] args) {

        int[] arrayOfInts =
            { 32, 87, 3, 589,
              12, 1076, 2000,
              8, 622, 127 };
        int searchfor = 12;

        int i;
        boolean foundIt = false;

        for (i = 0; i < arrayOfInts.length; i++) {
            if (arrayOfInts[i] == searchfor) {
                foundIt = true;
                break;
            }
        }

        if (foundIt) {
            System.out.println("Found " + searchfor + " at index " + i);
        } else {
            System.out.println(searchfor + " not in the array");
        }
    }
}

此程序在数组中搜索数字 12。break 语句在找到该值时终止 for 循环。然后控制流将转移到 for 循环之后的语句。此程序的输出为

Found 12 at index 4

不带标签的 break 语句终止最内层的 switchforwhiledo-while 语句,但带标签的 break 语句终止外部语句。以下程序 BreakWithLabelDemo 与之前的程序类似,但使用嵌套的 for 循环在二维数组中搜索值。找到该值后,带标签的 break 会终止外部 for 循环(标记为“search”)

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

这是程序的输出。

Found 12 at 1, 0

break 语句终止带标签的语句;它不会将控制流转移到标签。控制流将转移到带标签(终止)语句之后的语句。

 

continue 语句

continue 语句跳过 forwhiledo-while 循环的当前迭代。不带标签的形式跳过最内层循环主体末尾,并评估控制循环的布尔表达式。以下程序 ContinueDemo 遍历 String,计算字母 p 的出现次数。如果当前字符不是 p,则 continue 语句跳过循环的其余部分并继续下一个字符。如果是 p,则程序会增加字母计数。

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++) {
            // interested only in p's
            if (searchMe.charAt(i) != 'p')
                continue;

            // process p's
            numPs++;
        }
        System.out.println("Found " + numPs + " p's in the string.");
    }
}

以下是此程序的输出

Found 9 p's in the string.

为了更清楚地看到这种效果,请尝试删除 continue 语句并重新编译。当你再次运行程序时,计数将不正确,显示它找到了 35 个 p,而不是 9 个。

带标签的 continue 语句跳过用给定标签标记的外部循环的当前迭代。以下示例程序 ContinueWithLabelDemo 使用嵌套循环在另一个字符串中搜索子字符串。需要两个嵌套循环:一个用于迭代子字符串,另一个用于迭代要搜索的字符串。以下程序 ContinueWithLabelDemo 使用 continue 的带标签的 test 来跳过外部循环中的迭代。

class ContinueWithLabelDemo {
    public static void main(String[] args) {

        String searchMe = "Look for a substring in me";
        String substring = "sub";
        boolean foundIt = false;

        int max = searchMe.length() -
                  substring.length();

    test:
        for (int i = 0; i <= max; i++) {
            int n = substring.length();
            int j = i;
            int k = 0;
            while (n-- != 0) {
                if (searchMe.charAt(j++) != substring.charAt(k++)) {
                    continue test;
                }
            }
            foundIt = true;
                break test;
        }
        System.out.println(foundIt ? "Found it" : "Didn't find it");
    }
}

以下是此程序的输出。

Found it

 

return 语句

下一个分支语句是 return 语句。return 语句退出当前方法,控制流返回到调用该方法的位置。return 语句有两种形式:一种返回一个值,另一种不返回。要返回一个值,只需在 return 关键字之后加上该值(或计算该值的表达式)。

return ++count;

返回的值的数据类型必须与方法声明的 return 值的类型匹配。当方法声明为 void 时,请使用不返回值的 return 形式。

return;

类和对象部分将涵盖编写方法所需的一切知识。

 

yield 语句

最后一个分支语句是 yield 语句。yield 语句退出它所在的当前 switch 表达式。yield 语句后面始终是一个表达式,该表达式必须产生一个值。此表达式不能是 void。此表达式的值是封闭 switch 表达式产生的值。

以下是一个 yield 语句的示例。

class Test {
    enum Day {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
    }

    public int calculate(Day d) {
        return switch (d) {
            case SATURDAY, SUNDAY -> 0;
                default -> {
                    int remainingWorkDays = 5 - d.ordinal();
                    yield remainingWorkDays;
                }
            };
    }
}

最后更新: 2021 年 9 月 22 日


系列中的上一篇
当前教程
控制流语句
系列中的下一篇

系列中的上一篇: 表达式、语句和块

系列中的下一篇: 使用 switch 语句进行分支