【发布时间】:2017-10-02 17:00:29
【问题描述】:
今天我在 kotlin 中实现 Closeable,就像我过去在 java 中所做的那样,我想实现 finalize() 作为最后的后备手段,以防客户端代码忘记关闭它,渲染未回收的关键资源。我认为这个资源足够重要,可以添加这个后备,尽管这个后备不可靠。但是,kotlin.Any 没有声明 finalize 方法,这意味着我不能简单地这样做:
class Resource: Closeable {
fun close() {}
override fun finalize() { close()}
}
这不好,至少没有它应该的那么好。现在我恢复到纯 Java 作为一种解决方法。有谁知道如何在纯 Kotlin 中做到这一点?
PS:我目前的解决方法:
FinalizedCloseable.java:
public abstract class FinalizedCloseable implement Closeable {
@Override protected void finalize() { close(); }
}
科特林:
class Resource: FinalizedCloseable(), Closeable {
fun close() {}
override fun finalize() { close()}
}
但是这种解决方法需要一个超类。如果下次我的另一个 Resource 已经有了一个超类,那么如果没有大量样板文件,这个解决方法就行不通。
编辑:现在我知道如何实现 finalize(),但是 IDEA kotlin 插件不够聪明,无法知道这是一个终结器,因此用一些警告标记它。苦苦挣扎了一阵子,终于找到了如何抑制这些警告,特地分享一下:
class C {
@Suppress("ProtectedInFinal", "Unused") protected fun finalize() {}
}
【问题讨论】:
-
@ean5533 呃,我没有完整阅读那么长的互操作文档,现在是我的惩罚。还是谢谢你。
-
你读过“finalize() called on strongly reachable object in Java 8”吗?最重要的是,你最好不要这样做。除非您的代码涉及直接处理系统资源的
native代码,否则您的类将成为实际代表资源的另一个对象的包装器,并让包装器的可访问性确定实际资源的生命周期(可能仍然可以访问并且使用中),意味着提出严重的问题…… -
@Holger 感谢您指出这一点。但我的问题是,只有一部分资源被一个处理程序消耗,其余的将存储在一个池中,直到另一个处理程序,甚至失败的处理程序再次被拉出。因此,偶尔失败一次在我的软件中不是问题。但是,我不想冒险失去他们中的任何一个,否则会有三百人的军队撞到我的前门。顺便说一句,在我的机器上,链接中示例中的
FinalizeThis::finalize在我的机器上从未调用过一次。 -
这都是 JVM 特定的。除了过早被调用的危险之外,还有很大的可能永远不会被执行,至少不会在关键时间范围内。垃圾收集旨在管理内存,只要有足够的内存或垃圾收集器对回收不需要终结的对象的存储感到满意,它就可能不会运行或只是忽略具有终结器的对象。还有多线程问题……