2010-06-01 49 views
10

我工作的一些Java/Clojure的互操作性和跨反射以下代碼警告是:Clojure中使用類型提示對Java返回值

(defn load-image [resource-name] 
    (javax.imageio.ImageIO/read 
    (.getResource 
     (class javax.imageio.ImageIO) 
     resource-name))) 

=> Reflection warning, clojure/repl.clj:37 - reference to field read can't be resolved. 

我很驚訝這是因爲總的getResource回報一個URL,因此我期望編譯器在javax.imageio.ImageIO/read中使用適當的靜態方法。

該代碼工作得很好順便說一句,所以它顯然在運行時找到正確的方法。

所以兩個問題:

  1. 這是爲什麼返回一個反射警告?
  2. 需要什麼類型的提示來解決這個問題?
+0

這段代碼沒有反射警告。你能提供更多關於你的設置的細節嗎? (Clojure版本 - 儘管我嘗試了1.1版本和最新版本 - 至少是JVM版本。) – 2010-06-01 23:08:05

+0

我使用的是Clojure 1.2和Java 1.6 JDK的5月中旬版本。也許我應該嘗試最新的1.2版本? – mikera 2010-06-01 23:19:42

+0

Sun JDK或OpenJDK?至於構建,當然,給它一個鏡頭,雖然它適用於我自己的本地構建和1.1版本。 – 2010-06-02 00:10:36

回答

3

AFAICS與您的代碼或編譯無關。它是REPL的源 - Fn功能的一部分:

... 
     (let [text (StringBuilder.) 
      pbr (proxy [PushbackReader] [rdr] 
        (read [] (let [i (proxy-super read)] 
          (.append text (char i)) 
          i)))] 
... 

,並用於在REPL殼,AFAICT顯示源代碼。

+0

非常好的地方!猜測這是Clojure開發團隊修復的警告嗎? – mikera 2010-06-02 10:49:04

+0

反射警告是在編譯時發出的。當任何東西都可以輸入到REPL中時,REPL代碼當然是編譯完成的。實際上,'clojure.jar'中的內容是提前編譯的,所以我看不到連接到它的任何反射警告是否會出現在REPL中。而且,我仍然無法重現這個問題,並且我嘗試了當前的哈德森快照,兩個本地1.2版本和1.1版本的jar。只是試圖給遊行帶來一些建設性的雨水,以幫助沖走我們對此的理解的任何剩餘障礙... – 2010-06-02 19:50:26

+0

它似乎在repl.clj中抱怨的行是:(proxy [PushbackReader] [rdr] (閱讀[](讓[我(代理超級閱讀)](.append文本(字符我))我))) - 有趣的是我注意到,警告消失,如果我把(:使用[clojure.repl])在(set!* warn-on-reflection * true)行之前的ns聲明也許會發生什麼,這是否會改變編譯的時間? – mikera 2010-06-03 17:56:36

1

對於其他人誰找到這個職位(像我一樣)不知道什麼時候,爲什麼他們使用proxy-super時得到反映警告...

每個代理方法有一個隱this第一個參數,其中,唉,是不是類型 - 暗示(大概是因爲代理實現了許多可能的類型,並且稍後創建了代理類)。

所以,如果你曾經從代理內部調用this的方法(這就是proxy-super最終做的),那麼你會看到反射警告。

簡單的解決方案是將代碼包裝在使用類型提示的let中。例如:

(let [^SomeClass this this] 
    (proxy-super foo) 
    (.bar this))