Clojure-带有基元数组的反射警告。长度

Clojure-带有基元数组的反射警告。长度,clojure,primitive,Clojure,Primitive,我在clojure中尝试在java浮点数组上使用实例方法时遇到了一些问题。具体而言,以下代码在调用.length (defn make-matrix ([^floats fs] (let [len-fs (.length fs)] (cond (>= len-fs 16) (Matrix4. fs) (>= len-fs 9) (Matrix3. fs) :else (throw (IllegalArgumentExc

我在clojure中尝试在java浮点数组上使用实例方法时遇到了一些问题。具体而言,以下代码在调用
.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
的调用的反射需求。我遗漏了什么?

JVM上的数组与常规对象不同,它们的长度不是通过字段查找获得的,而是通过专门的操作码
数组长度
获得的。Java的
array.length
符号就是编译成这个操作码的语法糖。因此,
(.length fs)
将在运行时失败,因为
fs
既没有
length
方法,也没有
length
字段(假设它实际上是一个数组)

因此,您应该使用
clojure.core/alength
函数:

(alength fs)

如果没有类型提示,这将导致反射调用;有了类型提示,它将直接调用返回
fs.length
(用Java表示法)的静态方法。

基本数组在JVM中是一种特殊情况,证明这一点的是有一条字节码指令用于获取它们的长度:。因此Clojure显示反射警告的原因是,浮点数组
[F
的类没有声明名为
length
的字段,因此当它尝试获取它()时,字段不在那里

您可以通过以下操作自己检查它:

(-> (float-array [1])
  class
  (.getField "length"))