首页 文章

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

提问于
浏览
16

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

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类中,因此程序员使用我的api在java中编写一段代码,可以在eclipse中具有相应的intellisense / code completion(即: createListofTypedObjects() returns List<TypedObject> ) .

3 回答

  • 20

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

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

    这目前需要两个步骤:

    • 定义一个单独的接口(在Java中!),它可以根据需要指定参数化类型

    • 定义您的 gen-class 名称空间(或 proxyreify 实例),以便它实现该接口

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

    例如

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

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

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

    当您的用户创建 FooImpl 的实例时,他们会例如获取代码完成,指示该方法返回 List<TypedObject> 而不是 Object 或unparameterized List 类型 .

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

  • 11

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

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

    user=> (make-array String 10)            ; an empty String array
    #<String[] [Ljava.lang.String;@78878c4c>
    user=> (into-array ["foo" "bar"])        ; array type inferred from first element
    #<String[] [Ljava.lang.String;@743fbbfc>
    user=> (into-array Number [1.2 5 7N])    ; explicit type array
    #<Number[] [Ljava.lang.Number;@7433b121>
    
  • 10

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

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

相关问题