我试图比较这两种方法来实现枚举值(有和没有反射)。
这是我的测试类:
public class ReflectionOnEnumsTests2 {
enum TestEnum { ONE, TWO, THREE; }
public static void main(String[] args) {
long n = 600_000_000;
int stub;
//test without Reflection
long timeStartWithoutReflection = System.currentTimeMillis();
for (int i = 0; i < n; i++){
TestEnum[] values = TestEnum.values();
stub = values.length;
}
System.out.println("Time consuming with reflection: " + (System.currentTimeMillis() - timeStartWithoutReflection));
//test Reflection
long timeStartWithReflection = System.currentTimeMillis();
for (int i = 0; i < n; i++){
TestEnum[] values = TestEnum.class.getEnumConstants();
stub = values.length;
}
System.out.println("Time consuming with reflection: " + (System.currentTimeMillis() - timeStartWithReflection));
}
}
我对测试结果感到困惑。它们消耗的时间大致相同。我期待那门课。getEnumConstants会比values()方法慢得多。
结果:
使用反射耗时:6050
使用反射耗时:7483
1.8.0_60
问题:
那么为什么在性能上没有差别呢?
那么为什么在性能上没有差别呢?
您自己的测试显示非反射方法大约快20%。这可能没有您期望的那么多,但这是一个重要的差异。
事实上,很难以任何方式概括你的结果。性能测试Java很棘手。特别是JIT编译可能会导致像您这样的合成基准产生只代表它们自己的结果,并且不能准确地描述在实际应用程序上下文中可以期望的性能。
无论如何,你提出的比较这两种方法的标准是错误的。只要可能,您就应该使用普通的非反射方法,因为它提供了更好的API,即使性能差异很小。曾经使用反射的唯一原因是,在运行时确定要采取的操作的细节之前,您无法了解足够的信息。
TestEnum.class.getEnumConstants()
通过反射在内部调用values()
(至少在我的版本- Oracle的Java 7中):看看java.lang.Class.getEnumConstants()
和java.lang.Class.getEnumConstantsShared()
所以它应该只通过反射方法查找(如果使用映射可能是常数时间)和在getEnumConstants()
中执行的结果的克隆来减慢。
我对这些结果并不感到惊讶。
当java加载enum
(Class
对象中的值列表)时,它还将创建访问该列表(即values()
)的方法。
当你使用TestEnum.values();
时,你会得到这个值列表,当你使用TestEnum.class.getEnumConstants();
时,你所做的就是获取Class
对象并直接访问列表。
基本上,你得到的是相同的列表,这就是为什么没有真正的时间差。