6

Kotlinuse为对象提供了函数Closeable,但似乎他们忘记了AutoCloseable(例如,DB 准备好的语句)与 try-with-resources 的完整 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 的新手,我想知道我自己的解决方案中是否遗漏了一些重要的东西,这些东西可能会给我在生产环境中带来问题/泄漏。

4

3 回答 3

7

您的实现可以正常工作,但它不同于标准的 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在他的评论 中指出的那样,kotlin.Throwable它不包含addSuppressed(Throwable)方法,因此我们必须强制kotlin.Throwable转换才能java.lang.Throwable使代码正常工作。

于 2016-03-28T10:58:40.433 回答
2

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

从源复制

于 2017-05-20T05:40:11.010 回答
0

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

于 2016-03-28T14:48:19.463 回答