跳转到内容

循环块

100% developed
来自维基教科书,开放的书籍,为开放的世界


导航 语言基础 主题: v  d  e )


循环是一种便捷的工具,使程序员能够以最少的努力完成重复的任务。假设我们想要一个可以从 1 到 10 计数的程序,我们可以编写 以下程序

Computer code 代码清单 3.4:Count.java
class Count {
    public static void main(String[] args) {
        System.out.println("1 ");
        System.out.println("2 ");
        System.out.println("3 ");
        System.out.println("4 ");
        System.out.println("5 ");
        System.out.println("6 ");
        System.out.println("7 ");
        System.out.println("8 ");
        System.out.println("9 ");
        System.out.println("10 ");
    }
}
Standard input or output 代码清单 3.4 的输出
1
2
3
4
5
6
7
8
9
10


任务将顺利完成,数字 1 到 10 将在输出中打印,但此解决方案存在一些问题。

  • 灵活性:如果我们想更改起始数字或结束数字怎么办?我们必须遍历并更改它们,在需要的地方添加额外的代码行。
  • 可扩展性:10 次重复是微不足道的,但如果我们想要 100 次甚至 1000 次重复怎么办?对于大量迭代,所需的代码行数将非常多。
  • 维护性:代码量大时,更容易出错。
  • 特性:任务数量是固定的,不会在每次执行时改变。

使用循环,我们可以解决所有这些问题。一旦你掌握了它们,它们将成为解决编程中许多问题的宝贵工具。

打开你的编辑程序,创建一个名为 Loop.java 的新文件。现在输入或复制 以下代码

Computer code 代码清单 3.5:Loop.java
class Loop {
    public static void main(String[] args) {
        int i;
        for (i = 1; i <= 10; i++) {
            System.out.println(i + " ");
        }
    }
}
Standard input or output 代码清单 3.5 的输出
1
2
3
4
5
6
7
8
9
10

如果我们运行该程序,将产生相同的结果,但查看代码,我们立即看到了循环的优势。而不是执行十行不同的代码,第 5 行执行十次。十行代码已经减少到只有四行。此外,我们可以将数字 10 更改为我们喜欢的任何数字。自己试试,将 10 替换为你自己的数字。

while 循环是最简单的循环形式。while 循环重复执行代码块,直到指定的条件为真。以下是一个 while 循环的结构。

while (布尔表达式1) {
语句1
语句2
...
语句n

}

在每次循环迭代之前,都会检查循环的条件。如果在循环开始时条件为假,则循环将不会执行。在 代码部分 3.28 中,squareHigherThan200 设置了平方大于 200 的最小整数。

Example 代码部分 3.28:平方大于 200 的最小整数。
int squareHigherThan200 = 0;

while (squareHigherThan200 * squareHigherThan200 < 200) {
  squareHigherThan200 = squareHigherThan200 + 1;
}
Note 如果循环的条件永远不会变为假,例如,如果使用 true 常量作为条件,则该循环被称为无限循环。这样的循环会无限期地重复,除非它被 break 语句中断。无限循环可以用来执行需要不断重复而不确定停止点的任务,例如更新图形显示。

Do... while

[编辑 | 编辑源代码]

do-while 循环的功能类似于 while 循环,只是条件是在语句执行之后才评估的。当我们尝试通过随机浏览一组数据来查找起作用的数据时,它非常有用。

do {
语句1
语句2
...
语句n

} while (布尔表达式1);

for 循环是一个专门的 while 循环,其语法旨在方便地遍历数字序列。它由关键字 for 以及括号中包含的三个额外语句组成。第一个语句是变量声明语句,它允许你声明一个或多个整型变量。第二个是条件,其检查方式与 while 循环相同。最后一个是迭代语句,用于递增或递减变量,尽管任何语句都是允许的。

这是一个 for 循环的结构。

for (变量声明; 条件; 迭代语句) {
语句1
语句2
...
语句n

}

为了说明如何使用 for 循环,以下是一个示例。

Example 代码部分 3.29:一个 for 循环。
for (int i = 1; i <= 10; i++) {
    System.out.println(i);
}
Standard input or output 代码清单 3.29 的输出
1
2
3
4
5
6
7
8
9
10

for 循环就像 while 循环的模板版本。使用 while 循环的替代代码如下:

Example 代码部分 3.30:使用 while 循环的迭代。
int i = 1;
while (i <= 10) {
  System.out.println(i);
  i++;
}

