Java 7 的 switch 选择器不但可以使用整数值,还添加了使用字符串的能力。以下示例显示了在一组候选的 String 类型中做出选择的旧方式,以及使用 switch 的新方式:

  1. // control/StringSwitch.java
  2. public class StringSwitch {
  3. public static void main(String[] args) {
  4. String color = "red";
  5. // 旧方式:使用 if-then
  6. if("red".equals(color)) {
  7. System.out.println("RED");
  8. } else if("green".equals(color)) {
  9. System.out.println("GREEN");
  10. } else if("blue".equals(color)) {
  11. System.out.println("BLUE");
  12. } else if("yellow".equals(color)) {
  13. System.out.println("YELLOW");
  14. } else {
  15. System.out.println("Unknown");
  16. }
  17. // 新方式:在switch中使用字符串
  18. switch(color) {
  19. case "red":
  20. System.out.println("RED");
  21. break;
  22. case "green":
  23. System.out.println("GREEN");
  24. break;
  25. case "blue":
  26. System.out.println("BLUE");
  27. break;
  28. case "yellow":
  29. System.out.println("YELLOW");
  30. break;
  31. default:
  32. System.out.println("Unknown");
  33. break;
  34. }
  35. }
  36. }
  37. /* 输出:
  38. RED
  39. RED
  40. */

一旦你理解了 switch,这个语法就是一个逻辑扩展,可以让你的代码更简洁、更易于理解和维护。
作为第二个使用字符串的 switch 例子,让我们重新回顾一下 Math.random()。它是否产生一个 0~1 范围内的值?其中包不包括值 “1”?用数学术语来说,它是 (0,1)、[0,1] 、(0,1]还是[0,1) ?(方括号的意思是 “包括”,圆括号的意思是“不包括”。)
这里有一个可能会提供答案的测试程序。所有命令行参数都是作为字符串对象传递的,因此我们可以将参数作为 switch 的选择器来决定做什么。这里有个问题:用户可能不提供任何参数,因此如果索引 args 数组,则可能会导致程序失败。为了解决这个问题,先检查数组的长度。如果为零,就使用一个空字符串,否则选择 args 数组里的第一个元素:

  1. package onjava;
  2. import java.util.concurrent.*;
  3. public class TimedAbort {
  4. private volatile boolean restart = true;
  5. public TimedAbort(double t, String msg) {
  6. CompletableFuture.runAsync(() -> {
  7. try {
  8. while(restart) {
  9. restart = false;
  10. TimeUnit.MILLISECONDS
  11. .sleep((int)(1000 * t));
  12. }
  13. } catch(InterruptedException e) {
  14. throw new RuntimeException(e);
  15. }
  16. System.out.println(msg);
  17. System.exit(0);
  18. });
  19. }
  20. public TimedAbort(double t) {
  21. this(t, "TimedAbort " + t);
  22. }
  23. public void restart() { restart = true; }
  24. }
  1. // control/RandomBounds.java
  2. // Math.random()能生成0.0和1.0吗
  3. // {java RandomBounds lower}
  4. import onjava.*;
  5. public class RandomBounds {
  6. public static void main(String[] args) {
  7. new TimedAbort(3);
  8. switch(args.length == 0 ? "" : args[0]) {
  9. case "lower":
  10. while(Math.random() != 0.0)
  11. ; // 持续尝试
  12. System.out.println("Produced 0.0!");
  13. break;
  14. case "upper":
  15. while(Math.random() != 1.0)
  16. ; // 持续尝试
  17. System.out.println("Produced 1.0!");
  18. break;
  19. default:
  20. System.out.println("Usage:");
  21. System.out.println("\tRandomBounds lower");
  22. System.out.println("\tRandomBounds upper");
  23. System.exit(1);
  24. }
  25. }
  26. }

如果要运行程序,输入以下任意一条命令:
java RandomBounds lower
或者
java RandomBounds upper
使用 onjava 包中的 TimedAbort 类,程序会在 3 秒后中止,因此看起来 Math.random() 不会生成 0.0 或 1.0。但这正是这种实验可能具有欺骗性的地方。如果你考虑 0~1 范围内双精度浮点数的数量,通过实验生成一个值的可能性会超出一台计算机的使用寿命,甚至是实验者的寿命。其实 0.0 是包含在 Math.random() 的输出中的,而 1.0 没有。用数学术语表示就是 [0,1)。你一定要仔细分析自己的实验并了解它们的局限性。

5.10 总结

本章探索了大多数编程语言具有的基本功能。现在你已经做好了准备,可以开始迈进面向对象和函数式编程的世界了。第 6 章将讨论与对象初始化和清理相关的重要问题,第 7 章则讲解实现隐藏的基本概念。