如何将类型化集合从 clojure 传递给 java? [英] How to pass a typed collection from clojure to java?

查看:31
本文介绍了如何将类型化集合从 clojure 传递给 java?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 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 命名空间(或 proxyreify 实例),以便它实现该接口
  • define a separate interface (in Java!) that specifies the parameterized types as you like
  • define your gen-class namespace (or proxy or reify 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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