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