java kotlin extension-methods try-with-resources

java - Try-with-resources en Kotlin



extension-methods (3)

Cuando traté de escribir un código equivalente de try-with-resources en Kotlin, no funcionó para mí.

Intenté diferentes variaciones de lo siguiente:

try (writer = OutputStreamWriter(r.getOutputStream())) { // ... }

Pero ninguno funciona.

¿Alguien sabe qué se debe usar en su lugar? Aparentemente la gramática de Kotlin no tiene definición para tal construcción, pero puede ser que me falta algo. Define la gramática para try block de la siguiente manera:

try : "try" block catchBlock* finallyBlock?;


TL; DR

Sin sintaxis especial, pero use función

Kotlin, a diferencia de Java, no tiene una sintaxis especial para esto. En cambio, try-with-resources se ofrece como el use función de biblioteca estándar.

La implementación de use

@InlineOnly public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R { var closed = false try { return block(this) } catch (e: Exception) { closed = true try { this?.close() } catch (closeException: Exception) { } throw e } finally { if (!closed) { this?.close() } } }

¿Esta función se define como una extensión genérica en todos los Closeable? tipos. Closeable es la interface de Java que permite probar con recursos a partir de Java SE7 .
La función toma un block literal de función que se ejecuta en un try . Igual que con try-with-resources en Java, el Closeable se cierra por finally .

También las fallas que suceden dentro del block conducen a ejecuciones close , donde las posibles excepciones son literalmente "suprimidas" simplemente ignorándolas. Esto es diferente de try-with-resources , porque tales excepciones se pueden solicitar en la solución de interface .

Cómo usarlo

La extensión de use está disponible en cualquier tipo de Closeable , es decir, transmisiones, lectores, etc.

FileInputStream("filename").use { //use your stream by referring to `it` or explicitly give a name. }

La parte entre llaves es lo que se convierte en block en use (una lambda se pasa como argumento aquí). Una vez hecho el bloqueo, puede estar seguro de que FileInputStream se ha cerrado.


Hay una función de use en kotlin stdlib ( src ).

Cómo usarlo:

OutputStreamWriter(r.getOutputStream()).use { // by `it` value you can get your OutputStreamWriter it.write(''a'') }


Editar : la siguiente respuesta sigue siendo válida para Kotlin 1.0.x. Para Kotlin 1.1, se admite una biblioteca estándar que se dirige a Java 8 para admitir el patrón de recursos que se puede cerrar.

Para otras clases que no admiten la función "usar", he hecho los siguientes try-with-resources caseros:

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

Entonces puedes usarlo de la siguiente manera:

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