我正在关注this series以了解clojure编译器的工作原理。
我尝试使用以下代码调用eval
StaticMethodExpr
方法
(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)
但没有运气并抛出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吗?
答案 0 :(得分: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程序可以通过类型(+ 1 2)
的引用分析clojure.lang.Compiler.HostExpr
来调用此方法,该引用是公共的,即使clojure.lang.Compiler.Expr
的声明接口都不是实际的运行时类型也不公开,所以我认为需要setAccessible
有点令人惊讶。