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

欢迎!有关此功能的更多信息,请参阅关于页面。

+16
Clojure
编辑

从JDK19+版本开始,以下不需要添加类型提示即可反射

(def x 10)
(Thread/sleep x)

难点在于,在较早的JDK中上述代码没有进行反射,但当你升级JDK时,反射开始

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

将会有一个接受数字的内部sleep函数,这样我们就不必忘记添加类型提示,并且它在各个JDK上都保持一致

例如。

(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中、通过执行脚本、通过执行-a函数、在变量和函数周围添加额外的包装器。
(~/clojure)-(!2001)-> clj
    Clojure 1.12.0-alpha4
    user=> (System/getProperty "java.version")
    "20.0.1"
    用户=> (set! *warn-on-reflection* true)
    true
    用户=> (def x 1000)
    #'用户/x
    用户=> (Thread/sleep x)
     反射警告,NO_SOURCE_PATH:1:1 - 无法解决对java.lang.Thread的静态方法sleep的调用(参数类型:未知)。
    nil
    用户=>
by
在这种情况下,“正常”的情况应该是调用应该继续工作,但通过反射来进行,你可以使用^long类型提示进行纠正(如果你关心)。然而,在Reflector中有一个微妙的错误,使得它从不将更小的boxed numeric参数匹配为传递给接受更宽原始参数的方法的合法参数。

这里,如果你在运行时传递一个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
by
by
在core.async中存在与Thread/sleep的类似的可移植函数。
如果您只需要sleep功能,导如整个core.async有些过度了。
...