Quiero ejecutar el código de limpieza después de que se complete un determinado bloque de código, independientemente de las excepciones. Este no es un recurso que se puede cerrar y no puedo usar try-with-resources (o el use de Kotlin). En Java, podría hacer lo siguiente:
try { // ... Run some code } catch(Exception ex) { // ... Handle exception } finally { // ... Cleanup code }¿Es equivalente el siguiente código de Kotlin?
runCatching { // ... Run some code }.also { // ... Cleanup code }.onFailure { // ... Handle exception }Editar: manejo de excepciones repetitivo agregado: mi preocupación es garantizar que se ejecute el código de limpieza y la capacidad de mantenimiento.
Hay una diferencia importante, donde el código dentro runCatching contiene un retorno anticipado. Un bloque de finally se ejecutará incluso después de un retorno , mientras que also tiene tal magia.
Este código, cuando se ejecuta, no imprimirá nada:
fun test1() runCatching { return }.also { println("test1") } }Este código, cuando se ejecuta, imprimirá "test2":
fun test2() { try { return } finally { println("test2") } }Hay una gran diferencia entre ambos ejemplos de código. try...finally propaga excepciones mientras que runCatching().also() las captura/consume. Para que sea similar tendrías que tirar el resultado al final:
runCatching { // ... Run some code }.also { // ... Cleanup code }.getOrThrow() Pero aún así, no es realmente equivalente a 1:1. Atrapa todas las excepciones solo para volver a lanzarlas. Por esta razón, es probable que tenga menos rendimiento que el simple try...finally .
Además, creo que esto es menos claro para el lector. try...finally es una forma estándar de tratar las excepciones. Al usar runCatching() solo para volver a lanzarlo de inmediato, en realidad confunde a quien lea este código más tarde.
Su pregunta sonaba un poco como si creyera que Kotlin no tiene try...finally y necesita buscar alternativas. Si este es el caso, entonces, por supuesto, Kotlin lo ha try...finally y creo que deberías usarlo en lugar de runCatching() .
Según el documento de Kotlin para runCatching :
Llama al bloque de funciones especificado y devuelve su resultado encapsulado si la invocación fue exitosa, capturando cualquier excepción Throwable que se haya generado desde la ejecución de la función de bloque y encapsulándola como una falla.
Incluso si finally siempre se ejecuta después de un bloque de try y also siempre se ejecuta después de un runCatching , no tienen el mismo propósito.
finally no recibe ningún argumento y no puede operar en los valores del bloque try , mientras que also recibe el resultado del bloque runCatching .
TLDR; .runCatching{}.also{} es un try{}finally{}