在我看来,在很多情况下,switch
比if
/else if
更“轻量级”,基本上你的代码中没有太多大括号和括号。尽管如此,switch
继承了C语言的语法规则。这意味着你只有在引入新块时才会有break
和单一变量范围。
尽管如此,编译器能够将switch
语句优化为查找表,并在处理枚举类型时执行编译时检查。因此,如果你正在处理数字或枚举类型,通常建议使用switch
而不是if
/else if
。
就清晰度而言,switch 有一个优点:
switch (i) {
case 1:
// do something
break;
case 2:
case 4:
// do something
break;
case 5:
// do something
break;
}
如果2和4的代码相同,使用以下代码可能会更加清晰:
if ( i == 1 ) {
// do something
}
if ( (i == 2) || (i == 4) ) {
// do something
}
if ( (i == 5 ) {
// do something
}
对你(或其他程序员)来说,将 2 和 4 这两种情况拆分出来也更容易。
else if (i % 2 == 0)
。有时我会想念 VB 的 Select Case
:-) - Joey我使用switch语句来处理枚举类型,这比if else if else if语句更易读。然而,在面向对象的设计中,应该尽量避免这样的检查。
当你需要根据不同的原始/枚举/包装类型的值进行切换时,可以使用switch语句。(并非所有的原始/包装类型都支持,只有byte、short、char和int类型支持)
其余情况可以使用if / else语句。
例如,更美观的写法是:
int i = getValueOfI();
switch (i) {
case 1:
// do something
break;
case 2:
// do something
break;
etc.
than
if (i == 1) {
} else if (i == 2) {
}...
对于大多数情况,使用if/else语句是可以的。但是如果您需要切换字符串、函数值或复杂条件,那么您只能使用if/else语句。
case
和break
成对输入。这样我就不会忘记它们。但我同意这并不太好看。虽然可能没有多少人在这方面争论 :-) - Joey个人而言,我发现这两种结构有点过程化。虽然这可能被视为面向对象的极端主义,但我通常会使用一个Map,其中包含每个if情况下的内部接口实例。我认为这样可以更好地隔离代码。然而,要真正回答你的问题,只有在有真正重叠的情况下(那时我不使用break语句),我才使用switch。不幸的是,这真的不是可维护的代码块。
break
和忘记 else
。我认为不能争辩哪个比另一个更有可能。 - Kirby对我来说有两个因素:
易读性以及您是想使用数值范围还是条件来做出决定(在switch语句中,您只能使用单个整数或枚举值)。
if
语句。 - David R Tribble我一直觉得Java的switch语句不够强大。在他的最新版本中,lambdaj通过巧妙地使用闭包和Hamcrest匹配器实现了它。
例如,lambdaj Switcher允许实现策略模式。假设您需要根据要排序的列表的某些特征在三个排序算法之间切换。特别是,假设我们有一个专门针对字符串的算法:
public List<String> sortStrings(List<String> list) {
// a sort algorithm suitable for Strings
}
另一个适用于小型列表(不超过100个项目)的良好解决方案:
public List<T> sortSmallList(List<T> list) {
// a sort algorithm suitable for no more than 100 items
}
还有更通用的一个:
public List<String> sort(List<String> list) {
// a generic sort algorithm
}
鉴于这三种排序方法,可以通过以下声明方式创建选择最合适的策略:
Switcher<List<T>> sortStrategy = new Switcher<List<T>>()
.addCase(having(on(List.class).get(0), instanceOf(String.class))),
new Closure() {{ of(this).sortStrings(var(List.class)); }})
.addCase(having(on(List.class).size(), lessThan(100))),
new Closure() {{ of(this).sortSmallList(var(List.class)); }})
.setDefault(new Closure() {{ of(this).sort(var(List.class)); }});
通过调用Switcher,使用最佳可用算法对列表进行排序:
List<T> sortedList = sortStrategy.exec(list, list);
if (i == 1){
//do something
}else if (i == 2){
// do something else
}
如果条件均匀分布,编译器中的优化将提供性能优势。随着可能选择的数量增加,这种性能差异变得更加明显。
switch (i) {
case 1:
// do something
break;
case 2:
// do something else
break;
....
case N:
// do yet something else
break;
}
话虽如此,如果性能不重要,那么选择你喜欢的任何一种方法作为最可读的(易于维护和编写)。
另一方面,如果您的代码处于性能重点区域,则应使用switch。
对于“非常大”的条件,Mario的lambdaj switcher示例非常酷,并且在初始化时小心处理将产生非常高的性能。它非常类似于优化器正在生成的编码。我会将“非常大”定义为选项数量足够大或复杂,值得输入所有内容,并且值得支持混淆以便后续开发人员浏览代码。(用注释解释为什么要这样做!)