我自己的解决方案,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.Throwablejava.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()