Reputation: 511
I have a set of Java classes that all implement the newBuilder
interface (they are actually protobuf generated classes). I would like to pass the class as a parameter to a form that returns a function to create a new builder for that class.
(defn create-message-builder
[klass]
(. klass newBuilder))
I cannot get the form dynamically so that it calls the newBuilder
static method on klass
.
I found a macro on another SO post and made some modifications to support injecting it into my source:
(defmacro jcall [obj & args]
`(let [ref (if (and (symbol? ~obj)
(instance? Class (eval ~obj)))
(eval ~obj)
~obj) ]
(. ref# ~@args)))
When I attempt to call this macro:
repl> (jcall Contact newBuilder)
#object[com.skroot.Contact$Builder 0x5622de90 ""]
I get an error:
IllegalArgumentException No matching field found: newBuilder for class java.lang.Class
Upvotes: 0
Views: 400
Reputation: 91837
The same thing you would do in Java: use reflection to ask the Class object what methods it has, find the one of the right name, and call it with no arguments.
(defn class->builder [c]
(let [m (.getDeclaredMethod c "newBuilder" (into-array Class []))]
(.invoke m nil (into-array Object []))))
Upvotes: 4