问题描述
我知道 clojure/java 互操作的基础知识:从 clojure 调用 java,反之亦然.但是,我无法将类型化集合从 clojure 返回到 java.我试图从调用 clojure 的 java 代码中看到这种性质的 List
.
I know the basics of clojure/java interop: calling java from clojure and vice versa. However, I was not able to return a typed collection from clojure to java. I am trying to see something of that nature List<TypedObject>
from the java code which is calling into clojure.
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 中编写一段代码,可以有适当的智能感知/代码完成(即:createListofTypedObjects() 返回 List
) 例如在 Eclipse 中.
Let us consider that I am writing an API using clojure, which is to be distributed as a jar file, to be used from java. My question was really how to what to pass in place of the ???? questions marks above inside the :gen-class for AOT, so that a programmer writing a piece of code in java using my api, can have the appropriate intellisense / code completion (i.e.: createListofTypedObjects() returns List<TypedObject>
) from within eclipse for example.
推荐答案
其他人说得对,Clojure 不保证返回集合中元素的类型等(实际上,JVM 不保证元素的类型在集合中,要么 - 完全由 javac 处理.)
The others are right that Clojure doesn't ensure the types of elements in returned collections, etc. (Actually, the JVM doesn't ensure the types of elements in collections, either – that's handled entirely by javac.)
但是,我可以看到为其他 Java 程序员提供 API 的价值,该 API 指定了一个接口,该接口声明以各种方式参数化的返回值(或参数);如果您希望在现有 Java 环境中使用 Clojure 而不会引起波澜,这将特别有吸引力.
However, I can see the value of providing an API to other Java programmers that specifies an interface that declares that return values (or parameters) parameterized in various ways; this is especially attractive if one is looking to use Clojure in an existing Java environment without making waves.
这目前需要一个两步过程:
This currently requires a two step process:
- 定义一个单独的接口(在 Java 中!),根据需要指定参数化类型
- 定义您的
gen-class
命名空间(或proxy
或reify
实例),以便它实现该接口
- define a separate interface (in Java!) that specifies the parameterized types as you like
- define your
gen-class
namespace (orproxy
orreify
instance) such that it implements that interface
(Clojure 确实提供了一个 definterface
形式,可以让您避免单独的 Java 接口定义,但是 definterface
,就像 Clojure 的其余部分一样,没有提供指定参数化类型.也许有一天... :-))
(Clojure does provide a definterface
form that would allow you to avoid the separate Java interface definition, but definterface
, just like the rest of Clojure, does not provide for specifying parameterized types. Maybe someday... :-))
例如
public interface IFoo {
List<TypedObject> createListOfTypedObjects ();
}
然后是您的 gen-class 命名空间:
and then your gen-class namespace:
(ns your.ns.FooImpl
(:gen-class
:implements [IFoo]))
(defn -createListOfTypedObjects
[]
[typedObj1, typedObj2, typedObj3])
当您的用户创建 FooImpl
的实例时,他们将例如获取代码完成指示该方法返回 List
而不是 Object
或未参数化的 List
类型.
When your users create instances of FooImpl
, they'll e.g. get code completion indicating that the method returns List<TypedObject>
rather than Object
or the unparameterized List
type.
如果您使用的是健全的构建工具(例如 maven、gradle 或正确的-configured ant),那么你就可以把Java接口放到你的Clojure项目中了,跨语言的依赖就搞定了.
If you're using sane build tools (e.g. maven, gradle, or properly-configured ant), then you can put the Java interface in your Clojure project, and the cross-language dependency will be taken care of.
这篇关于如何将类型化集合从 clojure 传递给 java?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!