我很欣赏任何可以通过switch语句完成的事情都可以通过if else语句来完成。
但是,当一个人应该使用开关而不是if else statment时,是否有风格规则。
答案 0 :(得分:16)
嗯,在我看来,switch
在很多情况下比if
/ else if
阶梯感觉“更轻”。基本上,您的代码方式中没有大括号和括号的语法。话虽如此,switch
继承了C的语法。这意味着你有break
并且只有一个变量范围,除非你引入新的块。
仍然,编译器能够将switch
语句优化到查找表中,并在处理枚举时对文字执行编译时检查。所以,我建议,如果你正在处理数字或枚举类型,通常最好使用switch
而不是if
/ else if
。
答案 1 :(得分:11)
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 个案。
答案 2 :(得分:5)
我对枚举使用switch语句,if else else if else语句更具可读性。但是,您应该尝试在OO设计中避免这种检查。
答案 3 :(得分:4)
当您打开基元/枚举/包装类型的不同值时,可以使用switch语句。 (并非所有原始/包装类型,只有受支持的类型 - byte,short,char,int)。
如果/ else处理其余部分。
例如,说起来更美观:
int i = getValueOfI();
switch (i) {
case 1:
// do something
break;
case 2:
// do something
break;
等
大于
if (i == 1) {
} else if (i == 2) {
}...
对于大量案件。但是你不能打开字符串,函数值或复杂的条件,所以如果你需要做任何一个,那么你就会被if / else所困扰。
答案 4 :(得分:3)
个人而言,我用来发现两种结构都有点过程性。 虽然它可能被认为是OO extermism,但我使用包含if的每个case的内部接口实例的Map。 我认为它允许更好的代码隔离。 但是,为了回答你的问题,当我遇到真正重叠的情况时,我只使用开关(我不使用break语句)。不幸的是,它实际上不是一个可维护的代码块。
答案 5 :(得分:3)
我建议使用简单的规则:
当您有至少2个选项来区分,数据类型可用于交换机以及所有选项具有常量值时,请始终使用switch
。
有三个很好的理由。其中一个,在大多数情况下switch
比if
/ else
级联更快。二,它使代码的意图更清晰。三,如此糟糕的被遗忘的break
困境是一个比巨大的if
/ else
级联更小的邪恶,因为有人忘记了else
而意外破坏了。{/ p>
Java VM实际上支持两种不同类型的交换机:tableswitch和lookupswitch指令。如果所有case
常量都在一个窄范围内,则表格开关由编译器生成,否则它会生成一个lookupswitch。对于具有许多情况的大switch
语句,tableswitch比lookupswitch更有效。 lookupswitch通常通过某种形式的二进制搜索来实现。
答案 6 :(得分:2)
对我来说有两个因素:
可读性以及是否要使用值或条件范围来决定某事(在switch语句中,您只能使用单个整数或枚举值)。
答案 7 :(得分:1)
首先,switch语句必须可用。如果开关基于变量的值,则可以使用它。如果它基于一个复杂的AND / OR / NOT布尔表达式,它对每个条件都有所不同,那么根本就不能使用它。
话虽如此,如果适用,并且至少有2个案例,那么我使用开关。它更容易扩展,更易于阅读和检查。
答案 8 :(得分:1)
答案取决于你正在做什么以及选择的分配。
如果一个条件占优势,那么if / then是合适的。
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;
}
那就是说,如果性能不重要,那么你最喜欢的是你最喜欢的(可维护和最容易编写)。
如果另一方面,如果您的代码位于性能非常重要的热点,那么您应该使用交换机。
对于“非常大”的条件,Mario的lambdaj切换器的例子非常酷,并且小心初始化将带来非常高的性能。它与优化器生成的编码非常相似。我会定义“非常大”,因为当选项的数量很大或足够复杂以使其值得输入时,并且当后续开发人员试图通过代码时值得支持混淆。 (注释你的代码为什么你拥有这一切!)。
答案 9 :(得分:1)
切换和枚举。
如果您正在测试的枚举值因任何原因合法地为null
,则将其置于switch语句中将生成NullPointerException。如果不看字节代码,它就会感到莫名其妙。
解释:枚举是1.5中引入的语法糖。 Switch语句仍适用于good-ole int,但它使用的值是分配给enum的序数。为了得到序数,枚举值必须是非空的。
另一方面, if statement
很乐意接受null
获取枚举值,并且在没有NPE的情况下无法通过测试。
答案 10 :(得分:1)
也许有点offtopic,但如果我只回答标题中的问题,那么我会说你不应该在所有情况下使用switch,其中case表示某个对象的状态。在这些情况下,状态模式是更漂亮的解决方案。
答案 11 :(得分:1)
我总是发现java switch语句没有我想要的那么强大。在他的last release lambdaj implements it中,聪明地使用了闭包和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
}
鉴于这3种排序方法,可以创建一种策略,以下面的声明方式选择最合适的策略:
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);
答案 12 :(得分:0)
决定使用 if-then-else 语句还是 switch 语句是基于可读性和语句测试的表达式。 if-then-else 语句可以基于值或条件的范围测试表达式,而 switch 语句仅基于单个整数、枚举值或 String 对象测试表达式。 [The switch Statement - Oracle]
答案 13 :(得分:0)
我同意x4u's answer。
此外还有另一个未提及的实例,但我认为最好使用if
- else
块而不是switch
:当每个实例中的附加条件时使用case
块测试if
块。我在现有代码中一直看到这种混合物。
例如,我发现这个代码在字符串switch
上有type
,然后在{{1}中使用extension
检查第二个字符串if
语句。
case
相反,将其减少到一个 public abstract class Temp {
boolean valid;
public Temp() {
String type = getType();
String extension = getFilenameExtension();
switch(type) {
case "Image File": {
if(!".jpg".equals(extension) && !".png".equals(extension)) {
warnWrongImageFormat();
valid = false;
}
break;
}
case "Zip File": {
if(!".zip".equals(extension)) {
warnWrongZipFormat();
valid = false;
}
break;
}
default: {
valid = true;
break;
}
}
}
abstract String getType();
abstract String getFilenameExtension();
abstract void warnWrongImageFormat();
abstract void warnWrongZipFormat();
}
if
else
答案 14 :(得分:0)
与其他语言(如C或C ++)一样,如果要将给定变量与可能值列表进行比较并根据这些值执行操作,则switch语句非常有用。它比其他陈述更为温和。
答案 15 :(得分:0)
如果你有太多的条件要检查类似的类型,你可以去切换。
答案 16 :(得分:-1)
Switch有两个相关的缺点:
切换通常是OO设计不佳的标志,因为你最好使用多态。
切换唯一可能的优点是,它更具可读性。但是
switch (i) {
case 1:
// do something
break;
case 2:
// do something
break;
}
比这更具可读性:
if (i == 1)
//do something
else if (i == 2)
// do something else
我会说:不!你不会有开关的缺点。
我的建议:尽量避免转换。