16

clojure と Java の相互運用の基本を知っています。つまり、clojure から Java を呼び出したり、その逆を行ったりします。ただし、型付きコレクションを clojure から Java に返すことはできませんでした。List<TypedObject>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] ????])

jarファイルとして配布され、Javaから使用されるように、clojureを使用してAPIを作成しているとします。私の質問は、???? の代わりに何を渡すかということでした。上記の質問マークは AOT の :gen-class 内にあるため、プログラマーは私の API を使用して Java でコードを記述し、createListofTypedObjects() returns List<TypedObject>たとえば Eclipse 内から適切なインテリセンス/コード補完 (つまり: ) を使用できます。

4

3 に答える 3

23

Clojure は返されたコレクション内の要素の型などを保証しないという他の意見は正しいです (実際、JVM はコレクション内の要素の型も保証しません。これはすべて javac によって処理されます)。

しかし、さまざまな方法でパラメーター化された戻り値 (またはパラメーター) を宣言するインターフェースを指定する API を他の Java プログラマーに提供することの価値は理解できます。これは、波を作ることなく既存の Java 環境で Clojure を使用しようとしている場合に特に魅力的です。

これには現在、次の 2 段階のプロセスが必要です。

  • 必要に応じてパラメータ化された型を指定する別のインターフェイスを (Java で!) 定義します。
  • そのインターフェースを実装するようにgen-class名前空間(proxyまたはインスタンス)を定義します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<TypedObject>ObjectList

適切なビルド ツール (例: maven、gradle、または適切に構成された ant) を使用している場合は、Clojure プロジェクトに Java インターフェースを配置することができ、言語間の依存関係が処理されます。

于 2010-09-22T14:39:23.470 に答える
10

のようなものを Java メソッドに渡そうとしている場合はList<String>、心配する必要はありません。型パラメータ (例: 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>
于 2010-09-11T01:12:20.663 に答える
9

Clojure では、ジェネリック (型付きコレクション) について心配する必要はありません。ジェネリックスは、実際には Java コンパイラへの型ヒントにすぎません。実行中の Java プログラムでList<String>は、実質的に と同じList<Object>です。

したがって、たとえば、文字列を含む Clojure ベクトルは、すでにList<String>変換の必要がない です。

于 2010-09-11T01:13:10.117 に答える