Java:Enums与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."":()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 } 

在这两种情况下,这似乎都相当快。

所以,选择一个更容易维护的。

只要坚持用你能想到的最易读和最清晰的代码,我确信你已经失去了在性能优化中获得的所有时间,同时也在寻找这个答案。 像这样的微优化很少值得,并且很容易导致代码比需要的更复杂。

我不知道更快,我猜它们都非常快。

我的考虑是带有枚举的开关比多个if / else块更具可读性

但要注意缺少rest陈述!!

是的,一个switch语句几乎总是比if / else语句的等效块执行得更快,因为编译器可以执行更多的优化(通常一个switch块被编译成一个分支表,这对于一个块来说几乎是不可能的。条件句。)

我会说他们也更具可读性和可维护性(除了使用我建议反对的堕落案例!)

至于它是否明显更快,它取决于你定义的明显。 除非你真的特别注意到你根本不会注意到它,否则我仍然可以这样做,因为可读性优势比其他任何东西都要好(把速度优势视为奖励!)

我对此的回答与以往一样,问题是语言构造X通常比语言构造更快Y:没有一般答案!

对于语言的某些实现,可能只有特定的答案,例如Oralce(正式的Sun)基于Hotspot编译器的JVM,或者平台Z上的IBM JDK或Linux上的OpenJDK,或者……

因此,对您的问题给出有意义的答案的唯一方法是做一个适当的基准。 谨防微观基准,他们往往错误而不是正确,请参阅例如如何不编写微基准 。 如果您仍想查找有关使用此处描述的此问题框架 。

因此,我建议根据您的适用性和可读性选择语言function。

理论上,switch语句可以优化为单个计算跳转,而if-then-else链必须保持为单独的比较。 我不知道Java是否实际执行此优化。

无论如何,在可读性和可维护性方面,交换机比if-then-else链更好,所以尽可能使用它们。