代码部分 3.31 中,展示了如何使用多个变量使用 for 循环进行迭代,而 代码部分 3.32 展示了如何跳过 for 循环的任何参数。跳过所有参数,你就会得到一个无限循环。

Example 代码部分 3.31:使用多个变量的 for 循环。
for (int i = 1, j = 10; i <= 10; i++, j--) {
  System.out.print(i + " ");
  System.out.println(j);
}
Example 代码部分 3.32:没有参数的 for 循环。
for (;;) {
  // Some code
}

数组 还没有讲到,但你会想知道如何使用增强 for 循环,称为 for-each 循环。for-each 循环会自动遍历列表或数组,并将每个索引的值分配给一个变量。

要了解 for-each 循环的结构,请查看以下示例。

Example 代码部分 3.33:一个 for-each 循环。
String[] sentence = {"I", "am", "a", "Java", "program."};
for (String word : sentence) {
    System.out.print(word + " ");
}
Standard input or output 代码部分 3.33 的输出
I am a Java program.

该示例遍历了一个单词数组,并将它们像句子一样打印出来。循环所做的事情是遍历 sentence,并将每个索引的值分配给 word,然后执行代码块。

以下是 for-each 循环的一般约定。

for (变量声明 : 数组或列表) {
语句1
语句2
...
语句n

}

确保数组或列表的类型可以分配给声明的变量,否则你会遇到编译错误。注意,循环会在检查完集合中的最后一个项目后自动退出语句块。

虽然增强 for 循环可以使代码更清晰,但它不能用于一些常见情况。

  • 只能访问。 元素不能被赋值,例如,不能递增集合中的每个元素。
  • 只能单个结构。 无法同时遍历两个结构,例如,比较两个数组。
  • 只能单个元素。 仅用于访问单个元素,例如,不能比较连续的元素。
  • 只能向前。 只能按单步向前迭代。
  • 至少 Java 5。 如果需要与 Java 5 之前的版本兼容,请不要使用它。

Break 和 continue 关键字

[编辑 | 编辑源代码]

break 关键字退出流程控制循环,例如 for 循环。它基本上是中断循环。

代码部分 3.34 中,循环将打印出从 1 到 10 的所有数字,但我们有一个检查,当 i 等于 5 时会执行。当循环到达第五次迭代时,它将被 break 语句中断,此时它将退出循环。

Example 代码部分 3.34:一个被中断的 for 循环。
for (int i = 1; i <= 10; i++) {
    System.out.println(i);
    if (i == 5) {
       System.out.println("STOP!");
       break;
    }
}
Standard input or output 代码部分 3.34 的输出
1
2
3
4
5
STOP!

continue 关键字直接跳转到循环的下一个迭代,并评估控制循环的布尔表达式。 代码部分 3.35continue 语句在实际应用中的示例

Example 代码部分 3.35:带有跳过迭代的 for 循环。
for (int i = 1; i <= 10; i++) {
    if (i == 5) {
        System.out.println("Caught i == 5");
        continue;
    }
    System.out.println(i);
}
Standard input or output 代码部分 3.35 的输出
1
2
3
4
Caught i == 5
6
7
8
9
10

由于 breakcontinue 语句会降低代码的可读性,建议减少使用它们,或用 ifwhile 块替换它们。由于这些语句的存在,一些 IDE 重构操作可能会失败。

测试你的知识

问题 3.2:考虑以下代码

Example 问题 3.2:循环和条件。
int numberOfItems = 5;
int currentItems = 0;
int currentCandidate = 1;

while (currentItems < numberOfItems) {
  currentCandidate = currentCandidate + 1;
  System.out.println("Test with integer: " + currentCandidate);
 
  boolean found = true;
  for (int i = currentCandidate - 1; i > 1; i--) {
   
    // Test if i is a divisor of currentCandidate
    if ((currentCandidate % i) == 0) {
      System.out.println("Not matching...");
      found = false;
      break;
    }
   
  }
 
  if (found) {
    System.out.println("Matching!");
    currentItems = currentItems + 1;
  }
}

System.out.println("Find the value: " + currentCandidate);

标准输出中将打印什么?

答案
Standard input or output 问题 3.2 的输出
Test with integer: 2
Matching!
Test with integer: 3
Matching!
Test with integer: 4
Not matching...
Test with integer: 5
Matching!
Test with integer: 6
Not matching...
Test with integer: 7
Matching!
Test with integer: 8
Not matching...
Test with integer: 9
Not matching...
Test with integer: 10
Not matching...
Test with integer: 11
Matching!
Find the value: 11

