我没有真正的运气通过使用谷歌得到这个比较的简明答案,而不是自己做耗时的评估,我想我会先问。
我相当肯定使用 Enums 的 switch 语句会比 if-then-else 语句执行得更快,尽管它是否是一个明显的差异是另一个问题。
有人可以为我解释一下吗?
感谢大家的快速回复,我会在以后的项目中记住这一点。
我没有真正的运气通过使用谷歌得到这个比较的简明答案,而不是自己做耗时的评估,我想我会先问。
我相当肯定使用 Enums 的 switch 语句会比 if-then-else 语句执行得更快,尽管它是否是一个明显的差异是另一个问题。
有人可以为我解释一下吗?
感谢大家的快速回复,我会在以后的项目中记住这一点。
是的,确实如此,因为总的来说,switch 语句比 if/else 链运行得更快。
尽管生成的字节码并不总是用于性能比较的权威来源,但您可以检查它以获得更好的想法。
例如这段代码:
class A {
enum N { ONE, TWO, THREE }
void testSwitch( N e ) {
switch( e ) {
case ONE : x(); break;
case TWO : x(); break;
case THREE : x(); break;
}
}
void testIf( Enum e ) {
if( e == N.ONE ) { x(); }
else if( e == N.TWO ) { x(); }
else if( e == N.THREE ) { x(); }
}
void x(){}
}
生成以下内容:
Compiled from "A.java"
class A extends java.lang.Object{
A();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
void testSwitch(A$N);
Code:
0: getstatic #2; //Field A$1.$SwitchMap$A$N:[I
3: aload_1
4: invokevirtual #3; //Method A$N.ordinal:()I
7: iaload
8: tableswitch{ //1 to 3
1: 36;
2: 43;
3: 50;
default: 54 }
36: aload_0
37: invokevirtual #4; //Method x:()V
40: goto 54
43: aload_0
44: invokevirtual #4; //Method x:()V
47: goto 54
50: aload_0
51: invokevirtual #4; //Method x:()V
54: return
void testIf(java.lang.Enum);
Code:
0: aload_1
1: getstatic #5; //Field A$N.ONE:LA$N;
4: if_acmpne 14
7: aload_0
8: invokevirtual #4; //Method x:()V
11: goto 39
14: aload_1
15: getstatic #6; //Field A$N.TWO:LA$N;
18: if_acmpne 28
21: aload_0
22: invokevirtual #4; //Method x:()V
25: goto 39
28: aload_1
29: getstatic #7; //Field A$N.THREE:LA$N;
32: if_acmpne 39
35: aload_0
36: invokevirtual #4; //Method x:()V
39: return
void x();
Code:
0: return
}
在这两种情况下,这似乎都相当快。
所以,选择一个更容易维护的。
只要坚持使用你能想出的最易读、最清晰易懂的代码,我相信你在寻找这个答案时已经失去了在性能优化中获得的所有时间。像这样的微优化很少值得,并且很容易导致代码比需要的更复杂。
我不知道更快,我猜它们都非常快。
我的考虑是带有枚举的 switch 比 multi-if/else 块更具可读性
但要注意缺少 break 语句!!
是的,switch 语句几乎总是比 if / else 语句的等效块执行得更快,因为编译器可以执行更多优化(通常一个 switch 块被编译成一个分支表,这几乎不可能用块条件。)
我会说它们也更具可读性和可维护性(除了使用我建议不要使用的失败案例!)
至于它是否明显更快,这取决于你定义的明显。除非您追求真正具体的东西,否则您可能根本不会注意到它,但我仍然会这样做,因为可读性优势比其他任何事情都重要(将速度优势视为奖励!)
我对此的回答与对问题的回答相同,即语言构造 X 通常比语言构造 Y 快:没有通用答案!
对于某种语言的实现,可能只有特定的答案,例如 Oralce(以前称为 Sun 的)基于 Hotspot 编译器的 JVM 或平台 Z 上的 IBM JDK 或 Linux 上的 OpenJDK,或者......
因此,对您的问题给出有意义的答案的唯一方法是进行适当的基准测试。当心微基准测试,它们的错误多于正确,请参见例如如何不编写微基准测试。如果您仍然想找到关于使用这里描述的这个问题框架。
因此,我建议根据您的上下文中的适用性和可读性来选择语言功能。
理论上,switch 语句可以优化为单个计算的跳转,而 if-then-else 链必须保留为单独的比较。我不知道 Java 是否真的执行了这种优化。
无论如何,开关在可读性和可维护性方面都比 if-then-else 链好,所以尽可能使用它们。