首页 文章

在Kotlin尝试资源

提问于
浏览
108

当我尝试在Kotlin中编写等效的try-with-resources代码时,它对我不起作用 .

我尝试了以下不同的变体:

try (writer = OutputStreamWriter(r.getOutputStream())) {
    // ...
}

但都不起作用 .

有谁知道应该使用什么?显然Kotlin语法doesn't have definition对于这样的构造,但可能是我遗漏了一些东西 . 它定义了try块的语法,如下所示:

try : "try" block catchBlock* finallyBlock?;

3 回答

  • 165

    kotlin stdlib(src)中有 use 功能 .

    如何使用它:

    OutputStreamWriter(r.getOutputStream()).use {
        // by `it` value you can get your OutputStreamWriter
        it.write('a')
    }
    
  • 17

    TL; DR

    No special syntax, but use function

    与Java相反,Kotlin没有特殊的语法 . 相反,try-with-resources,作为标准库函数 use 提供 .

    使用实现

    @InlineOnly
    public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
        var closed = false
        try {
            return block(this)
        } catch (e: Exception) {
            closed = true
            try {
                this?.close()
            } catch (closeException: Exception) {
            }
            throw e
        } finally {
            if (!closed) {
                this?.close()
            }
        }
    }
    

    此函数被定义为所有 Closeable? 类型的通用扩展 . Closeable 是Java的interface,允许从Java SE7开始尝试使用资源 .
    该函数采用函数文字 block ,它在 try 中执行 . 与Java中的try-with-resources相同, Closeablefinally 中得到 closed .

    block 内部发生的故障也导致 close 执行,其中可能的异常只是忽略它们而实际上是"suppressed" . 这与try-with-resources不同,因为可以在Java的解决方案中请求此类异常 .

    如何使用它

    use 扩展名可用于任何 Closeable 类型,即流,阅读器等 .

    FileInputStream("filename").use {
       //use your stream by referring to `it` or explicitly give a name.
    }
    

    大括号中的部分是 use 中的 block (这里将lambda作为参数传递) . 块完成后,您可以确定 FileInputStream 已关闭 .

  • 29

    Edit :以下响应对Kotlin 1.0.x仍然有效 . 对于Kotlin 1.1,支持一个标准库,它以java 8为目标,支持可关闭的资源模式 .

    对于不支持“use”功能的其他类,我已经完成了以下自制的try-with-resources:

    package info.macias.kotlin
    
    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)
        }
    }
    

相关问题