这段代码片段正在搜索第 5 个 质数,也就是:11。它迭代从 2 开始的每个正整数(2、3、4、5、6、7、8、9、10、11...),其中,它统计质数(2、3、5、7、11)并在第 5 个质数处停止。

因此,代码片段首先使用 while 循环迭代从 2 开始的每个正整数

Example 答案 3.2.1:while 循环。
int numberOfItems = 5;
int currentItems = 0;
int currentCandidate = 1;

while (currentItems < numberOfItems) {
  currentCandidate = currentCandidate + 1;
  System.out.println("Test with integer: " + currentCandidate);
 
  boolean found = true;
  for (int i = currentCandidate - 1; i > 1; i--) {
   
    // Test if i is a divisor of currentCandidate
    if ((currentCandidate % i) == 0) {
      System.out.println("Not matching...");
      found = false;
      break;
    }
   
  }
 
  if (found) {
    System.out.println("Matching!");
    currentItems = currentItems + 1;
  }
}

System.out.println("Find the value: " + currentCandidate);

对于每一次迭代,当前数字要么是质数,要么不是。如果是质数,则执行左侧的代码。如果不是质数,则执行右侧的代码。

Example 答案 3.2.2:一个质数。
int numberOfItems = 5;
int currentItems = 0;
int currentCandidate = 1;

while (currentItems < numberOfItems) {
  currentCandidate = currentCandidate + 1;
  System.out.println("Test with integer: " + currentCandidate);
 
  boolean found = true;
  for (int i = currentCandidate - 1; i > 1; i--) {
   
    // Test if i is a divisor of currentCandidate
    if ((currentCandidate % i) == 0) {
      System.out.println("Not matching...");
      found = false;
      break;
    }
   
  }
 
  if (found) {
    System.out.println("Matching!");
    currentItems = currentItems + 1;
  }
}

System.out.println("Find the value: " + currentCandidate);
Example 答案 3.2.3:不是一个质数。
int numberOfItems = 5;
int currentItems = 0;
int currentCandidate = 1;

while (currentItems < numberOfItems) {
  currentCandidate = currentCandidate + 1;
  System.out.println("Test with integer: " + currentCandidate);
 
  boolean found = true;
  for (int i = currentCandidate - 1; i > 1; i--) {
   
    // Test if i is a divisor of currentCandidate
    if ((currentCandidate % i) == 0) {
      System.out.println("Not matching...");
      found = false;
      break;
    }
   
  }
 
  if (found) {
    System.out.println("Matching!");
    currentItems = currentItems + 1;
  }
}

System.out.println("Find the value: " + currentCandidate);


质数使用 currentItems 计数。当 currentItems 等于 numberOfItems(5)时,程序退出 while 循环。currentCandidate 包含最后一个数字,也就是第 5 个质数

Example 答案 3.2.4:程序结束。
int numberOfItems = 5;
int currentItems = 0;
int currentCandidate = 1;

while (currentItems < numberOfItems) {
  currentCandidate = currentCandidate + 1;
  System.out.println("Test with integer: " + currentCandidate);
 
  boolean found = true;
  for (int i = currentCandidate - 1; i > 1; i--) {
   
    // Test if i is a divisor of currentCandidate
    if ((currentCandidate % i) == 0) {
      System.out.println("Not matching...");
      found = false;
      break;
    }
   
  }
 
  if (found) {
    System.out.println("Matching!");
    currentItems = currentItems + 1;
  }
}

System.out.println("Find the value: " + currentCandidate);

标签

[edit | edit source]

标签可用于为循环命名。这样做的原因是,我们可以从嵌套循环中退出或继续上级循环。

以下是为循环添加标签的方法

标签名称:循环

要退出或继续循环,请使用 breakcontinue 关键字,后面跟着循环的名称。

例如

Example 代码部分 3.36:一个双重 for 循环。
int i, j;
int[][] nums = {
    {1, 2, 5},
    {6, 9, 7},
    {8, 3, 4}
};

Outer:
for (i = 0; i < nums.length; i++) {
    for (j = 0; j < nums[i].length; j++) {
        if (nums[i][j] == 9) {
            System.out.println("Found number 9 at (" + i + ", " + j + ")");
            break Outer;
        }
    }
}
Standard input or output 代码部分 3.36 的输出
Found number 9 at (1, 1)

