【问题标题】:Clojure: call java static method/field via instance variable or string (not class name symbol)Clojure:通过实例变量或字符串(不是类名符号)调用java静态方法/字段
【发布时间】:2020-08-28 16:08:27
【问题描述】:

我可以执行以下操作,并且有效...

=> (. java.awt.event.KeyEvent getKeyText 10)
"Enter"

但是,我有一个名为 ev 的 java.awt.event.KeyEvent 实例。例如,

=> (class ev)
java.awt.event.KeyEvent

我想改为这样调用方法(但是,这会产生错误):

=> (. (class ev) getKeyText 10)
No matching method getKeyText found taking 1 args for class java.lang.Class

是否可以从实例中调用静态方法?

我已经阅读了docs 并搜索了堆栈溢出。问题here不一样。

【问题讨论】:

标签: clojure static-methods clojure-java-interop


【解决方案1】:

这是使用MethodHandle API 的尝试。

(ns playground.static-method-handle
  (:import [java.lang.invoke MethodType MethodHandles]))

;; Get a MethodType instance that encodes the shape of the method (return type and arguments)
(def getKeyText-method-type (MethodType/methodType String Integer/TYPE))

(defn call-getKeyText-on-class [cl key-code]
  (let [lu (MethodHandles/lookup)
        h (.findStatic lu cl "getKeyText" getKeyText-method-type)]
    (.invokeWithArguments h [(int key-code)])))

我们这样使用它:

(call-getKeyText-on-class KeyEvent 10)
;; => "Enter"

【讨论】:

    【解决方案2】:

    就像在 Java 中一样,只有在编译时知道要调用哪个类的哪个方法时,才能直接调用静态方法。否则,您需要在 Class 对象上使用反射来查找方法句柄。

    【讨论】:

    • 谢谢...我想可能是这种情况(我不写Java)。我想我将不得不解决...(condp =(class ev)FirstClass(FirstClass/someMethod)SecondClass(SecondClass/someMethod)。如果您不知道完整的可能类名集,这不完全是一个解决方案一个实例。
    • 我暂时将其标记为已接受的答案,因为这是我将代码从这种模式中重新分解的充分理由。但是,如果有人有宏/反射 hack,请随时分享。
    • 还有哪些其他类有 .getKeyText 静态方法?
    • 本例中的具体类仅作为示例。据我所知,不会有其他类定义 getKeyText 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 2017-10-10
    • 2013-02-27
    • 1970-01-01
    相关资源
    最近更新 更多