2017-02-05 82 views
0

我正在關注this series以瞭解clojure編譯器的工作原理。如何調用StaticMethodExpr.eval?

我嘗試使用下面的代碼

(ns clojure.lang 
    (:use clojure.core) 
    (:import [clojure.lang Compiler Compiler$C])) 

(def form (read-string "(+ 1 1)")) 

(def expr (Compiler/analyze Compiler$C/EXPRESSION form)) 

(.eval expr) 

,但沒有運氣援引StaticMethodExpreval方法,並拋出IllegalArgumentException

Unhandled java.lang.IllegalArgumentException 
    Can't call public method of non-public class: public 
    java.lang.Object clojure.lang.Compiler$StaticMethodExpr.eval() 

有什麼我失蹤,或者這是a bug in jdk

回答

1

,您仍然可以調用方法使用反射:

(let [m (.getDeclaredMethod clojure.lang.Compiler$Expr "eval" (make-array Class 0))] 
    (.setAccessible m true) 
    (defn -eval [expr] 
    (.invoke m expr (object-array 0)))) 

(-eval (clojure.lang.Compiler/analyze clojure.lang.Compiler$C/EXPRESSION '(+ 1 2))) 
;= 3 

這應該是足夠好,如果你的目標是要探索。

無反射Java程序可以調用經由clojure.lang.Compiler.HostExpr類型的引用,這是公開的,即使既不clojure.lang.Compiler.Expr申報接口也不實際運行時類型是公共分析(+ 1 2)的結果該方法,所以我想令人驚訝的是setAccessible是必需的。