如果你不理解所有代码,也不用担心,但请注意标签是如何用于从内循环退出外循环的。但是,由于这种代码难以阅读和维护,强烈建议不要使用标签。

尝试... 捕获块

[edit | edit source]
另请参阅 抛出和捕获异常

try-catch 块用于捕获代码中的任何异常或其他可抛出对象。

以下是 try-catch 块的样子

try {
statement1.1
statement1.2
...
statement1.n

} catch (exception1) {

statement2.1
...
statement2.n

}

代码清单 3.6 尝试打印传递给程序的所有参数。但是,如果参数不足,它将抛出异常。

Computer code 代码清单 3.6:Attempt.java
public class Attempt {
  public static void main(String[] args) {
    try {
      System.out.println(args[0]);
      System.out.println(args[1]);
      System.out.println(args[2]);
      System.out.println(args[3]);
    } catch (ArrayIndexOutOfBoundsException e) {
      System.out.println("Not enough arguments");
    }
  }
}

除了 try 和 catch 块之外,还可以使用 finally 块。无论是否抛出异常,都会始终执行 finally 块。它可以与 catch 块一起出现,也可以不与 catch 块一起出现,但始终与 try 块一起出现。

以下是 finally 块的样子

try {
statement1.1
statement1.2
...
statement1.n

} catch (exception1) {

statement2.1
...
statement2.n

} finally {

statement3.1
...
statement3.n

}

示例

[edit | edit source]

代码清单 3.7 接收一个数字作为参数,并打印它的二进制表示。

Computer code 代码清单 3.7:GetBinary.java
public class GetBinary {
    public static void main(String[] args) {
        if (args.length == 0) {
            // Print usage
            System.out.println("Usage: java GetBinary <decimal integer>");
            System.exit(0);
        } else {
            // Print arguments
            System.out.println("Received " + args.length + " arguments.");
            System.out.println("The arguments are:");
            for (String arg : args) {
                System.out.println("\t" + arg);
            }
        }

        int number = 0;
        String binary = "";

        // Get the input number
        try {
            number = Integer.parseInt(args[0]);
        } catch (NumberFormatException ex) {
            System.out.println("Error: argument must be a base-10 integer.");
            System.exit(0);
        }

        // Convert to a binary string
        do {
            switch (number % 2) {
                case 0: binary = '0' + binary; break;
                case 1: binary = '1' + binary; break;
            }
            number >>= 1;
        } while (number > 0);

        System.out.println("The binary representation of " + args[0] + " is " + binary);
    }
}

代码清单 3.8 模拟玩一个名为幸运七的游戏。这是一个骰子游戏,玩家掷两个骰子。如果骰子上的数字加起来是七,他就赢了 4 美元。如果不是,他就输了 1 美元。这个游戏展示了如何在程序中使用控制流以及赌博的徒劳无益。

Computer code 代码清单 3.8:LuckySevens.java
import java.util.*;

public class LuckySevens {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Random random = new Random();
        String input;
        int startingCash, cash, maxCash, rolls, roll;

        // Loop until "quit" is input
        while (true) {
            System.out.print("Enter the amount of cash to start with (or \"quit\" to quit): ");

            input = in.nextLine();

            // Check if user wants to exit
            if (input.toLowerCase().equals("quit")) {
                System.out.println("\tGoodbye.");
                System.exit(0);
            }

            // Get number
            try {
                startingCash = Integer.parseInt(input);
            } catch (NumberFormatException ex) {
                System.out.println("\tPlease enter a positive integer greater than 0.");
                continue;
            }

            // You have to start with some money!
            if (startingCash <= 0) {
                System.out.println("\tPlease enter a positive integer greater than 0.");
                continue;
            }

            cash = startingCash;
            maxCash = cash;
            rolls = 0;
            roll = 0;

            // Here is the game loop
            for (; cash > 0; rolls++) {
               roll = random.nextInt(6) + 1;
               roll += random.nextInt(6) + 1;

                if (roll == 7)
                    cash += 4;
                else
                    cash -= 1;

                if (cash > maxCash)
                    maxCash = cash;
            }

            System.out.println("\tYou start with $" + startingCash + ".\n"
                    + "\tYou peak at $" + maxCash + ".\n"
      + "\tAfter " + rolls + " rolls, you run out of cash.");
        }
    }
}


华夏公益教科书