如何创建实现此接口的Clojure对象,然后从Java代码调用?
public interface Doer {
public String doSomethin(String input);
}
Doer clojureDoer = ?;
String output = clojureDoer.doSomethin(input);
Run Code Online (Sandbox Code Playgroud)
ama*_*loy 45
reify
非常适合实现接口 - proxy
重载,旧,慢,所以应尽可能避免使用.实现看起来像:
(reify Doer
(doSomethin [this input]
(...whatever...)))
Run Code Online (Sandbox Code Playgroud)
请注意,关于使用的现有答案reify
具有不正确的语法,如果您决定最后使用代理:proxy采用隐式proxy
参数,而不是命名的第一个参数.
小智 15
从Clojure 1.6开始,首选方法如下.假设您在类路径上有Clojure 1.6 jar和以下clojure文件(或其编译的等效文件):
(ns my.clojure.namespace
(:import [my.java.package Doer]))
(defn reify-doer
"Some docstring about what this specific implementation of Doer
does differently than the other ones. For example, this one does
not actually do anything but print the given string to stdout."
[]
(reify
Doer
(doSomethin [this in] (println in))))
Run Code Online (Sandbox Code Playgroud)
然后,从Java,您可以按如下方式访问它:
package my.other.java.package.or.maybe.the.same.one;
import my.java.package.Doer;
import clojure.lang.IFn;
import clojure.java.api.Clojure;
public class ClojureDoerUser {
// First, we need to instruct the JVM to compile/load our
// Clojure namespace. This should, obviously, only be done once.
static {
IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("my.clojure.namespace"));
// Clojure.var() does a somewhat expensive lookup; if we had more than
// one Clojure namespace to load, so as a general rule its result should
// always be saved into a variable.
// The call to Clojure.read is necessary because require expects a Clojure
// Symbol, for which there is no more direct official Clojure API.
}
// We can now lookup the function we want from our Clojure namespace.
private static IFn doerFactory = Clojure.var("my.clojure.namespace", "reify-doer");
// Optionally, we can wrap the doerFactory IFn into a Java wrapper,
// to isolate the rest of the code from our Clojure dependency.
// And from the need to typecast, as IFn.invoke() returns Object.
public static Doer createDoer() {
return (Doer) doerFactory.invoke();
}
public static void main(String[] args) {
Doer doer = (Doer) doerFactory.invoke();
doer.doSomethin("hello, world");
}
}
Run Code Online (Sandbox Code Playgroud)
Jan*_*Jan 13
看proxy
宏.Clojure Docs有一些例子.它也包含在Java Interop页面上.
(proxy [Doer] []
(doSomethin [input]
(str input " went through proxy")))
Run Code Online (Sandbox Code Playgroud)
proxy
返回一个实现的对象Doer
.现在,要使用Java访问它,您必须使用它gen-class
来使您的Clojure代码可以从Java调用.它涵盖了"从java调用clojure"问题的答案.
(ns doer-clj
(:gen-class
:name DoerClj
:implements [Doer]
:methods [[doSomethin [String] String]]))
(defn -doSomethin
[_ input]
(str input " went through Clojure"))
Run Code Online (Sandbox Code Playgroud)
现在保存为doer_clj.clj
,mkdir classes
并通过调用REPL进行编译(require 'doer-clj) (compile 'doer-clj)
.您应该DoerClj.class
已准备好在classes
目录中使用Java
有关这个问题的更一般性的看法,当您需要某种Java-interop时,此图表可能非常有用:
https://github.com/cemerick/clojure-type-selection-flowchart
归档时间: |
|
查看次数: |
9629 次 |
最近记录: |