Kotlin的尝试资源


147

当我尝试try用Kotlin 编写与Java相同的带有资源的代码时,它对我不起作用。

我尝试了以下各种变化:

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

但是两者都不起作用。

有谁知道应该用什么代替?显然Kotlin语法没有为这种结构定义,但也许我遗漏了一些东西。它为try块定义语法,如下所示:

try : "try" block catchBlock* finallyBlock?;

Answers:


219

use功能全在科特林STDLIB(SRC)。

如何使用它:

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

3
我非常喜欢扩展方法。您可以做很多事情,而无需其他语言功能。
Kirill Rakhman 2014年

20
除此之外,实际上还有一个扩展属性也可以获取OutputStreamWriterr.outputStream.writer.use { ... }
Damian Wieczorek

3
链接到演示use扩展的参考文档:kotlinlang.org/docs/reference/…–
Javaru

1
如何更好地使用多重“使用”? FileOutputStream(into).use { val mergingStream = BufferedOutputStream(it).use { } }
Ponomarenko Oleh,

43

TL; DR:没有特殊的语法,只是一个函数

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

FileInputStream("filename").use { fis -> //or implicit `it`
   //use stream here
} 

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的接口,允许从Java SE7开始使用try-with-resources。 该函数采用一个函数文字,该文字在中执行。同与尝试,以资源在Java中,被关闭的。
blocktryCloseablefinally

内部发生的故障block也会导致close执行,在这种情况下,只要忽略它们,就可以“抑制”可能的异常。try-with-resources不同,因为可以在Java解决方案中请求此类异常。

如何使用它

use扩展适用于任何Closeable类型,即流,阅读器等。

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

大括号中的部分变成blockuse(在这里lambda作为参数传递)。完成该块后,可以确保FileInputStream已将其关闭。


16

编辑:以下响应对于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)
    }
}

1
这不能正确地处理从finally子句引发的异常,这是将try-with-resources添加到Java的原因之一。这只是一个简单的try/finally街区
NikolaMihajlović,

0

由于此StackOverflow帖子位于“ kotlin可关闭示例”当前搜索结果的顶部附近,而其他答案(也非官方文档)都没有明确说明如何扩展Closeable(aka java.io.Closeable),因此我想添加一个示例如何使自己的课程扩展Closeable。它是这样的:

import java.io.Closeable

class MyServer : Closeable {
    override fun close() {
        println("hello world")
    }
}

然后使用它:

fun main() {
    val s = MyServer()
    s.use {
        println("begin")
    }
    println("end")
}

此处的Kotlin游乐场中查看此示例。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.