如何将类型化的集合从clojure传递给java?

我知道clojure / java interop的基础知识:从clojure调用java,反之亦然。 但是,我无法将clojure中的类型集合返回到java。 我试图从调用clojure的java代码中看到一些自然的List

 Java Object: public class TypedObject { private OtherType1 _prop1; public OtherType1 getProp1() { return _prop1; } public void setProp1(OtherType1 prop1) { _prop1 = prop1; } } CLojure method: (defn -createListOfTypedObjects "Creates and returns a list of TypedObjects" [input] ;Do work here to create and return list of TypedObjects [typedObj1, typedObj2, typedObj3]) (:gen-class :name some.namespace :methods [createListofTypedObjects[String] ????]) 

让我们考虑一下,我正在使用clojure编写一个API,它将作为jar文件分发,以便在java中使用。 我的问题是如何通过代替???? 上面的问题标记在:AOT的gen-class中,以便程序员使用我的api在java中编写一段代码,可以从eclipse中获得相应的intellisense / code completion(即: createListofTypedObjects() returns List )例如。

其他正确的是Clojure不能确保返回集合中的元素类型等。(实际上,JVM也不能确保集合中元素的类型 – 完全由javac处理。)

但是,我可以看到为其他Java程序员提供API的价值,这些程序员指定了一个接口,该接口声明以各种方式参数化的返回值(或参数); 如果想要在现有的Java环境中使用Clojure而不产生波浪,这一点尤其具有吸引力。

这目前需要两个步骤:

  • 定义一个单独的接口(在Java中!),它可以根据需要指定参数化类型
  • 定义您的gen-class命名空间(或proxyreify实例),以便它实现该接口

(Clojure确实提供了一个允许你避免单独的Java接口定义的definterfaceforms,但是definterface ,就像Clojure的其余部分一样,没有提供指定参数化类型。也许有一天… :-))

例如

 public interface IFoo { List createListOfTypedObjects (); } 

然后你的gen-class命名空间:

 (ns your.ns.FooImpl (:gen-class :implements [IFoo])) (defn -createListOfTypedObjects [] [typedObj1, typedObj2, typedObj3]) 

当您的用户创建FooImpl实例时,他们将获得代码完成,表明该方法返回List而不是Object或未参数化的List类型。

如果您正在使用理智的构建工具(例如maven ,gradle或正确配置的ant),那么您可以将Java接口放在Clojure项目中,并且将考虑跨语言依赖性。

如果您尝试将类似List传递给java方法,那么您不必担心它。 类型参数(例如, String )仅用于javac编译器,因此任何List在运行时都可以正常工作。

另一方面,如果您尝试传递特定对象类型的数组(例如, String[] ),那么您可以使用各种-array函数:

 user=> (make-array String 10) ; an empty String array # user=> (into-array ["foo" "bar"]) ; array type inferred from first element # user=> (into-array Number [1.2 5 7N]) ; explicit type array # 

您不必担心Clojure中的generics(类型集合)。 generics实际上只是Java编译器的类型提示。 在正在运行的Java程序中, List实际上与List相同。

因此,例如,包含字符串的Clojure向量已经是List ,不需要转换。