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

发布于 2024-09-19 02:13:02 字数 981 浏览 7 评论 0原文

我了解 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< /code>) 例如,来自 eclipse 内。

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

述情 2024-09-26 02:13:03

您无需担心 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 as List<Object>.

So, for example, a Clojure vector containing Strings is already a List<String> with no conversion needed.

和影子一齐双人舞 2024-09-26 02:13:02

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

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

目前这需要一个两步过程:

  • 定义一个单独的接口(在 Java 中!),根据您的需要指定参数化类型
  • 定义您的 gen-class 命名空间(或 proxy 或 < code>reify 实例),以便它实现该接口

(Clojure 确实提供了 definterface 形式,可以让您避免单独的 Java 接口定义,但是 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 而不是 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:

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

女中豪杰 2024-09-26 02:13:02

如果您尝试将 List 之类的内容传递给 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>

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 any List 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:

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文