何时在Java中使用switch语句

时间:2010-01-20 16:36:54

标签: java switch-statement if-statement

我很欣赏任何可以通过switch语句完成的事情都可以通过if else语句来完成。

但是,当一个人应该使用开关而不是if else statment时,是否有风格规则。

17 个答案:

答案 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

有三个很好的理由。其中一个,在大多数情况下switchif / 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

我会说:不!你不会有开关的缺点。

我的建议:尽量避免转换。