资源清理
使用
try
-finally
块进行资源清理是繁琐且容易出错的。Kotlin 的库函数可以为您管理清理。
就像您在 异常处理 中学到的一样,finally
子句会在 try
块退出时无论如何清理资源。但是如果在关闭资源时可能发生异常怎么办?你最终会在 finally
子句内部添加另一个 try
块。而且,如果在 try
内部抛出一个异常,并在关闭资源时抛出另一个异常,后者不应该遮盖前者。确保适当的清理变得非常混乱。
为了减少这种复杂性,Kotlin 的 use()
保证关闭资源的适当清理,使您不必编写手动的清理代码。
use()
可以与实现了 Java 的 AutoCloseable
接口的任何对象一起使用。它执行块内的代码,然后在对象上调用 close()
,无论您如何退出块,无论是正常退出(包括通过 return
),还是通过异常退出。
use()
会重新抛出所有的异常,因此您仍然必须处理这些异常。
与 use()
一起使用的预定义类在 Java 的 AutoCloseable
文档中可以找到。例如,要从 File
中读取行,我们可以将 use()
应用于 BufferedReader
。Check Instructions
(se06-ch02.md)中的 DataFile
继承了 java.io.File
:
// ResourceCleanup/AutoCloseable.kt
import atomictest.eq
import checkinstructions.DataFile
fun main() {
DataFile("Results.txt")
.bufferedReader()
.use { it.readLines().first() } eq
"Results"
}
useLines()
打开一个 File
对象,提取所有的行,并将这些行传递给目标函数(通常是一个 lambda):
// ResourceCleanup/UseLines.kt
import atomictest.eq
import checkinstructions.DataFile
fun main() {
DataFile("Results.txt").useLines {
it.filter { "#" in it }.first() // [1]
} eq "# ok"
DataFile("Results.txt").useLines { lines ->
lines.filter { line -> // [2]
"#" in line
}.first()
} eq "# ok"
}
- [1] 左侧的
it
是文件中所有行的集合,而右侧的it
是每一行。为了减少混淆,避免编写同时出现两个不同的it
的代码。 - [2] 使用命名参数可以避免
it
过多引起混淆。
所有操作都在 useLines()
lambda 内部完成;在 lambda 之外,文件内容不可用,除非您显式返回它们。当关闭文件时,useLines()
会返回 lambda 的结果。
forEachLine()
使得可以轻松地对文件中的每一行应用一个操作:
// ResourceCleanup/ForEachLine.kt
import checkinstructions.DataFile
import atomictest.*
fun main() {
DataFile("Results.txt").forEachLine {
if (it.startsWith("#"))
trace("$it")
}
trace eq "# ok"
}
forEachLine()
中的 lambda 返回 Unit
,这意味着您对行所做的任何操作必须通过副作用实现。在函数式编程中,我们更喜欢返回结果而不是副作用,因此 useLines()
比 forEachLine()
更符合函数式编程的方式。但是,forEachLine()
对于简单的实用程序来说是一种快速的解决方案。
您可以通过实现 AutoCloseable
接口来创建自己的类,以便与 use()
一起使用,该接口仅包含 close()
函数:
// ResourceCleanup/Usable.kt
package resourcecleanup
import atomictest.*
class Usable() : AutoCloseable {
fun func() = trace("func()")
override fun close() = trace("close()")
}
fun main() {
Usable().use { it.func() }
trace eq "func() close()"
}
use()
确保资源在创建资源的位置进行清理,而不是在您完成资源时强制您编写清理代码。
Exercises and solutions can be found at www.AtomicKotlin.com.