我正在使用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:No matching method:staticMethod”。
我唯一能看到我做错的是,在cookbook示例中,ArrayList被声明为List类型,虽然ArrayList实现了List接口,但我没有在Clojure代码中明确地这样做。我的Java-fu并不那么强大,所以我是否正确理解了方法签名在Java中的工作方式?
编辑:正如下面的答案之一所暗示的,该方法是可变的。它的格式为
public static List<String> staticMethod(List<String> args, Object... moreArgs) {
...
}
答案 0 :(得分:4)
如果你正在使用的java库实际上声明了这样的方法:
public static Whatever staticMethod(List<String> xs) {...}
然后你正在做的是正确的(实际上你甚至可以跳过j.u.ArrayList调用,因为矢量也实现了List)。所以,要么你做的不同于你所说的你正在做的事情,要么宣布这个方法与你尝试使用它的方式不同。
我的赌注是后者:或许还有一个你没有提到的varargs(Foo... xs
)论点?如果是这样,请查看How to handle java variable length arguments in clojure?之类的内容以获得正确的方法。如果没有,那么请粘贴您尝试拨打的方法的确切签名,也许有人会想出来。
答案 1 :(得分:2)
我对这些情况的常用方法是在课堂上使用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 ....
答案 2 :(得分:1)
当用户 amalloy 在他们的回答中指出时,你不能在从Clojure调用时忽略Java varargs参数。当我将代码更改为:
(-> ["vector" "of" "strings"]
(JavaClass/staticMethod (into-array Object [nil])))
一切都按预期工作。