我自己针对 Kotlin 缺少资源尝试的解决方案

My own solution for Kotlin's try-with-resources absence

Kotlin 为 Closeable 对象提供了 use 函数,但他们似乎忘记考虑 AutoCloseable (例如数据库准备语句)用于 try-with-resources full Java相当于.

我已经实施了下一个 "home-made" 解决方案:

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 的新手,我想知道我自己的解决方案中是否遗漏了一些可以在生产环境中为我提供 problems/leakages 的重要内容。

您的实现可以正常工作,但它不同于标准的 try-with-resources 实现。如果你想让它像 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 pointed out in his kotlin.Throwable 不包含 addSuppressed(Throwable) 方法,因此我们必须将 kotlin.Throwable 转换为 java.lang.Throwable 以使代码正常工作。

我想你想要的是 use() 定义在 Closable.

自 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)
    }
}

复制自source