2016-03-28 21 views
5

Kotlin zapewnia funkcję use dla obiektów Closeable, ale wygląda na to, że zapomniały rozważyć AutoCloseable (np. Instrukcje przygotowane przez DB) dla try-with-resources pełnego odpowiednika Javy.Moje własne rozwiązanie dla próby braku zasobów Kotlina

Mam realizowane następnego "home-made" rozwiązanie:

inline fun <T:AutoCloseable,R> trywr(closeable: T, block: (T) -> R): R { 
    try { 
     return block(closeable); 
    } finally { 
     closeable.close() 
    } 
} 

Wtedy można go używać następny sposób:

fun countEvents(sc: EventSearchCriteria?): Long { 
    return trywr(connection.prepareStatement("SELECT COUNT(*) FROM event")) { 
     var rs = it.executeQuery() 
     rs.next() 
     rs.getLong(1) 
    } 
} 

Jestem nowy Kotlin i chciałbym wiedzieć, czy brakuje mi czegoś ważnego w swoim własnym rozwiązaniu, które mogłoby spowodować problemy/wycieki w środowisku produkcyjnym.

+3

Powodem nie obsługują 'AutoClosable' out-of-the-box jest to, że są one jeszcze do wdrożenia wsparcia Java8, a także wspierać zajęcia JDK8 – voddan

+0

zawsze można skopiuj źródło dla 'use' i zmień' Closeable' na 'AutoCloseable' (zobacz [ReadWrite.kt: 145-177] (https://github.com/JetBrains/kotlin/blob/8549ec7645ff6db4d5fede2c43034be66683561a/libraries/stdlib/src/ kotlin/io/ReadWrite.kt # L145-L177). – mfulton26

+0

Rozważ użycie java 8 dla wzorca. Możesz go znaleźć tutaj http://stackoverflow.com/a/43269795/2463695 –

Odpowiedz

7

Twoje wdrożenie będzie działać dobrze, ale różni się od standardowej implementacji try-with-resources. Jeśli chcesz, aby pracować jak w Javie trzeba zrobić coś takiego:

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:

Jak mfulton26 wskazał w swoim commentkotlin.Throwable nie zawiera addSuppressed(Throwable) sposób więc mamy do oddania kotlin.Throwable do java.lang.Throwable, aby kod działał.

+1

Nie ma 'addSuppress (Throwable)' metoda na 'kotlin.Thro wable' i nie możesz użyć 'java.lang.Throwable' w próbie catch Kotlin, więc w jaki sposób ten kod się kompiluje (poza' s/throwble/throwable/')? – mfulton26

+0

@ mfulton26 Wierzę, że to powinno być 'Wyjątkiem' zamiast' Throwable'. – Kiskae

+1

@ mfulton26 Dzięki, to jest dobra uwaga. Zaktualizowano kod, aby go skompilować. – Michael

0

Myślę, że to, czego chcesz, to use() zgodnie z definicją pod numerem Closable.

2

Ponieważ Kotlin 1.1, .use ma implementację 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) 
    } 
} 

Skopiowane z source