2024 Clojure状态调查中分享您的想法!

欢迎!请查阅关于页面以了解此功能的一些更多信息。

0
Java互操作

此处使用Java 1.8(Oracle或Open JDK)

`
weird-abs.core=> (Math/abs -10000000000000)
10000000000000
weird-abs.core=> (def a -10000000000000)

'weird-abs.core/a

weird-abs.core=> (Math/abs a)
1316134912
`

在Java 1.7中,返回预期的结果(10000000000000)。

原因:似乎调用了Math.abs(int)。反射程序考虑了int和long版本,但Java 1.7和1.8以不同的顺序返回这些签名,并且选择了第一个找到的签名。

解决方案:使用提示或强制类型转换来通知反射程序选择哪一个。

6个答案

0

评论由:alexmiller

在第一种情况下,-10000000000000是long类型,编译器明确找到Math.abs(long)。

在第二种情况下,a是Object类型,所有abs签名都被考虑(这在Reflector.invokeMatchingMethod中)。在Java 1.7和1.8中,都找到了"一致的"long和int签名。

在Java 1.7中,首先找到long版本并被处理为匹配项,然后检查int,Compiler.subsumes((link: int), (link: long))返回false,导致保留long方法作为匹配项。

在Java 1.8中,首先找到int版本并被处理为匹配项,然后检查long,Compiler.subsumes((link: long), (link: int))返回false,导致保留int方法作为匹配项。

这两个都在两个JDK上返回false

(Compiler/subsumes (into-array [Long/TYPE]) (into-array [Integer/TYPE])) (Compiler/subsumes (into-array [Integer/TYPE]) (into-array [Long/TYPE]))

所以实际的差异只是考虑的顺序,这是JDK特定的。

可以考虑以某些规范方式对这些签名进行排序,以使这种行为一致,或者可以以某种方式表达对这两个签名之间的偏好。

无论如何,通过提示或类型转换来消除这里的反射可以解决该问题——我认为在这种情况下,Java 7中出现正确结果只能是运气而不是意图。

0

评论由:bronsa 发布

在我看来,cljure的反射器在可选参数多于一个时随机选择一个的行为既非常不符合直觉,也令人不快。

在我看来,唯一理智的方法应该是
- 如果可能,选择最具体的类型(例如,如果可用的类型是 (Object, CharSequence, String),而反射的类型是 StringBuffer,我们使用 CharSequence 而不是 Object)。
- 如果可能,选择最宽的原始类型(例如,在这种情况下我们会使用 long 而不是 int)
- 如果无法解决冲突,则抛出 “更多匹配方法找到” 异常(在某些情况下已经这样做)

(我还是很怕之前阅读/修复 Reflector.java 和 Compiler.java 中的复杂野兽般的反射部分的经验,所以我提出这个建议,但没有任何意图自己工作在这个上面 :))

0

评论由:alexmiller

我认为子集检查实际上是试图做你的选项 #1——这是一个两种情况下的参数类型没有层次关系的情况。很可能 #2 会更合理——表达偏好,尽管当然有 cases 中“最广泛”无意义的情况,所以不是很清楚这个一般形式是什么样的。

0

评论由:bronsa 发布

为了澄清,那不是一个不同选项的列表,而是一系列要采取的步骤。
即,如果可能从层次结构中选择最具体的类型,那么就做这件事,否则如果类型是原始类型,就选择最宽的类型,否则失败

0

评论由:jafingerhut 发布

可能与 CLJ-1212 相同,或者至少有一些共同点。

0
参考:https://clojure.atlassian.net/browse/CLJ-1921(由 alexmiller 报告)
...