访问未在Clojure

时间:2015-04-24 22:07:42

标签: java clojure clojure-java-interop

我开始更多地了解Clojure-Java互操作。如果我在Clojure中创建一个Java类,我需要导入它,但如果我只使用类的字段或方法,我不必导入它。例如:

(ns students.Student
  (:import [sim.util Double2D])

(defn -step
  [this students]  ; students is a students.Students, extends sim.engine.SimState
  (let [yard (.-yard students) ; a sim.field.continuous.Continuous2D
        yard-width (.-width yard)
        yard-height (.-height yard)]
    (.setObjectLocation yard this (Double2D. (/ yard-height 2) (/ yard-width 2)))))

如果不导入Double2D,则无法编译,因为代码会创建Double2D实例。

但是,我访问yard实例的setObjectLocation()字段和Students方法以及widthheight字段{ {1}}实例没有问题,即使我没有导入Continuous2DStudents类。

这是否意味着Clojure在运行时使用反射来访问Java字段和方法?那效率低吗?如果我在函数中需要速度,那么沿着缺少的import语句添加Java类的类型声明是否有利?这会阻止反思吗?

[编辑:正如我对Arthur Ulfeldt的回答所表达的第二个评论所表明的那样,我现在认为,在编译时不知道类所带来的任何低效率可能与函数包含在函数中的低效率有很大的不同。变量。如果我担心 ,我会忘记Clojure并使用纯Java编程(可能),而不是尝试使用Clojure中的Java库。对我来说,一个我可以使用Clojure而不是Java的世界是更好的。]

1 个答案:

答案 0 :(得分:4)

导入仅用于you don't have to type the full name of the class,包括它的包名,每次都要使用它。 如果课程在课程路径上,您可以通过它在任何地方的全名来调用。如果您作为import语句,则只能通过类名称来调用它,尽管只能从存在该导入的命名空间中调用它。

我将从一个新项目开始,并在默认项目中的任何位置添加一个明显 not 的依赖项,在这种情况下,Riemann客户端用于监控内容(它是' sa伟大的程序检查出来)

lein new hello

并添加dep

(defproject hello "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :aot :all
  :main hello.core
  :profiles {:uberjar {:aot :all}}
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [com.aphyr/riemann-java-client "0.3.1"]])

然后首先,我将通过它的全名来查看该课程而不进行任何导入

hello.core> com.aphyr.riemann.client.RiemannClient
com.aphyr.riemann.client.RiemannClient

然后尝试短名称:

hello.core> RiemannClient
CompilerException java.lang.RuntimeException: Unable to resolve symbol: RiemannClient in this context, compiling:(/tmp/form-init3055907211270530213.clj:1:5933) 

不起作用:

hello.core> (import '[com.aphyr.riemann.client RiemannClient])
com.aphyr.riemann.client.RiemannClient

然后,如果我们添加导入并再试一次:

hello.core> RiemannClient
com.aphyr.riemann.client.RiemannClient

名称从用户名称空间内解析 如果我更改名称空间:

hello.core> (in-ns 'foo)

然后再看一下课程:

foo> RiemannClient
CompilerException java.lang.RuntimeException: Unable to resolve symbol: RiemannClient in this context, compiling:(/tmp/form-init3055907211270530213.clj:1:5933) 
foo> com.aphyr.riemann.client.RiemannClient
com.aphyr.riemann.client.RiemannClient

我们可以看到导入是按命名空间进行的,尽管类路径上的类在任何地方都可用。