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

欢迎!有关此如何工作,请参阅 关于 页面以获取更多信息。

0
Clojure

即使对象仍然可到达,也会为具象对象调用 finalize。它会在适当的时候再次被调用。

`
user=> (def x (reify Object (finalize [o] (println "OH MY!"))))

'user/x

user=> (System/gc)
nil
OH MY!
user=> x

<user$reify1496 user$reify1496@53fb35af>

user=> (System/gc)
nil
user=> (def x nil)

'user/x

user=> (System/gc)
nilOH MY!
`

Deftype 看起来工作得很好

`
user=> (deftype T [] Object (finalize [o] (println "great success")))
user.T
user=> (def y (->T))

'user/y

user=> (System/gc)
nil
user=> (def y nil)

'user/y

user=> (System/gc)
great success
`

6 答案

0

评论者:alexmiller

注意:调用 System/gc 并不一定在第一次尝试时触发 finalizers 的执行 - 有时我需要多次尝试才能成功。您可能认为 System/runFinalizers 会这样做,但我在这件事上完全没运气。

0

评论者:gfredericks

{{reify}} 实际上创建了两个对象——第一个由 * 创建,然后 {{reify}} 立即对其进行 {{with-meta}} 调用,创建一个副本。

文档字符串大致描述了这种行为:“reify 总是实现 clojure.lang.IObj 并将表单的元数据传输到创建的对象中。”

0

评论者:wagjo

哦,所以在reify中finalizer是不允许的。我认为应该将这一点写入文档。

0

评论者:gfredericks

为了好玩,你可以做一些有点花哨的事情,比如

`
^::second-object
(reify Object
(finalize [self]

(when (::second-object (meta self))
  ...)))

`

尚未实际运行此代码)

0

评论者:gfredericks

看起来{{reify}}生成的类总是有一个接受元数据参数的构造函数,所以彻底消除额外的对象似乎并不成问题。

我会继续深入挖掘这个问题。

0
参考:[https://clojure.atlassian.net/browse/CLJ-1347](https://clojure.atlassian.net/browse/CLJ-1347) (由wagjo报告)
...