Clojure调用匿名类

时间:2017-06-26 20:46:04

标签: clojure clojure-java-interop

我有一组Java类都实现了newBuilder接口(它们实际上是protobuf生成的类)。我想将类作为参数传递给一个表单,该表单返回一个函数来为该类创建一个新的构建器。

(defn create-message-builder
  [klass]
  (. klass newBuilder))

我无法动态获取表单,因此它会在newBuilder上调用klass静态方法。

我在another SO post找到了一个宏并进行了一些修改以支持将其注入我的源代码:

(defmacro jcall [obj & args]
  `(let [ref (if (and (symbol? ~obj) 
                     (instance? Class (eval ~obj)))
          (eval ~obj)
          ~obj) ]
  (. ref# ~@args)))

当我尝试调用此宏时:

repl> (jcall Contact newBuilder)
#object[com.skroot.Contact$Builder 0x5622de90 ""]

我收到错误:

  

IllegalArgumentException找不到匹配的字段:类java.lang.Class的newBuilder

1 个答案:

答案 0 :(得分:4)

你将在Java中做同样的事情:使用反射来询问Class对象它有哪些方法,找到正确的名称之一,并且不带参数调用它。

(defn class->builder [c]
  (let [m (.getDeclaredMethod c "newBuilder" (into-array Class []))]
    (.invoke m nil (into-array Object []))))