尝试与资源: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 ""; } } } 

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

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 

query.evaluate()来自Sesame并实现AutoClosable 。 这是一个Kotlin错误,还是有一个原因为什么不起作用?


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

 <groupId>org.openrdf.sesame</groupId> <artifactId>sesame-runtime</artifactId> <version>4.0.2</version> 

    Kotlin目前的目标是Java 6,所以它的标准库不使用AutoCloseable接口。 use函数只支持Java 6 Closeable接口。 查看问题跟踪器以供参考。

    您可以在您的项目中创建use函数的副本,并修改它以使用AutoCloseable替换Closeable

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

    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" 

    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> 

    样品

     val resource: AutoCloseable = getCloseableResource() resource.use { r -> //play with r } 

    对于不支持“使用”功能的类,我已经完成了下一个自制的试用资源:

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