以下示例函数使用 Clojure 的 Java 互操作的特殊形式调用类构造函数,导致反射警告:
(defn test-reflection-err []
(new java.util.HashMap {}))
该消息内容如下:
Reflection warning, /Users/ethan/Projects/scicloj/tablecloth.time/src/tablecloth/time/index.clj:26:3 - call to java.util.HashMap ctor can't be resolved.
我尝试放置类型提示来避免这种情况,但不确定将它们放置在哪里以防止反射错误。有人知道怎么做吗?
我试过了:
(defn test-reflection-err []
(^TreeMap new java.util.HashMap {}))
和
(defn test-reflection-err []
(doto ^TreeMap (new java.util.HashMap {})))
答案 0 :(得分:5)
您需要在构造函数参数中添加一个提示:
(let [^java.util.Map m {}]
(new java.util.HashMap m))
答案 1 :(得分:-2)
除非您出于某种原因确实需要消除所有反射,否则最简单的答案是将此行放在您的 project.clj
中:
:global-vars {*warn-on-reflection* false}
在使用空的 Clojure 映射作为构造函数 arg 时,我无法获得消除警告的类型提示。观察此代码:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(dotest
(newline)
(spyxx {:a 1}) ; `spyxx` prints expression, type, and value
(newline)
(spyxx (java.util.HashMap.)) ; Works
(spyxx (new java.util.HashMap)) ; Works
(newline)
(let [m ^java.util.Map {}]
(spyxx (new java.util.HashMap m)) ; Reflection Warning
(spyxx (java.util.HashMap. m))) ; Reflection Warning
(newline)
(let [^java.util.Map m {}]
(spyxx (new java.util.HashMap m)) ; Works
(spyxx (java.util.HashMap. m)))) ; Works
(def ^java.util.Map m3 {})
(dotest
(newline)
(spyxx m3)
(spyxx (java.util.HashMap. m3))) ; Works
结果如下。请注意,它们都可以工作,但是您会在上面指出的地方收到反射警告:
--------------------------------------
Clojure 1.10.2-alpha1 Java 15
--------------------------------------
Testing tst.demo.core
{:a 1} => <#clojure.lang.PersistentArrayMap {:a 1}>
(java.util.HashMap.) => <#java.util.HashMap {}>
(new java.util.HashMap) => <#java.util.HashMap {}>
(new java.util.HashMap m) => <#java.util.HashMap {}>
(java.util.HashMap. m) => <#java.util.HashMap {}>
(new java.util.HashMap m) => <#java.util.HashMap {}>
(java.util.HashMap. m) => <#java.util.HashMap {}>
m3 => <#clojure.lang.PersistentArrayMap {}>
(java.util.HashMap. m3) => <#java.util.HashMap {}>
看来您不需要空的 Clojure 映射作为构造函数 arg,然后问题就消失了。您还可以通过将 *warn-on-reflection*
设置为 false(在 project.clj
中或在代码中手动设置)来消除警告。
如果你使用类型提示,很容易把它放在错误的地方,它会被默默地忽略。
考虑这个额外的代码:
(dotest
(newline)
(set! *warn-on-reflection* false) ; not executed upon parsing
(let [m4 ^java.util.Map {}]
(spyxx (new java.util.HashMap m4)) ; Reflection Warning
(spyxx (java.util.HashMap. m4)))) ; Reflection Warning
(newline)
; vvv executed when parsed before following lines
(set! *warn-on-reflection* false)
(let [m5 ^java.util.Map {}]
(spyxx (new java.util.HashMap m5)) ; Works
(spyxx (java.util.HashMap. m5))) ; Works
第一个测试在解析时(在测试运行之前)会生成一个反射警告,因为解析器似乎正在评估常量表达式(推测)。
第二个测试不会产生警告,因为 Clojure 正在依次读取、解析和评估每个表单。因此调用 (set! *warn-on-reflection* false)
在读取和评估以下行之前执行以禁用警告。