2016-03-28 44 views
5

Kotlin为Closeable对象提供了use函数,但似乎忘记考虑AutoCloseable(例如DB准备语句)的资源尝试与Java完全等效。我自己的解决方案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) 
    } 
} 

我是新来的科特林,我想了解我是否在自己的解决方案中丢失了一些重要的东西,这可能会在生产环境中给我带来问题/泄漏。

+3

他们之所以不支持'AutoClosable'出的现成的是,他们仍然实现Java8支持,以及支持JDK8类 – voddan

+0

你总是能复制复制'use'的源代码并将'Closeable'改为'AutoCloseable'(参见[ReadWrite.kt:145-177](https://github.com/JetBrains/kotlin/blob/8549ec7645ff6db4d5fede2c43034be66683561a/libraries/stdlib/src/) kotlin/io/ReadWrite.kt#L145-L177) – mfulton26

+0

考虑使用java 8作为模式,你可以在这里找到http://stackoverflow.com/a/43269795/2463695 –

回答

7

你的实现将很好地工作,但它不同于标准的尝试资源实现。如果你想它的工作就像在Java中,你应该做这样的事情:

inline fun <T : AutoCloseable, R> trywr(closeable: T, block: (T) -> R): R { 
    var currentThrowable: java.lang.Throwable? = null 
    try { 
    return block(closeable) 
    } catch (throwable: Throwable) { 
    currentThrowable = throwable as java.lang.Throwable 
    throw throwable 
    } finally { 
    if (currentThrowable != null) { 
     try { 
     closeable.close() 
     } catch (throwable: Throwable) { 
     currentThrowable.addSuppressed(throwable) 
     } 
    } else { 
     closeable.close() 
    } 
    } 
} 

UPDATE

由于mfulton26在他commentkotlin.Throwable指出不包含addSuppressed(Throwable)方法,所以我们必须要投kotlin.Throwablejava.lang.Throwable以使代码正常工作。

+1

没有'addSuppress(Throwable)''方法'kotlin.Thro wable',你不能在Kotlin try-catch中使用'java.lang.Throwable',所以这段代码如何编译(除了's/throwble/throwable /')? – mfulton26

+0

@ mfulton26我相信它应该是'Exception'而不是'Throwable'。 – Kiskae

+1

@ mfulton26谢谢,这是一个很好的观点。更新了代码以使其编译。 – Michael

0

我认为你想要的是在Closable上定义。

2

由于Kotlin 1.1,.use具有AutoCloseable实现。

@SinceKotlin("1.1") 
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") 
@kotlin.internal.InlineOnly 
public inline fun <T : AutoCloseable?, R> T.use(block: (T) -> R): R { 
    var exception: Throwable? = null 
    try { 
     return block(this) 
    } catch (e: Throwable) { 
     exception = e 
     throw e 
    } finally { 
     this.closeFinally(exception) 
    } 
} 

source

相关问题