2010-08-17 161 views
21

是因爲我們應該加載類(例如,通過string),創建實例,然後搜索適當的方法,打包參數,然後調用方法?所以大部分時間都花在這些操作上,而不是在對象上顯式調用方法,對吧?爲什麼反射速度很慢?

+3

在現代的jdk/jvm實現中,它並沒有你想象的那麼慢。 – Roman 2010-08-17 13:08:52

回答

28

您每次使用反射時都需要驗證每一步操作。例如,當你調用一個方法時,它需要檢查目標是否實際上是方法聲明器的一個實例,是否有合適的參數個數,每個參數是否是正確類型等。

絕對沒有內聯或其他表演技巧的可能性。

如果您通過名稱查找類型或方法,那麼最好包含一個簡單的地圖查找 - 每次執行時都會執行該查找,而不是在JIT時間執行一次。

基本上還有很多事情要做。然而,反思比以前快得多,如果你發現它太慢,你可能會過度使用它。

+1

另一個微妙的問題是,在使用反射時,可能需要將混淆器設置爲較不積極,從而減少收益。(許多混淆器製造商聲稱混淆提供了性能優勢以及知識產權保護和減少佔用空間。請參見,例如[本文](http://www.devx.com/wireless/Article/28989/1954)。) – 2011-11-18 15:21:48

+0

它只是調用,特別慢?其他反射使用如枚舉屬性,獲取聲明類型,獲取getter/setter方法等?這些也很慢嗎? – 2015-06-19 05:54:14

+0

@zespri:那麼,「慢」通常是相對於別的東西 - 很難說枚舉屬性是否是「慢」,因爲這不是在反射之​​外完成的 - 而「調用方法」或「獲取字段值」很多反射比直接慢。是否僅反射操作比您的應用程序需要它們慢是另一回事... – 2015-06-19 05:59:17

6

作爲附錄喬恩斯基特的回答以上(我需要更多的聲譽,以便能夠發表評論。):

反射取決於CPU資源可;如果您的應用程序運行緩慢,則反射無法解決任何問題,只需將其緩慢。

像Java本身,反思不慢任何 - 它更多的是一個古老的傳言;)

+0

反思不慢不是真的。 對於三個可放大的類,toString()比手動編碼toString要慢百分之五十。 (我正在使用OpenJDK 8) – 2015-06-22 09:17:18

2

當你調用一個方法,你需要知道,如果你用有效的論據這樣做,對一個有效的對象,返回類型是什麼,以及要執行的字節碼。當在代碼中指定確切的方法時,java可以快速找出這些東西,然後繼續實際執行該方法。

當你用反射來做這件事時,你知道的少得多。由於代碼中未指定要調用的方法,因此這些操作都不能事先完成,並且VM必須在運行時執行更加複雜且處理器密集的任務。

多態方法調用雖然可以介於這兩個極端之間的某處。在運行時間之前,您不知道要調用什麼方法,但至少可以確定方法的名稱,參數和返回類型。對於執行什麼方法知道的越多,Java在運行時就可以避免的越多。

這證明反射是較慢,但並不是說它實際上是「慢」。如果您需要反射或多態方法,請使用它們,並稍後保存對「慢」的判斷。

0

如果以適當的方式使用它,速度並不慢。例如,我用它來掃描模型類中的所有屬性,它完美地工作。

在其他情況下,如檢查目標是否具有相同的類型或簽名,它是非常緩慢的。

事情有時會很慢,但對於開箱即用的實施很重要......:D。