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

欢迎!请参阅 关于 页面了解该功能如何工作。

0
编译器
即使它们是最终的(final),也可以为 defrecord 的字段设置 set!。


(defprotocol SetA (seta [x a]))
=> SetA
(defrecord X [a]
  SetA
  (seta [this newa]
    ; 下一条语句应该在编译时出错,但实际上不会出错。
    ; 然而 (set! a newa) 在编译时正确出错。
    (set! (.a this) newa)))
=> user.X
(def x (->X 0))
=> #'user/x
x
=> #user.X{:a 0}
(seta x 1) ;; 这不应运行。
=> 1
x
=> #user.X{:a 1}


这里有两个问题

# Clojure 编译器没有检测到 (set! (.a this) x) 是对最终字段的赋值。这可以通过增强来改进。Nicola Mometto 已经发现了原因,并相信他有一个简单的补丁。
# JVM 字节码验证器仅在类文件版本 9 及以上版本上执行必要的最终赋值检查: https://bugs.openjdk.java.net/browse/JDK-8159215 (Clojure 生成版本 6 的类文件。) 这不在我们手中。


方法:如果尝试设置最终字段的 set!,则在编译时让编译器失败。

补丁:0001-CLJ-2126-don-t-assign-final-fields.patch

1 答案

0
by
参考: https://clojure.atlassian.net/browse/CLJ-2126(由 favila 报告)
...