我想在一个类实例存在的整个过程中打开一个FileWriter。所以我需要在析构函数中关闭它。但是如何在Scala中指定析构函数?
答案 0 :(得分:10)
您可能有兴趣查看Josh Suereth的scala-arm项目,该项目仅针对此使用来源提供基于monadic和delimited-continuation的资源管理:http://github.com/jsuereth/scala-arm
如果你真的认为你需要一个析构函数(也就是因为你认为你需要创建该对象,然后将其交给它再也不会再看到它)我建议重新考虑你的应用程序架构......根本就没有在JVM上可靠地工作的方法。
答案 1 :(得分:8)
这是我经常使用的一种方便的实用方法。我发现它很好地整理了我的代码。
def closer [T, C <: Closeable] (c : C) (f : C => T) : T =
try f (c)
finally c.close
使用它很简单。下面的示例使用来自URLConnection的输入流。您可以创建任何任意流,而不是connection.getInputStream(或者更常见的是,任何可任意的可关闭对象)。
val bytes = closer (connection.getInputStream) { istream =>
val bytes = new ByteArrayOutputStream ()
val buffer : Array [Byte] = new Array (1024)
Iterator.continually (istream read buffer).takeWhile (_ > 0).foreach (bytes write (buffer, 0, _))
bytes.toByteArray
}
此版本将使用close方法操作(无需实现Closeable或其他任何内容)。
def autoClose[R <: {def close()}, T](resource: R)(use: R => T): T = {
try use(resource)
// Don't want an NPE here masking an exception from use.
finally Option(resource).foreach(_.close())
}
以下是一些隐含的类来完成这项工作。
implicit class AutoCloseBracket[R <: Closeable](resource: R) {
def autoClose[V](use: R => V): V = try use(resource) finally resource.close()
}
implicit class AutoCloseableBracket[R <: AutoCloseable](resource: R) {
def autoClose[V](use: R => V): V = try use(resource) finally resource.close()
}
答案 2 :(得分:7)
Scala没有析构函数。它有终结器,如Java,但它们根本不是一回事。还有一个有趣的博客系列在此处模拟Scala中的C#using
关键字:
答案 3 :(得分:2)
如上所述,Java有一个专门针对IO的现有Closeable
接口,您可以采用。这不会提供任何糖,但它会帮助人们正确使用你的课程。
在Java 7中,Closeable
将是AutoCloseable
的子接口。 AutoCloseable
是一个更通用的接口,用于在使用后需要关闭的任何资源,同时可能引发异常。它是Java 7中计划的Automatic Resource Management支持的一部分。与您的问题不太相关(因为您使用的是Scala),也应该是新的Java syntax(现有try块的扩展)对于这种情况。