枚举值()方法和class.getEnumConstants()的比较

时间:2015-10-02 12:50:01

标签: java reflection enums

我正在尝试比较这两种方式来实现枚举值(有和没有反射)。

所以这是我的测试类:

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

问题:
那么为什么性能没有差异呢?

3 个答案:

答案 0 :(得分:2)

  

那为什么性能没有差异呢?

您自己的测试表明,非反射方法的速度提高了约20%。这可能没有你想象的那么多,但这是一个非平凡的差异。

事实上,很难以任何方式概括你的结果。性能测试Java很棘手。特别是JIT编译可能导致像你这样的综合基准测试产生仅代表自身的结果,并且不能准确地表征在实际应用程序环境中可以预期的性能。

无论如何,你提出了比较这两种方法的错误标准。您应该在的任何地方使用普通的非反射方法,因为它提供了更好的API ,即使性能差异很小。 永远使用反射的唯一原因是,在运行时确定要采取的操作的详细信息之前,您无法知道。这种情况很少见。

答案 1 :(得分:0)

我对这些结果并不感到惊讶。

当java加载enumClass对象中的值列表时,它还会创建访问该列表的方法(即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()中执行结果的克隆,它应该更慢。