2014-02-27 45 views
4

當處理現有的java類時,如果我做了一些不正確的事情,我經常會得到反射警告,Java interlo的Clojure優化

拋出:IllegalArgumentException沒有找到匹配字段:獲取類 java.lang.String中clojure.lang.Reflector.getInstanceField (Reflector.java:271)

Clojure的是在運行時做反射每個調用給定的方法?或者以任何方式緩存?將任何一種涉及的java-interop移動到相關的java類中會有速度優勢嗎?

回答

5

只有當Clojure無法根據周圍的上下文推斷出確切的調用方法時,Clojure纔會在運行時進行反射,否則會發出直接調用該方法的代碼。如果需要,可以使用類型提示爲編譯器提供此上下文。例如:

user=> (set! *warn-on-reflection* true) 

user=> (defn str-len [x] (.length x)) 
Reflection warning, NO_SOURCE_PATH:1:19 - reference to field length can't be resolved. 

user=> (defn str-len-2 [^String x] (.length x)) 

user=> (str-len "abc") ; -> 3 
user=> (str-len-2 "abc") ; -> 3 

user=> (time (dotimes [_ 100000] (str-len "abc"))) 
"Elapsed time: 1581.163611 msecs" 
user=> (time (dotimes [_ 100000] (str-len-2 "abc"))) 
"Elapsed time: 36.838201 msecs" 

第一個函數每次調用時都會使用反射;第二個與本地Java代碼具有相似的性能。

+0

謝謝,這是非常有幫助的。 –

4

這不是反射警告,它只是表明它正在使用反射。可以使用type hints消除反射。上述鏈接中描述的*warn-on-reflection*標誌(默認爲false),可以選擇啓用反射警告。

我發現使用Leiningen的lein check實用程序非常方便,它會嘗試編譯項目中的每個Clojure文件,並打開反射警告。這會在您的代碼或從庫加載的任何代碼中報告反射問題。