Clojure:无法找到静态字段

时间:2016-02-04 11:29:10

标签: clojure

给出以下代码:

(map Integer/parseInt ["1" "2" "3" "4"])

除非我将Integer/parseInt包装在匿名函数中并手动调用(#(Integer/parseInt %)),否则为什么会出现以下异常?

clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to find static field: parseInt in class java.lang.Integer

3 个答案:

答案 0 :(得分:19)

java interop上的文档说明如下:

  

用于访问字段或方法成员的首选惯用表单   如上所述。实例成员表单适用于两个字段和   方法。 instanceField表单是字段和必需字段的首选   如果同时存在同名字段和0参数方法。他们   全部扩展到点运算符的调用(如下所述)   宏观扩张时间。扩展如下:   ...   (类名称/ STATICMETHOD   args *)==> (.Classname staticMethod args *)Classname / staticField ==>   (.Classname staticField)

所以你应该记住,Class/fieldName只是获取静态字段的糖,既不是静态方法调用,也不是引用静态方法(java方法实际上不是clojure函数),因此parseInt中没有静态字段Integer class,而(Class/fieldName arg)调用静态方法,它们是两个完全不同的操作,使用类似的含糖语法。

所以当你(map #(Integer/parseInt %) ["1" "2" "3" "4"])时,它会扩展为

(map #(. Integer parseInt %) ["1" "2" "3" "4"])

(你可以通过宏扩展轻松看到它),

(map Integer/parseInt ["1" "2" "3"])扩展为

(map (. Integer parseInt) ["1" "2" "3"])

当它试图获得一个字段(你认为它正在获取对方法的引用)时失败。

答案 1 :(得分:5)

usersInteger/parseInt类的静态方法,而不是clojure函数。每个clojure函数都编译为实现Integer接口的java类。 clojure.lang.IFn期望clojure函数(实现map接口)作为第一个参数,但IFn不是。

您可以在clojure repl。

中查看
Integer/parseInt

或许阅读this stackoverflow question可以帮助您了解正在发生的事情。

答案 2 :(得分:1)

您可能更喜欢在没有Java互操作的情况下执行此操作:

(map read-string ["1" "2"])

或更安全的变体:

(map clojure.edn/read-string ["1" "2"])

我个人更喜欢在Clojure代码中尽量减少使用Java。

至于为什么你不能只传递Java函数,因为map期望Clojure中的函数,而不是Java中的函数。