如何在Kotlin中实现finalize()方法?

43

今天我在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(); }
}

Kotlin:

class Resource: FinalizedCloseable(), Closeable {
    fun close() {}
    override fun finalize() { close()}
}

但这种解决方法需要一个超类。如果下一次我的其他Resource已经有一个超类,那么使用这种解决方法将需要大量的样板文件。


编辑:现在我知道如何实现finalize(),但IDEA kotlin插件不够聪明,无法知道这是一个finalizer,因此没有标记它并发出警告。经过一番挣扎,我找到了如何抑制这些警告,并且想分享一下:

class C {
    @Suppress("ProtectedInFinal", "Unused") protected fun finalize() {}
}

1
https://kotlinlang.org/docs/reference/java-interop.html#finalize - ean5533
@ean5533 嗯,我没有完全阅读那份冗长的Interop文档,现在是我的惩罚。无论如何,还是谢谢你。 - glee8e
你读过《Java 8中finalize()在强可达对象上被调用》吗?底线是,最好根本不要这样做。除非你的代码涉及使用native代码直接处理系统资源,否则你的类将成为另一个实际表示资源并让包装器的可达性决定实际资源(可能仍然可达和正在使用)寿命的对象的包装器,这意味着会出现严重问题... - Holger
@Holger 谢谢你指出这个问题。但我的问题是只有一部分资源被一个处理程序使用,其余的将被存储在池中,直到其他处理程序甚至失败的处理程序再次拉取。因此,偶尔失败一次并不是我软件的问题。然而,我不想冒险失去任何一个资源,否则就会有300个人冲进我的前门。顺便说一下,在我的机器上,你链接中的示例中的 FinalizeThis::finalize 从未被调用过 - glee8e
这都是与JVM相关的。除了可能被过早调用的风险外,还存在一个巨大的可能性,就是根本不会被执行,至少不会在关键时间内被执行。垃圾回收旨在管理内存,只要有足够的内存或垃圾收集器可以轻松地回收不需要 finalization 的对象的存储空间,它可能不会运行或只会忽略具有 finalizers 的对象。同时,还存在多线程问题... - Holger
1个回答

72

官方文档中有相关介绍。

要重写 finalize(),只需声明即可,无需使用 override 关键字:


class C {
    protected fun finalize() {
        // finalization logic
    }
}

1
你比我快几秒钟 :) - ean5533
2
好的,它能工作,但如何在其中调用 super.finilize()?我反编译了生成的Java代码,但那里没有超类调用。 - don11995
2
@Boris 是的,在您扩展具有此代码的类的情况下是需要的。但是,如果您从中继承的类没有覆盖它,则不需要。但是,如果您从中继承的类允许它,您应该能够调用 super.finalize,所有内容都可以正常工作。 - android developer
1
但是它能工作吗?当对象准备好被释放时,这个函数会运行吗? - Aaron Lee
1
@AaronLee 是的,它有效。看起来有点奇怪,但当对象被释放时确实会调用它。 - Trevor
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接