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

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

问题描述

我知道clojure / java interop的基本知识:从clojure调用java,反之亦然。但是,我不能返回一个类型的集合从clojure到java。我试图从调用clojure的java代码看到那种自然 List< TypedObject>

  Java对象:

public class TypedObject {
private OtherType1 _prop1;
public OtherType1 getProp1(){
return _prop1;
}
public void setProp1(OtherType1 prop1){
_prop1 = prop1;
}
}

CLojure方法:

(defn -createListOfTypedObjects
创建并返回TypedObjects列表
[input]
;在这里工作来创建和返回TypedObjects列表
[typedObj1,typedObj2,typedObj3])

(:gen-class
:name some .namespace
:methods [createListofTypedObjects [String] ????))

考虑我正在使用clojure编写一个API,它将作为一个jar文件分发,从java中使用。我的问题是真正的如何通过代替???问题标记上面的:gen-class为AOT,这样一个程序员在java中使用我的api编写一段代码,可以有适当的intellisense /代码完成(即: createListofTypedObjects()返回List<

解决方案

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



但是,我可以看到为其他Java程序员提供API的价值,它指定了以各种方式声明返回值(或参数)的接口;如果要在现有的Java环境中使用Clojure而不浪费资源,这是特别有吸引力的。



目前需要两个步骤:




  • 定义一个单独的接口(在Java!中),根据您的喜好指定参数化类型

  • 定义 gen-class 命名空间(或 proxy reify 实例)接口



(Clojure提供了一个 definterface 表单,单独的Java接口定义,但 definterface ,就像Clojure的其余部分,不提供指定参数化类型。

例如

  public interface IFoo {
List< TypedObject> CreateListOfTypedObjects();
}

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

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

用户创建 FooImpl 的实例,他们会eg获得代码完成,指示该方法返回 List< TypedObject> 而不是 Object 或未参数



如果您使用完整的构建工具(例如 maven ,gradle或正确配置的ant),那么你可以把Java接口放在你的Clojure项目中,跨语言依赖关系的


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.

解决方案

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:

  • 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 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... :-))

e.g.

public interface IFoo {
    List<TypedObject> createListOfTypedObjects ();
}

and then your gen-class namespace:

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

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.

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天全站免登陆