有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

互操作如何将类型化集合从clojure传递到java?

我知道clojure/java互操作的基础知识:从clojure调用java,反之亦然。然而,我无法将类型化集合从clojure返回到java。我试图从调用clojure的java代码中看到这种性质的东西

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] ????])

让我们考虑使用CuljuleAPI编写一个API,它将被分配为JAR文件,用于java。我的问题是如何通过什么来代替????上面的问题标记在AOT的:gen类中,因此程序员使用我的api在java中编写一段代码时,可以从eclipse中获得适当的intellisense/代码完成(例如:createListofTypedObjects() returns List<TypedObject>


共 (2) 个答案

  1. # 1 楼答案

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

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

  2. # 2 楼答案

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

    然而,我可以看到向其他Java程序员提供API的价值,该API指定了一个接口,该接口声明以各种方式参数化的返回值(或参数);如果希望在现有Java环境中使用Clojure而不引起轰动,这一点尤其有吸引力

    目前,这需要两个步骤:

    • 定义一个单独的接口(用Java!)根据需要指定参数化类型
    • 定义gen-class名称空间(或proxyreify实例),使其实现该接口

    (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的实例时,他们将获得代码完成,表明该方法返回List<TypedObject>,而不是Object或未经参数化的List类型

    如果您使用的是sane构建工具(例如maven、gradle或正确配置的ant),那么您可以将Java接口放在Clojure项目中,跨语言依赖性将得到解决