kotlin - 如何正确处理“使用”块中的异常?
问题描述
我希望Closeable
资源自动关闭,但同时我希望能够处理任何可能的异常。
考虑以下代码。
val opcPackage: OPCPackage
URI.create(document.fileUrl).toURL().openStream().use {
opcPackage = OPCPackage.open(it) // it = InputStream!
}
如果出现异常,InputStream 将自动关闭,这要归功于该use
块。但是,执行流程将被中断。
我仍然想处理这样的异常并对我的程序做一些事情(例如日志,发送信号 ecc ......)
以下不编译:
kotlin.runCatching {
URI.create(document.fileUrl).toURL().openStream().use {
opcPackage = OPCPackage.open(it)
}
}.onFailure {
// e.g. log and exit
}
这种方式违背了整个目的,use
因为我必须手动关闭Closeable
.
URI.create(document.fileUrl).toURL().openStream().use {
try {
opcPackage = OPCPackage.open(it)
} catch (ex: Exception) {
// ...
it.close()
return internalServerError()
}
}
在这一点上,我不妨简单地使用
val inputStream = URI.create(document.fileUrl).toURL().openStream()
try {
opcPackage = OPCPackage.open(inputStream)
inputStream.close()
} catch (ex: Exception) {
inputStream.close()
return internalServerError()
}
但我正在尝试正确使用 kotlin 功能。
这个用例的最佳片段是什么?
解决方案
use()
允许您在一个表达式中处理资源管理,即使在异常情况下也是如此。你仍然可以try-catch
绕过它:
val opcPackage = try {
URI.create(document.fileUrl).toURL().openStream().use {
OPCPackage.open(it)
}
} catch (e: SomeException) {
// e.g. log and exit
// no need to manually close here
// you do need to break control flow here or provide a default OPCPackage
}
您的变体runCatching
实际上也很好,您可能只需要将其用作表达式来初始化您的变量:
val opcPackageResult = runCatching {
URI.create(document.fileUrl).toURL().openStream().use {
OPCPackage.open(it)
}
}.onFailure {
// e.g. log and exit
}
// you still need to handle the Result type later
但是即使你在里面捕获了异常,use()
块的末尾仍然会为你关闭资源:
val opcPackage = URI.create(document.fileUrl).toURL().openStream().use {
try {
OPCPackage.open(it)
} catch (ex: Exception) {
return internalServerError()
}
}
或者你也可以使用普通try-catch-finally
的:
val inputStream = URI.create(document.fileUrl).toURL().openStream()
val opcPackage = try {
OPCPackage.open(inputStream)
} catch (ex: Exception) {
return internalServerError()
} finally {
inputStream.close()
}
推荐阅读
- oracle11g - Geoserver WFS-T 插入错误 (ORA-22816) 时使用基于数据库视图 ic 的层和 ID 的序列号
- php - 向 PHP 中的 2 个变量发送电子邮件
- accessibilityservice - Android Accessibility Service 在 Oreo 上运行一两天后停止工作
- python - 如何获取python图像中指定区域中的所有像素坐标?
- c++ - 包括
成功,包括 失败的 - c - c char[] to jstring printf 适用于 int 类型但不适用于字符串
- google-sheets - 谷歌表格连接多行单元格中的行
- python - Python Pyodbc 无法通过 executemany 返回第一个插入的 id
- c# - 如何解决错误:无法加载文件或程序集“Microsoft.VisualStudio.Threading”?
- warnings - 当 FutureBuilder 快照数据等于 0(零)时如何显示自定义警告?