【问题标题】:Clojure: how do I require a class and call a static method?Clojure:我如何需要一个类并调用一个静态方法?
【发布时间】:2016-02-22 15:00:42
【问题描述】:

刚刚进入 Clojure,我在命名空间、路径和类语法方面遇到了一些问题。

我首先测试并编写了一个简单的 hello world 函数。

test/test_subject_test.clj:

(ns test-subject-test
  (:require [clojure.test :refer :all]
            [test-subject :refer :all]))

(deftest testit
  (testing "All good?"
    (is (= "I got this" (subject))))

src/test_subject.clj:

(ns test-subject)

(defn subject []
  "I got this")

一切正常,所以我决定接下来尝试在类上调用静态方法。

test/test_subject_test.clj:

(ns test-subject-test
  (:require [clojure.test :refer :all]
            [test-subject :refer :all]
            [hello :refer :all]))

(deftest testit
  (testing "All good?"
    (is (= "I got this" (subject))))
  (testing "Try calling a static method"
    (is (= "Hello Guy!" (-handler Hello "Guy")))))

src/hello.clj:

(ns hello
  (:gen-class :name "Hello"
              :methods [^:static [handler [String] String]]))

(defn -handler [s]
  (str "Hello " s "!"))

但是现在编译器会抛出一个很长的堆栈跟踪,其中包含一条有趣的消息:Caused by: java.lang.RuntimeException: Unable to resolve symbol: Hello in this context。我尝试了:require 语句和(-handler Hello) 调用的一些排列,我尝试不使用:refer :all 并将该方法称为(-handler (.Hello hello)),但显然我错过了一些关于如何类的非常基本的东西在 Clojure 中工作。

我查看了Clojure vars and Java static methods,但它似乎比我想要做的事情复杂得多:只需调用一个静态方法。然而,问题中有一个有趣的引述,这让我尝试了这个:(Hello handler "Guy") without success (Unable to resolve symbol: Hello in this context)。

那么,我应该如何从另一个文件中获取一个类并在其上调用一个静态方法?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    如果您有一个静态方法,您应该使用/ 分隔符来调用它。

    例如:

    (System/currentTimeMillis)    
    

    在你的情况下,以下应该有效:

    (ns other
      (:require [hello :as hello]))
    
    (hello/-handler "FOO")
    ; => "Hello FOO!"
    

    供参考:http://clojure.org/java_interop

    【讨论】:

      【解决方案2】:

      如果您将一个类编译到默认包中(这就是您在此处所做的),所有这些都略有不同,因为您无法导入这些类。我不建议你这样做。在下面的代码中,我假装你真的写了(:gen-class :name "hello.Hello" ...)

      要调用 java 类的方法,您应该使用完全限定的类名或首先使用 import 类:

      (import 'hello.Hello)
      (Hello/handler "there")
      

      (hello.Hello/handler "there")
      

      如您所见,您应该使用 / 来调用 java 类的静态方法。

      要使这一切都与 gen-class 一起使用,您必须确保首先编译这些类。保证那个的最简单方法是先require它的命名空间:

      (require 'hello)
      (import 'hello.Hello)
      

      因为这比使用普通的 clojure 函数和命名空间更麻烦,如果您只想从 clojure 调用代码,可能不应该使用 java interop。

      【讨论】:

      • 是的,我只使用互操作,因为我的第一个 Clojure 应用程序将是 AWS Lambda“函数”,而 Lambda 需要一个带有静态 .handler 方法的 Java 类。
      猜你喜欢
      • 2015-02-13
      • 2013-10-18
      • 2011-05-20
      • 2012-11-22
      • 1970-01-01
      • 2010-12-24
      • 1970-01-01
      相关资源
      最近更新 更多