Java 7 的 switch 选择器不但可以使用整数值,还添加了使用字符串的能力。以下示例显示了在一组候选的 String 类型中做出选择的旧方式,以及使用 switch 的新方式:
// control/StringSwitch.java
public class StringSwitch {
public static void main(String[] args) {
String color = "red";
// 旧方式:使用 if-then
if("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;
}
}
}
/* 输出:
RED
RED
*/
一旦你理解了 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 章则讲解实现隐藏的基本概念。