Java 7 的 switch 选择器不但可以使用整数值,还添加了使用字符串的能力。以下示例显示了在一组候选的 String 类型中做出选择的旧方式,以及使用 switch 的新方式:
// control/StringSwitch.javapublic class StringSwitch {public static void main(String[] args) {String color = "red";// 旧方式:使用 if-thenif("red".equals(color)) {System.out.println("RED");} else if("green".equals(color)) {System.out.println("GREEN");} else if("blue".equals(color)) {System.out.println("BLUE");} else if("yellow".equals(color)) {System.out.println("YELLOW");} else {System.out.println("Unknown");}// 新方式:在switch中使用字符串switch(color) {case "red":System.out.println("RED");break;case "green":System.out.println("GREEN");break;case "blue":System.out.println("BLUE");break;case "yellow":System.out.println("YELLOW");break;default:System.out.println("Unknown");break;}}}/* 输出:REDRED*/
一旦你理解了 switch,这个语法就是一个逻辑扩展,可以让你的代码更简洁、更易于理解和维护。
作为第二个使用字符串的 switch 例子,让我们重新回顾一下 Math.random()。它是否产生一个 0~1 范围内的值?其中包不包括值 “1”?用数学术语来说,它是 (0,1)、[0,1] 、(0,1]还是[0,1) ?(方括号的意思是 “包括”,圆括号的意思是“不包括”。)
这里有一个可能会提供答案的测试程序。所有命令行参数都是作为字符串对象传递的,因此我们可以将参数作为 switch 的选择器来决定做什么。这里有个问题:用户可能不提供任何参数,因此如果索引 args 数组,则可能会导致程序失败。为了解决这个问题,先检查数组的长度。如果为零,就使用一个空字符串,否则选择 args 数组里的第一个元素:
package onjava;import java.util.concurrent.*;public class TimedAbort {private volatile boolean restart = true;public TimedAbort(double t, String msg) {CompletableFuture.runAsync(() -> {try {while(restart) {restart = false;TimeUnit.MILLISECONDS.sleep((int)(1000 * t));}} catch(InterruptedException e) {throw new RuntimeException(e);}System.out.println(msg);System.exit(0);});}public TimedAbort(double t) {this(t, "TimedAbort " + t);}public void restart() { restart = true; }}
// control/RandomBounds.java// Math.random()能生成0.0和1.0吗// {java RandomBounds lower}import onjava.*;public class RandomBounds {public static void main(String[] args) {new TimedAbort(3);switch(args.length == 0 ? "" : args[0]) {case "lower":while(Math.random() != 0.0); // 持续尝试System.out.println("Produced 0.0!");break;case "upper":while(Math.random() != 1.0); // 持续尝试System.out.println("Produced 1.0!");break;default:System.out.println("Usage:");System.out.println("\tRandomBounds lower");System.out.println("\tRandomBounds upper");System.exit(1);}}}
如果要运行程序,输入以下任意一条命令: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 章则讲解实现隐藏的基本概念。
