2015-10-02 121 views
0

比較我想比較這兩種方法來實現枚舉值(有和沒有反射)。枚舉值()方法和class.getEnumConstants()

所以這是我的測試類:

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()方法慢得多。

結果:
時間與反思消費:7483

JDK版本: 1.8.0_60

問題:6050
時間與反思消費

那麼爲什麼會出現性能沒有差別?

+0

你的問題到底是什麼? – Jan

+1

'Class'緩存enum常量,因此'getEnumConstants()'非常快(用於重複調用) – ZhongYu

+0

@Jan爲什麼性能沒有差別? –

回答

0

我對這些結果並不感到驚訝。

當java加載對象中的值的列表enum時,它還將創建訪問該列表的方法(即values())。

當您使用TestEnum.values();時,您將獲得此值列表,並且在使用TestEnum.class.getEnumConstants();時,您所做的只是獲取Class對象並直接訪問列表。

基本上,你得到了相同的列表,這就是爲什麼沒有實時差異。

0

TestEnum.class.getEnumConstants()電話values()內部通過反射(至少在我的版本 - Oracle的Java 7):看看java.lang.Class.getEnumConstants()java.lang.Class.getEnumConstantsShared()

所以只應通過反射方法查找(可能是固定的時間,如果較慢地圖使用)以及在getEnumConstants()中執行的結果的克隆。

2

那麼,爲什麼沒有性能差異?

您自己的測試顯示非反射方法快20%左右。這可能不如您預期的那麼多,但這是一個不小的差異。

事實上,雖然很難以任何方式概括您的結果。性能測試Java很棘手。特別是JIT編譯可能會導致諸如您的合成基準測試產生僅表示自身的結果,並且不能準確地表徵在實際應用環境中可以預期的性能。

無論如何,您提出的是比較這兩種方法的錯誤標準。您應該儘可能使用普通的,無反射的方法,因爲它提供了更好的API,即使性能差異僅適中。有史以來使用反射的唯一原因是,直到運行時間才能確定要採取的操作的詳細信息。這種情況很少見。