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}} 实际上创建两个对象 - 第一个是通过 * } 创建的,然后立即在它上调用 {{with-meta}},创建一个副本。

文档中有点描述了这种行为:"reify 总是实现 clojure.lang.IObj,并将表单的元数据转移到创建的对象中。"

0

评论者:wagjo

哦,所以终结器在reify对象中是不可以的。在我看来,这应该在文档中提一下。

0

评论由:gfredericks

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

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

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

`

(尚未实际运行此代码)

0

评论由:gfredericks

看起来{{reify}}生成的类总是有一个接受元数据参数的构造函数,因此销毁整个额外对象似乎是合理的。

我会继续在这方面挖掘。

0
参考文献:https://clojure.atlassian.net/browse/CLJ-1347(由wagjo汇报)
...