首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Clojure中实现Java接口

如何在Clojure中实现Java接口
EN

Stack Overflow用户
提问于 2011-12-23 18:09:51
回答 4查看 11.7K关注 0票数 20

如何创建实现此接口的Clojure对象,然后从Java代码中调用该对象?

代码语言:javascript
复制
public interface Doer {
   public String doSomethin(String input);
}

Doer clojureDoer = ?;

String output = clojureDoer.doSomethin(input);
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-12-23 18:35:18

reify是实现接口的首选-- proxy是繁重、陈旧和缓慢的,所以应该尽可能避免使用它。实现将如下所示:

代码语言:javascript
复制
(reify Doer
  (doSomethin [this input]
    (...whatever...)))
票数 47
EN

Stack Overflow用户

发布于 2014-05-12 01:06:13

对于Clojure 1.6,首选方法如下所示。假设您的类路径中有Clojure 1.6jar和以下clojure文件(或其已编译的等价物):

代码语言:javascript
复制
(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))))

然后,您可以从Java访问它,如下所示:

代码语言:javascript
复制
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");
    }
}
票数 18
EN

Stack Overflow用户

发布于 2011-12-23 18:13:26

使用代理

请参见proxy宏。Clojure Docs有一些例子。在Java Interop页面上也有介绍。

代码语言:javascript
复制
(proxy [Doer] []
  (doSomethin [input]
    (str input " went through proxy")))

proxy返回一个实现Doer的对象。现在,要在Java语言中访问它,您必须使用gen-class使您的Clojure代码可从Java调用。在对"Calling clojure from java"问题的回答中对此进行了介绍。

使用gen-class

代码语言:javascript
复制
(ns doer-clj
  (:gen-class
    :name DoerClj
    :implements [Doer]
    :methods [[doSomethin [String] String]]))

(defn -doSomethin
  [_ input]
  (str input " went through Clojure"))

现在将它保存为doer_clj.cljmkdir classes,并通过调用你的REPL (require 'doer-clj) (compile 'doer-clj)来编译它。您应该可以在classes目录中找到可从Java使用的DoerClj.class

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8614734

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档