2017-06-26 10 views
0

私はすべてnewBuilderインターフェイスを実装する一連のJavaクラスを持っています(これらは実際に生成されるクラスのプロトタイプです)。私はそのクラスのための新しいビルダーを作成する関数を返すフォームにパラメータとしてクラスを渡したいと思います。Clojureは静的な匿名クラスのJavaメソッドを呼び出します

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

それはklassnewBuilder静的メソッドを呼び出すように私は、動的にフォームを取得することはできません。

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

私はこのマクロを呼び出そう:

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

私はエラーを取得する:

私は another SO postにマクロを発見し、私の元に注入サポートするためにいくつかの変更をしました

IllegalArgumentException No matching field found: newBuilder for class java.lang.Class

+1

また、匿名のクラスでもありません。実行時にClassオブジェクトを渡すので、コンパイル時にその名前が分かりません。 – amalloy

答えて

4

Javaで行うのと同じことです:反射を使用してClass objecに問い合わせますどのようなメソッドを持っているか、適切な名前の1つを見つけて、引数なしでそれを呼び出します。

(defn class->builder [c] 
    (let [m (.getDeclaredMethod c "newBuilder" (into-array Class []))] 
    (.invoke m nil (into-array Object [])))) 
関連する問題