我在使用clojure中的java float数组上的实例方法时遇到了一些麻烦。具体来说,以下代码在调用.length
(defn make-matrix
([^floats fs]
(let [len-fs (.length fs)]
(cond (>= len-fs 16) (Matrix4. fs)
(>= len-fs 9) (Matrix3. fs)
:else (throw (IllegalArgumentException. (str "Array must have at least 9 elements (found" len-fs ")")))))))
根据我的理解,类型提示应该不需要反射来解析对.length
的调用。我错过了什么?
答案 0 :(得分:10)
JVM上的数组不像常规对象,它们的长度不是通过字段查找获得的,而是通过专门的操作码arraylength
获得的。 Java的array.length
表示法只是语法糖,可编译为此操作码。因此,(.length fs)
将在运行时失败,因为fs
将既没有length
方法也没有length
字段(假设它实际上是一个数组)
因此,您应该使用clojure.core/alength
函数:
(alength fs)
没有类型提示,这将导致反射调用;使用类型提示,它将直接调用返回fs.length
的静态方法(用Java表示法)。
答案 1 :(得分:3)
原始数组在JVM中是一种特殊情况,证明了这一点是有一个字节码指令来获取它们的长度:arraylength。所以Clojure显示反射警告的原因是因为浮点数组[F
的类没有声明名为length
的字段,所以当它尝试获取它时here这个领域不存在。
您可以自行检查以下内容:
(-> (float-array [1])
class
(.getField "length"))