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

怎甘沉沦 提交于 2019-12-01 02:15:16

问题


Kotlin provides the use function for Closeable objects, but it seems they forgot to consider AutoCloseable (e.g. DB prepared statements) for the try-with-resources full Java equivalent.

I've implemented the next "home-made" solution:

inline fun <T:AutoCloseable,R> trywr(closeable: T, block: (T) -> R): R {
    try {
        return block(closeable);
    } finally {
        closeable.close()
    }
}

Then you can use it the next way:

fun countEvents(sc: EventSearchCriteria?): Long {
    return trywr(connection.prepareStatement("SELECT COUNT(*) FROM event")) {
        var rs = it.executeQuery()
        rs.next()
        rs.getLong(1)
    }
}

I'm new to Kotlin and I would like to know if I'm missing something important in my own solution that could give me problems/leakages in a production environment.


回答1:


Your implementation will work fine but it's different from a standard try-with-resources implementation. If you want it to work like in Java you should do something like that:

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

UPDATE:

As mfulton26 pointed out in his comment kotlin.Throwable doesn't contain addSuppressed(Throwable) method so we have to cast kotlin.Throwable to java.lang.Throwable to make the code work.




回答2:


Since Kotlin 1.1, .use has an AutoCloseable implementation.

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

Copied from source




回答3:


I think what you want is use() as defined on Closable.



来源:https://stackoverflow.com/questions/36260556/my-own-solution-for-kotlins-try-with-resources-absence

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!