168

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

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

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

但两者都不起作用。

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

try : "try" block catchBlock* finallyBlock?;
4

5 回答 5

252

kotlin 标准库( src)中有use-function 。

如何使用它:

OutputStreamWriter(r.getOutputStream()).use {
    // by `it` value you can get your OutputStreamWriter
    it.write('a')
}
于 2014-11-17T18:34:07.873 回答
63

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

Kotlin 与 Java 不同,对此没有特殊的语法。相反,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 中的try-with-resources相同,在.
blocktryCloseablefinally

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

如何使用它

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

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

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

于 2017-10-20T06:40:08.387 回答
16

编辑:以下响应对 Kotlin 1.0.x 仍然有效。对于 Kotlin 1.1,支持以 Java 8 为目标的标准库以支持可关闭资源模式。

对于其他不支持“使用”功能的类,我做了以下自制的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)
    }
}
于 2016-03-28T10:21:17.557 回答
1

由于这篇 StackOverflow 帖子接近“kotlin closeable example”的当前搜索结果的顶部,但其他答案(也没有官方文档)都没有清楚地解释如何扩展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 Playground 中的此示例。

于 2020-04-13T16:41:32.733 回答
0

我强烈建议对课程使用 AutoCloseable。

AutoCloseable 对象在退出资源规范标头中已为其声明对象的 try-with-resources 块时自动调用。

例子:

class Resource : AutoCloseable {
    fun op1() = println("op1")
    override fun close() = println("close up.")
}

在主要功能中:

Resource().use {
    it.op1()
}

输出:

> op1
close up.
于 2020-12-21T07:28:36.100 回答