如何使用已归类/子类化的对象调用Java方法

时间:2019-06-05 13:53:28

标签: java clojure reify

我试图从Clojure调用Java方法。它具有某种类型的参数。

我已经使用reify创建了一个子类并重写了一个方法。当我尝试调用Java方法时,收到IllegalArgumentsException。我已经使用clojure.reflect来确认该方法是否存在,所以我认为问题在于它无法识别该子类。

这是我的project.clj:

(defproject clojure-se "0.1.0-SNAPSHOT"
  :description "A clojure Helidon SE app"
  :dependencies [[org.clojure/clojure "1.9.0"]
               [io.helidon/helidon-bom "1.0.0" :extension "pom"]
               [io.helidon.bundles/helidon-bundles-webserver "1.0.0"]
               [io.helidon.config/helidon-config-yaml "1.0.0"]
               [io.helidon.health/helidon-health "1.0.0"]
               [io.helidon.health/helidon-health-checks "1.0.0"]
               [io.helidon.metrics/helidon-metrics "1.0.0"]]  :main ^:skip-aot clojure-se.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all}})

我的代码:

(ns clojure-se.core
  (:gen-class)
  (:import io.helidon.webserver.Routing
           io.helidon.webserver.Routing$Builder
           io.helidon.webserver.Handler
           io.helidon.webserver.ServerRequest
           io.helidon.webserver.ServerResponse
           io.helidon.webserver.WebServer))

(defn -main
  "I am a Helidon app."
  [& args]

  (def handler (reify io.helidon.webserver.Handler
                 (^void accept [this ^ServerRequest req ^ServerResponse res]
                   (print "handled a request"))))

  (def builder (. Routing builder))

  (def routing (.any builder handler))
; also tried:
;  (def routing (.any builder "/test" handler))
;    to use the method with String, Handler
;  (def routing (.any builder (to-array '(handler)))
;    to use the method with Handler...  (varargs)

  (def server
    (. WebServer create routing))

  (. server start))

作为参考,下面是大致等效的Java代码:

  public static void main (String[] args) throws Exception {
   WebServer webServer = WebServer.create (Routing.builder()
                         .any ((req, res) -> res.send ("It works!"))
                         .build())
   .start(); 
 }

any()的参数是处理程序,FunctionalInterface

我可以在反射输出中看到这些方法:

clojure-se.core=> (pprint (reflect builder))
{:bases
 #{java.lang.Object io.helidon.webserver.Routing$Rules
   io.helidon.common.Builder},
 :flags #{:public},
 :members
 #{  ; truncated...
   {:name any,
    :return-type io.helidon.webserver.Routing$Builder,
    :declaring-class io.helidon.webserver.Routing$Builder,
    :parameter-types [io.helidon.webserver.Handler<>],
    :exception-types [],
    :flags #{:varargs :public}}
   {:name any,
    :return-type io.helidon.webserver.Routing$Builder,
    :declaring-class io.helidon.webserver.Routing$Builder,
    :parameter-types [java.lang.String io.helidon.webserver.Handler<>],
    :exception-types [],
    :flags #{:varargs :public}}}

这是我得到的例外,请注意,如果我在REPL中查看handler,它说它是一个验证,而不是Handler,尽管反射确实显示它是以Handler为基础。

clojure-se.core=> (-> (. Routing builder) (.any handler) (.build))

IllegalArgumentException No matching method found: any for class io.helidon.webserver.Routing$Builder  clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:80)
clojure-se.core=> handler
#object[clojure_se.core$reify__1772 0x109a9c90 "clojure_se.core$reify__1772@109a9c90"]
clojure-se.core=> 

0 个答案:

没有答案