gpt4 book ai didi

java - 对存储在 var 中的 Java 类调用静态方法

转载 作者:行者123 更新时间:2023-11-29 05:21:36 24 4
gpt4 key购买 nike

我正在处理事件流,编码为 Google Protobuffers,存储为字节。 Protobuffers 的诀窍是你必须在尝试加载它之前知道它的类。另一个技巧是我正在加载的事件是嵌套的。

所以。我有最内层事件的 ByteArray。幸运的是,在次内层事件中有一个字段指定了最内层事件的类型,因此我可以确定应该加载哪个类。

好消息:每个候选类的解析函数都具有相同的名称 (parseFrom)。坏消息:我需要调用的函数是静态的,并且根据数量和类型进行分派(dispatch)。

我想做的是:

(ns do-the-thing
(import com.thing.place Type$Subtype Type$SecondSubType)

(def decl-obj-map
{:type-subtype Type$SubType
:type-second-subtype Type$Second$SubType})

(defn call-fn
[class n-args method]
(let [o (gensym)
args (repeatedly n-args gensym)
assure-symbol (fn [thing] (if (symbol? thing) thing (symbol thing)))
method (assure-symbol method)]
(eval
`(fn [~o ~@args]
(. ~(with-meta o {:tag class})
(~method ~@args))))))

(def event-type (.getSubtypeField event-obj)
(def parse-func (call-fn (event-type decl-obj-map) 0 "parseFrom")

(parse-func (.getByteArrayFromInnerObj inner-obj))

所以。这根本行不通。我还尝试了 this method 而不是 call-fn来自 clojure.contrib。它抛出永远难以理解的 IllegalArgumentException array element type mismatch java.lang.reflect.Array.set (Array.java:-2) 错误。

有人吗?

最佳答案

应用于类的静态方法的代码存在一些问题,最重要的是必须在编译时为点特殊形式和 friend 知道该类[注意:(类/method ...) 扩展为 (.Class method ...)]。因此,您必须在使用此策略的每次调用时都进行 eval —— eval 必须在返回的函数中移动(在对其进行一些修补之后)。这是不可取的。

例如,你可以通过反射来解决这个问题

(defn call-fn [^Class class method] 
(fn [& args]
(clojure.lang.Reflector/invokeStaticMethod
(.getName class)
(str method)
(to-array args))))


(def my-abs (call-fn Math "abs"))
(my-abs -1) ;=> 1

但我认为您过度设计了您的问题。例如,考虑从规范直接到函数的映射,而不是从类型关键字到类的映射

(def spec->parser
{:type-subtype {1 #(Type$Subtype/parseFrom %) 2 #(Type$Subtype/parseFrom % %2)}
:type-second-subtype {1 #(Type$SecondSubtype/parseFrom %) ...}})

那么你的call-fn就是

(defn get-parser [type-kw nargs] (get-in spec->parser [type-kw nargs]))

或者只是#(get-in spec->parser &%)

关于java - 对存储在 var 中的 Java 类调用静态方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24472968/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com