2016-03-16 19 views
0

我正在使用Clojure的Java庫。圖書館食譜描述了作爲一個靜態方法如下:如何匹配Clojure中的Java方法簽名

List<String> myList = new ArrayList<String>(); 
// next, add values to list, then: 
myResults = JavaClass.staticMethod(myList); 

起初,我以爲我將能夠通過執行以下操作使用來自Clojure的方法:

(-> ["vector" "of" "strings"] 
    java.util.ArrayList. 
    JavaClass/staticMethod) 

但是當我做這我得到錯誤消息「CompilerException java.lang.IllegalArgumentException:沒有匹配的方法:staticMethod」。

我可以看到我做錯的唯一的事情是,在食譜示例中,ArrayList被聲明爲類型List,儘管ArrayList實現了List接口,但我並沒有在Clojure代碼中明確地做到這一點。我的Java-fu沒有那麼強大,所以我正確理解Java中的方法簽名是如何工作的?

編輯:作爲以下答案之一,所提到的方法是可變的。它的形式是

public static List<String> staticMethod(List<String> args, Object... moreArgs) { 
... 
} 
+0

有了'JavaLibrary/staticMethod',你的意思是'JavaClass/staticMethod',其中'JavaClass'屬於'JavaLibrary'嗎? – MicSokoli

+0

@MicSokoli完全正確。正式編輯。 – patabongo

回答

0

隨着用戶amalloy在他們的回答中指出,你不能只是從Clojure調用時忽略Java可變參數參數。當我將我的代碼更改爲:

(-> ["vector" "of" "strings"] 
(JavaClass/staticMethod (into-array Object [nil]))) 

一切按預期工作。

4

如果你實際使用的Java庫聲明,像這樣的方法:

public static Whatever staticMethod(List<String> xs) {...} 

那麼你正在做的是正確的(事實上,你甚至可以跳過juArrayList調用,因爲矢量也實現List)。所以,要麼你正在做一些與你所說的不同的事情,要麼你的方法與你試圖使用它的方式不同。

我的賭注是關於後者:或許你有沒有提到的可變參數(Foo... xs)?如果是這樣,請參閱How to handle java variable length arguments in clojure?這樣的正確方法。如果沒有,那麼請粘貼您嘗試撥打的方法的確切簽名,也許有人會弄清楚。

1

我對這些情況通常的方法是使用的類clojure.reflect/refelct,看看它的真正期待

main> (-> [1 2 3] 
      java.util.ArrayList. 
      java.util.Arrays/copyOf) 
CompilerException java.lang.IllegalArgumentException: No matching method: copyOf, compiling:(*cider-repl api*:49:24) 

main> (-> java.util.Arrays 
      clojure.reflect/reflect 
      clojure.pprint/pprint) 
{:bases #{java.lang.Object}, 
:flags #{:public}, 
:members 
#{{:name stream, 
    :return-type java.util.stream.Stream, 
    :declaring-class java.util.Arrays, 
    :parameter-types [java.lang.Object<>], 
    :exception-types [], 
    :flags #{:public :static}} 

.... lots more methods ... 

    {:name copyOf, 
    :return-type java.lang.Object<>, 
    :declaring-class java.util.Arrays, 
    :parameter-types [java.lang.Object<> int java.lang.Class], 
    :exception-types [], 
    :flags #{:public :static}} 

.... lots more ....