【问题标题】:How to match Java method signatures in Clojure如何在 Clojure 中匹配 Java 方法签名
【发布时间】:2016-07-02 16:26:48
【问题描述】:

我正在使用 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”。

我唯一能看到我做错的事情是,在食谱示例中,ArrayList 被声明为 List 类型,尽管 ArrayList 实现了 List 接口,但我并没有在 Clojure 代码中明确地这样做。我的 Java-fu 没那么强,所以我是否正确理解了 Java 中方法签名的工作原理?

编辑:正如以下答案之一所暗示的,该方法是可变的。它的形式是

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

【问题讨论】:

  • JavaLibrary/staticMethod,你的意思是JavaClass/staticMethod,其中JavaClass属于JavaLibrary
  • @MicSokoli 非常正确。适当编辑。

标签: java clojure


【解决方案1】:

如果您使用的 java 库实际上声明了这样的方法:

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

那么你所做的就是正确的(事实上你甚至可以跳过 j.u.ArrayList 调用,因为向量也实现了 List )。所以,要么你做的事情与你所说的不同,要么声明的方法与你尝试使用它的方式不同。

我的赌注是后者:是否存在您未提及的可变参数 (Foo... xs) 论点?如果是这样,请参阅How to handle java variable length arguments in clojure? 之类的正确方法。如果不是,那么请粘贴您尝试调用的方法的确切签名,也许有人会弄清楚。

【讨论】:

    【解决方案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 ....
    

    【讨论】:

      【解决方案3】:

      正如用户 amalloy 在他们的回答中指出的那样,在从 Clojure 调用时,您不能只忽略 Java varargs 参数。当我将代码更改为:

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

      一切都按预期进行。

      【讨论】:

        猜你喜欢
        • 2011-03-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-18
        • 2018-01-15
        • 2021-06-12
        • 1970-01-01
        • 2019-01-20
        • 1970-01-01
        相关资源
        最近更新 更多