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

欢迎!请查看关于页面以获取更多关于如何使用这个功能的信息。

+16
Clojure
编辑

从JDK19+开始,以下内容在添加类型提示后不再具有反射性

(def x 10)
(Thread/sleep x)

有点棘手的是,在早期的JDK中上述操作没有反射,但是当你升级你的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中,通过执行脚本,通过执行`-main`函数,在变量和函数周围添加额外的包装器。
by
(~/clojure)-(!2001)-> clj
    Clojure 1.12.0-alpha4
    user=> (System/getProperty "java.version")
    "20.0.1"
    user=> (set! *warn-on-reflection* true)
    true
    user=> (def x 1000)
    #'user/x
    user=> (Thread/sleep x)
     Reflection warning, NO_SOURCE_PATH:1:1 - call to static method sleep on java.lang.Thread can't be resolved (argument types: unknown).
    nil
    user=>
by
在这种情况中,“正常”的行为应该是调用继续工作,但会反射地调用,如果你关心的话,可以用^long类型提示来纠正。然而,在Reflector中有一个细微的bug,导致它永远不会匹配较小的boxed numeric参数作为传递给接收更宽原语参数的方法的有效参数。

在这里,如果你在运行时传递一个boxed Integer,它将与Thread.sleep()方法匹配的所有方法都不会匹配。还有一个有用的知识是,当使用Cheshire读取JSON时,如果值在整数范围内,Cheshire会发出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 的可移植替代品。
如果只需要 sleep,则整个 core.async 拖进来显得有些过度了。
...