尝试使用资源:Kotlin中的"使用"扩展功能并不总是有效

Phi*_*ßen 10 java try-with-resources kotlin

我在Kotlin中表达Java的try-with-resources构造时遇到了一些麻烦.在我的理解中,作为实例的每个表达式都AutoClosable应该提供use扩展函数.

这是一个完整的例子:

import java.io.BufferedReader;
import java.io.FileReader;

import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;

public class Test {

    static String foo(String path) throws Throwable {
        try (BufferedReader r =
           new BufferedReader(new FileReader(path))) {
          return "";
        }
    }

    static String bar(TupleQuery query) throws Throwable {
        try (TupleQueryResult r = query.evaluate()) {
          return "";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Java-to-Kotlin转换器创建此输出:

import java.io.BufferedReader
import java.io.FileReader

import org.openrdf.query.TupleQuery
import org.openrdf.query.TupleQueryResult

object Test {

    @Throws(Throwable::class)
    internal fun foo(path: String): String {
        BufferedReader(FileReader(path)).use { r -> return "" }
    }

    @Throws(Throwable::class)
    internal fun bar(query: TupleQuery): String {
        query.evaluate().use { r -> return "" } // ERROR
    }
}
Run Code Online (Sandbox Code Playgroud)

foo工作正常,但代码中bar没有编译:

Error:(16, 26) Kotlin: Unresolved reference.
None of the following candidates is applicable
because of receiver type mismatch: 
public inline fun <T : java.io.Closeable, R>
???.use(block: (???) -> ???): ??? defined in kotlin.io
Run Code Online (Sandbox Code Playgroud)

query.evaluate()来自芝麻和工具AutoClosable.这是一个Kotlin bug,还是有一个原因导致它不起作用?


我正在使用IDEA 15.0.3和Kotlin 1.0.0-beta-4584-IJ143-12以及以下sasame-runtime版本:

<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-runtime</artifactId>
<version>4.0.2</version>
Run Code Online (Sandbox Code Playgroud)

yol*_*ole 19

Kotlin目前面向Java 6,因此其标准库不使用该AutoCloseable接口.该use函数仅支持Java 6 Closeable接口.请参阅问题跟踪器以供参考.

您可以use在项目中创建该函数的副本,并将其修改为替换CloseableAutoCloseable:

public inline fun <T : AutoCloseable, R> T.use(block: (T) -> R): R {
    var closed = false
    try {
        return block(this)
    } catch (e: Exception) {
        closed = true
        try {
            close()
        } catch (closeException: Exception) {
            e.addSuppressed(closeException)
        }
        throw e
    } finally {
        if (!closed) {
            close()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为这有效@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")(e as java.lang.Throwable).addSuppressed(closeException) (2认同)

Quy*_*ang 5

Kotlin 1.1+有一个标准库,以Java 8为目标,支持Closeable resource模式 - kotlin-stdlib-jre8

摇篮

compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.1"
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:1.1.1"
Run Code Online (Sandbox Code Playgroud)

Maven的

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib</artifactId>
    <version>1.1.1</version>
</dependency>
<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib-jre8</artifactId>
    <version>1.1.1</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

样品

val resource: AutoCloseable = getCloseableResource() 
resource.use { r -> //play with r }
Run Code Online (Sandbox Code Playgroud)

  • `kotlin-stdlib-jre8` 现已弃用,替换为 [kotlin-stdlib-jdk8](https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib-jdk8)。此外,Java 7中引入了“AutoCloseable”,因此“jdk7”版本就足够了。由于必须包含这些库的原因,Kotlin 默认目标是 Java 6。 (2认同)