如何将类型化集合从 clojure 传递到 java?
我了解 clojure/java 互操作的基础知识:从 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 中编写一段代码,可以具有适当的智能感知/代码完成(即: createListofTypedObjects() 返回 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] ????])
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您无需担心 Clojure 中的泛型(类型化集合)。泛型实际上只是 Java 编译器的类型提示。在运行的 Java 程序中,
List
实际上与List
因此,例如,包含字符串的 Clojure 向量已经是一个
List
,无需转换。You don't need to worry about generics (typed collections) in Clojure. Generics are really just type hints to the Java compiler. In a running Java program,
List<String>
is effectively the same asList<Object>
.So, for example, a Clojure vector containing Strings is already a
List<String>
with no conversion needed.其他人是对的,Clojure 不确保返回集合中元素的类型等。(实际上,JVM 也不确保集合中元素的类型 - 这完全由 javac 处理。)
但是,我可以看到向其他 Java 程序员提供 API 的价值在于指定一个接口,该接口声明以各种方式参数化的返回值(或参数);如果您希望在现有 Java 环境中使用 Clojure 而又不引起轰动,那么这一点尤其有吸引力。
目前这需要一个两步过程:
gen-class
命名空间(或proxy
或 < code>reify 实例),以便它实现该接口(Clojure 确实提供了
definterface
形式,可以让您避免单独的 Java 接口定义,但是definterface
,就像 Clojure 的其余部分一样,不提供指定参数化类型。也许有一天...:-))例如
,然后是您的 gen-class 命名空间:
当您的用户创建 FooImpl 实例时,他们会例如,获取代码完成,指示该方法返回
List
而不是Object
或未参数化的List
类型。如果您使用的是健全的构建工具(例如 maven、gradle 或正确配置的 ant ),那么你可以将Java接口放在你的Clojure项目中,跨语言依赖就会得到处理。
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.)
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:
gen-class
namespace (orproxy
orreify
instance) such that it implements that interface(Clojure does provide a
definterface
form that would allow you to avoid the separate Java interface definition, butdefinterface
, just like the rest of Clojure, does not provide for specifying parameterized types. Maybe someday... :-))e.g.
and then your gen-class namespace:
When your users create instances of
FooImpl
, they'll e.g. get code completion indicating that the method returnsList<TypedObject>
rather thanObject
or the unparameterizedList
type.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.
如果您尝试将
List
之类的内容传递给 java 方法,那么您无需担心它。类型参数(例如,String
)仅由javac 编译器使用,因此任何List
在运行时都可以正常工作。另一方面,如果您尝试传递特定对象类型的数组(例如,
String[]
),则可以使用各种-array
函数:If you're trying to pass something like
List<String>
to a java method, then you don't need to worry about it. The type parameter (e.g.,String
) is only used to by the javac compiler, so anyList
will work just fine at runtime.On the other hand if you're trying to pass an array of a particular object type (e.g.,
String[]
), then you can use the various-array
functions: