我正在尝试比较这两种方式来实现枚举值(有和没有反射)。
所以这是我的测试类:
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));
}
}
我对测试结果感到困惑。大致相同的时间消耗。我期望class.getEnumConstants比values()方法慢得多。
结果:
反思时间:6050
用反射耗时:7483
JDK版本: 1.8.0_60
问题:
那么为什么性能没有差异呢?
答案 0 :(得分:2)
那为什么性能没有差异呢?
您自己的测试表明,非反射方法的速度提高了约20%。这可能没有你想象的那么多,但这是一个非平凡的差异。
事实上,很难以任何方式概括你的结果。性能测试Java很棘手。特别是JIT编译可能导致像你这样的综合基准测试产生仅代表自身的结果,并且不能准确地表征在实际应用程序环境中可以预期的性能。
无论如何,你提出了比较这两种方法的错误标准。您应该在的任何地方使用普通的非反射方法,因为它提供了更好的API ,即使性能差异很小。 永远使用反射的唯一原因是,在运行时确定要采取的操作的详细信息之前,您无法知道。这种情况很少见。
答案 1 :(得分:0)
我对这些结果并不感到惊讶。
当java加载enum
(Class
对象中的值列表时,它还会创建访问该列表的方法(即values()
)。
当您使用TestEnum.values();
时,您将获得此值列表,当您使用TestEnum.class.getEnumConstants();
时,您所做的只是获取Class
对象并直接访问列表。
基本上,你得到的是相同的列表,这就是没有实际时间差异的原因。
答案 2 :(得分:0)
TestEnum.class.getEnumConstants()
通过反思在内部调用values()
(至少在我的版本中是Oracle的Java 7):看看java.lang.Class.getEnumConstants()
和java.lang.Class.getEnumConstantsShared()
因此,通过反射方法查找(如果使用地图可能是恒定时间)以及getEnumConstants()
中执行结果的克隆,它应该更慢。