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

欢迎!请参阅关于页面了解有关这个网站更多信息。

+16
Clojure
编辑

从JDK19+开始,以下在不添加类型提示的情况下变得可反射

(def x 10)
(Thread/sleep x)

棘手的是,在较早的JDKs中上述内容不进行反射,但当你升级你的JDK时,反射就会开始。

如果你使用native-image,你的程序可能会因为缺少反射配置而开始失败。

如果有一个内置的sleep函数,可以接受一个数字,我们就不会忘记添加类型提示,并且它将跨JDKs保持一致地工作。

例如:

(ns clojure.java.misc)
(defn sleep [x]
  (if (number? x)
    (Thread/sleep (long x))
    ....)

clojure.java.misc来说,更好的名字是welcome。也许只要clojure.java,或者把此函数放到clojure.core中?

奇怪的是,我在1.11.1和JDK 20上完全无法复制这个问题 - 无论是在REPL中执行,还是通过执行脚本,通过构造主程序,或者对变量和函数进行额外的包装。
(~/clojure)-(!2001)-> clj
    Clojure 1.12.0-alpha4
    user=> (System/getProperty "java.version")
    "20.0.1"
    user=> (set! *warn-on-reflection* true)
    true
    用户=> (def x 1000)
    #'用户/x
    用户=> (Thread/sleep x)
     反射警告,NO_SOURCE_PATH:1:1 - 调用java.lang.Thread的静态方法sleep无法解析(参数类型:未知)。
    nil
    用户=>
在这种情况下,“正常”的现象应该是调用应该继续正常工作,但通过反射,您可以使用^long类型提示进行更正(如果您在乎)。然而,在Reflector中有一个细微的错误,它从未将较小的boxed数值参数匹配为合法传递给期望更广泛的原始参数类型的方法。

在这里,如果运行时传递boxed Integer对象,它将不会匹配Thread.sleep()的任何方法。了解这一点也很有用的是,Cheshire在读取JSON值且整数值在整数范围内时会生成boxed Integer对象(Cheshire中有关此问题的工单)。

结合这些情况,我们观察到,如果您使用Cheshire(或其他可能将配置文件作为Integer读取的具有此行为的工具),并且升级到新版本的Java,则可能不是废弃,而是在运行时出现反射错误。这似乎不能接受,因此我们创建了https://clojure.atlassian.net/browse/CLJ-2843并在Clojure 1.11.3和1.12.0-alpha10中修复了此问题。

1 答案

+1 投票
在core.async中有一个与Thread/sleep相同的可移植等效函数。
by
但如果只是需要sleep,引入整个core.async似乎有些过度。
...