测试对象是否是Clojure中的Java原始数组

mik*_*era 11 arrays reflection clojure primitive-types

在Clojure中检测对象是否是Java原始数组的最佳方法是什么?

我需要这个的原因是对原始数组做一些特殊的处理,它可能看起来像:

  (if (byte-array? object)
    (handle-byte-array object))
Run Code Online (Sandbox Code Playgroud)

它是一个相当性能敏感的代码片段,所以我宁愿避免反思,如果可能的话.

Art*_*ldt 10

您可以使用反射一次从名称中获取类,缓存它,然后将其余部分与之进行比较

(def array-of-ints-type (Class/forName "[I"))
(def array-of-bytes-type (Class/forName "[B")) 
...

(= (type (into-array Integer/TYPE [1 3 4])) array-of-ints-type)
true
Run Code Online (Sandbox Code Playgroud)

  • `"[J"`对于`long`s更加可爱,不是吗?此外,无论谁想出".toString"中无与伦比的左括号都会返回值,只要我知道他们的名字,我的干草叉就会准备就绪.它一直打破我的优势,更不用说[对我的心灵的影响](http://xkcd.com/859/).(替换所有相关案例的'print-method`可能也可能不可行 - 我目前的直觉是*不*.) (3认同)

Mic*_*zyk 7

(defn primitive-array? [o]
  (let [c (class o)]
    (and (.isArray c)
         (.. c getComponentType isPrimitive))))
Run Code Online (Sandbox Code Playgroud)

对于特定情况,您可以使用以下内容:

(defn long-array? [o]
  (let [c (class o)]
    (and (.isArray c)
         (identical? (.getComponentType c) Long/TYPE))))
Run Code Online (Sandbox Code Playgroud)


小智 6

要在不使用反射的情况下检查字节数组,可以执行以下操作:

(def ^:const byte-array-type (type (byte-array 0)))
(defn bytes? [x] (= (type x) byte-array-type))
Run Code Online (Sandbox Code Playgroud)

不完全确定原因,但你甚至可以内联字节数组类型^:const.


kot*_*rak 5

或者普通的旧instance?

(instance? (RT/classForName "[B") thing)
Run Code Online (Sandbox Code Playgroud)


小智 5

正如Arthur Ulfeldt指出的那样,你可以使用Class/forName,例如,像这里:

(def byte_array_class (Class/forName "[B"))

(defn byte-array? [arr] (instance? byte_array_class arr))
Run Code Online (Sandbox Code Playgroud)

如果要"[B"在缓存类时避免使用魔术字符串,可以应用于class现有的数组对象:

(def byte_array_class (class (byte-array [])))
Run Code Online (Sandbox Code Playgroud)