我自己的解决方案,Kotlin的尝试与资源缺席
Kotlin提供了可Closeable
对象的use
函数,但似乎忘记考虑AutoCloseable
(例如,数据库准备语句)的资源尝试与Java完全等效。
我实施了下一个“自制”解决方案:
inline fun <T:AutoCloseable,R> trywr(closeable: T, block: (T) -> R): R { try { return block(closeable); } finally { closeable.close() } }
那么你可以用下一个方法:
fun countEvents(sc: EventSearchCriteria?): Long { return trywr(connection.prepareStatement("SELECT COUNT(*) FROM event")) { var rs = it.executeQuery() rs.next() rs.getLong(1) } }
我是Kotlin的新手,我想知道是否在自己的解决方案中丢失了一些重要的东西,这可能会在生产环境中给我带来问题/泄漏。
你的实现可以正常工作,但与标准的尝试资源实现不同。 如果你想让它像Java一样工作,你应该这样做:
inline fun <T : AutoCloseable, R> trywr(closeable: T, block: (T) -> R): R { var currentThrowable: java.lang.Throwable? = null try { return block(closeable) } catch (throwable: Throwable) { currentThrowable = throwable as java.lang.Throwable throw throwable } finally { if (currentThrowable != null) { try { closeable.close() } catch (throwable: Throwable) { currentThrowable.addSuppressed(throwable) } } else { closeable.close() } } }
更新 :
正如mfulton26在他的评论中指出kotlin.Throwable
不包含addSuppressed(Throwable)
方法,所以我们必须将kotlin.Throwable
为java.lang.Throwable
来使代码工作。
由于Kotlin 1.1, .use
有一个AutoCloseable
实现。
@SinceKotlin("1.1") @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") @kotlin.internal.InlineOnly public inline fun <T : AutoCloseable?, R> T.use(block: (T) -> R): R { var exception: Throwable? = null try { return block(this) } catch (e: Throwable) { exception = e throw e } finally { this.closeFinally(exception) } }
从源复制
我想你想要的就是在Closable
定义的use()
。