clojure用gen-class来实现java接口,及java中测试

时间:2021-03-20 22:51:48

clojure借助gen-class实现java接口,提前编译为class文件?


这在很长一段时间困扰了我,虽然如《clojure编程》中也有例子介绍,但是却不知道如何运行这些例子,一些细节没被提到,让我与实际操作相脱离。

这篇博客也有提到gen-class的一些例子:https://kotka.de/blog/2010/02/gen-class_how_it_works_and_how_to_use_it.html

但是仍然不知道如何去将这些例子运作起来的细节。

我这里就以一个小例子来阐述我不明白的细节。涉及了clojure项目build工具lein的使用。

这个例子的主要思路是用java定义一个接口,然后用clojure的gen-class来实现该接口,最后在java中测试是否实现成功。

gen-class函数用在ns函数中就改为‘:gen-class’,该方法表示会将clojure代码提前编译为java的class文件,

然后java调用class文件中的方法。


1. 创建一个lein管理的clojure项目,名叫gen_class:lein new gen_class
然后进入项目根目录,修改project.clj文件为:
(defproject gen_class "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"}
:dependencies [[org.clojure/clojure "1.7.0"]]
:aot [gen-class.HelloImpl]
:java-source-paths ["src/java_source"])
 #:aot 意思是提前编译文件gen-class.HelloImpl.clj

 #:java-source-paths 意思是指定了java代码路径,该路径下代码会自动在clojure代码编译前被编译。

2. 进入项目的目录:src/gen_class
cd gen_class/src/
创建文件夹:java_source/java_source
创建一个定义了java接口的文件HelloInterface.java
package java_source;
public interface HelloInterface {
void sayHello();
}
3.创建clojure文件HelloImpl.clj在路径src/gen-class下:
(ns gen-class.HelloImpl
(:gen-class
:implements [java_source.HelloInterface]))

(defn -sayHello
[this ^String para]
(println "Hello, world! " para))
4. 项目根目录下打开cmd,执行命令:lein compile
5. HelloInterface和HelloImpl会先后被编译为class文件于target目录下。
6. 进入test/gen-class目录,创建java目录,编写测试的java文件Test.java,在里面调用HelloImpl.class中的sayHello方法。
package gen_class.java;

import gen_class.HelloImpl;
import java_source.HelloInterface;

public class Test {
public static void main(String[] args) {
HelloInterface HelloI = new HelloImpl();
HelloI.sayHello("Java");
}
}