La declaración try-with-resources en Java

Introducción

try-with-resources es una de las varias trydeclaraciones en Java, destinada a liberar a los desarrolladores de la obligación de liberar recursos utilizados en un trybloque.
Inicialmente se introdujo en Java 7 y la idea principal fue que el desarrollador no tiene que preocuparse por la administración de recursos para los recursos que usa solo en un bloque try-catch-finally . Esto se logra eliminando la necesidad de finallybloques, que los desarrolladores solo usaron para cerrar recursos en la práctica.
Además, el código que usa try-with-resources es a menudo más limpio y más legible, por lo tanto, hace que el código sea más fácil de administrar, especialmente cuando se trata de muchos trybloques.

Sintaxis

La sintaxis de try-with-resources es casi idéntica a la sintaxis usual de try-catch-finally . La única diferencia son los paréntesis después tryde los cuales declaramos qué recursos usaremos:
BufferedWriter writer = null;  
try {  
    writer = new BufferedWriter(new FileWriter(fileName));
    writer.write(str);  // do something with the file we've opened
} catch (IOException e) {
   // handle the exception
} finally {
    try {
        if (writer != null)
            writer.close();
    } catch (IOException e) {
       // handle the exception
    }
}
El mismo código escrito usando try-with-resources se vería así:
try(BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))){  
    writer.write(str); // do something with the file we've opened
}
catch(IOException e){  
    // handle the exception
}
La forma en que Java entiende este código:
Los recursos abiertos entre paréntesis después de la instrucción try solo serán necesarios aquí y ahora. Llamaré a sus .close()métodos tan pronto como termine el trabajo en el bloque try . Si se lanza una excepción mientras está en el bloque try , cerraré esos recursos de todos modos.
Antes de que se introdujera este enfoque, el cierre de los recursos se hacía manualmente, como se ve en el código anterior. Este era esencialmente un código de referencia, y las bases de códigos estaban llenas de ellos, reduciendo la legibilidad y haciéndolos más difíciles de mantener.
El catchy la finallyparte de try-with-resources funcionan como se esperaba, con catchbloques que manejan sus respectivas excepciones y el finallybloque ejecutado independientemente de si hubo una excepción o no. La única diferencia son las excepciones suprimidas, que se explican al final de este artículo.
Nota : desde Java 9, no es necesario declarar los recursos dentro de la declaración try-with-resourcesPodemos hacer algo como esto en su lugar:
BufferedWriter writer = new BufferedWriter(new FileWriter(fileName));  
try (writer) {  
    writer.write(str); // do something with the file we've opened
}
catch(IOException e) {  
    // handle the exception
}

Recursos Múltiples

Otro buen aspecto de try-with-resources es la facilidad de agregar / eliminar recursos que estamos usando y tener la seguridad de que se cerrarán una vez que hayamos terminado.
Si quisiéramos trabajar con varios archivos, los abriríamos en la try()declaración y los separaremos con un punto y coma:
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName));  
    Scanner scanner = new Scanner(System.in)) {
if (scanner.hasNextLine())  
    writer.write(scanner.nextLine());
}
catch(IOException e) {  
    // handle the exception
}
Java luego se encarga de llamar .close()a todos los recursos que hemos abierto try().
Nota : están cerrados en orden de declaración inverso, lo que significa que, en nuestro ejemplo, scannerse cerrarán antes de writer.

Clases apoyadas

Todos los recursos declarados en try()deben implementar la AutoCloseableinterfaz. Estos suelen ser varios tipos de escritores, lectores, sockets, flujos de salida o entrada, etc. Cualquier cosa que necesite escribir resource.close()después de que haya terminado de trabajar con él.
Esto, por supuesto, incluye objetos definidos por el usuario que implementan la AutoClosableinterfaz. Sin embargo, rara vez se encontrará con una situación en la que desee escribir sus propios recursos.
En caso de que eso suceda, debe implementar la interfaz AutoCloseableCloseable(solo allí para preservar la compatibilidad con versiones anteriores, preferir AutoCloseable) la interfaz y anular el .close()método:
public class MyResource implements AutoCloseable {  
    @Override
    public void close() throws Exception {
        // close your resource in the appropriate way
    }
}

Manejo de excepciones

Si se lanza una excepción desde un bloque de prueba de recursos de Java , cualquier recurso abierto dentro de los paréntesis del trybloque se cerrará automáticamente.
Como se mencionó anteriormente, try-with-resources funciona de la misma manera que try-catch-finally , excepto con una pequeña adición. La adición se llama excepciones suprimidas . Es nonecesario entender excepciones suprimidos con el fin de utilizar try-con-recursos , pero la lectura de ellos podría ser útil para depurar cuando nada parece funcionar.
Imagina una situación:
  • Por alguna razón, se produce una excepción en el bloque try-with-resources
  • Java detiene la ejecución en el bloque try-with-resources y llama .close()a todos los recursos declarados entry()
  • Uno de los .close()métodos lanza una excepción.
  • ¿Qué excepción catch"bloquearía" el bloque?
Esta situación nos introduce a las excepciones suprimidas antes mencionadas. Una excepción suprimida es una excepción que de alguna manera se ignora cuando se lanza dentro del bloque final implícito de un bloque try-with-resources , en el caso de que también se lance una excepción desde el trybloque.
Esas excepciones son excepciones que ocurren en los .close()métodos y se accede a ellas de manera diferente a las excepciones "regulares".
Es importante entender que el orden de ejecución es:
  1. bloque try-with-resources
  2. implícito finalmente
  3. bloque de captura (si se lanzó una excepción en [1] y / o [2])
  4. (explícito) finalmente
Por ejemplo, aquí hay un recurso que no hace más que lanzar excepciones:
public static class MyResource implements AutoCloseable {  
    // method throws RuntimeException
    public void doSomething() {
        throw new RuntimeException("From the doSomething method");
    }

    // we'll override close so that it throws an exception in the implicit finally block of try-with-resources (when it attempts to close our resource)
    @Override
    public void close() throws Exception {
        throw new ArithmeticException("I can throw whatever I want, you can't stop me.");
    }
}

public static void main(String[] arguments) throws Exception {  
    // declare our resource in try
    try (MyResource resource = new MyResource()) {
        resource.doSomething();
    }
    catch (Exception e) {
        System.out.println("Regular exception: " + e.toString());

        // getting the array of suppressed exceptions, and its length
        Throwable[] suppressedExceptions = e.getSuppressed();
        int n = suppressedExceptions.length;

        if (n > 0) {
            System.out.println("We've found " + n + " suppressed exceptions:");
            for (Throwable exception : suppressedExceptions) {
                System.out.println(exception.toString());
            }
        }
    }
}
Este código es ejecutable. Puede usarlo para experimentar con el uso de múltiples MyResourceobjetos o ver qué sucede cuando try-with-resources no lanza una excepción, pero .close()sí lo hace.
Sugerencia : De repente, las excepciones lanzadas al cerrar los recursos comienzan a ser importantes.
Es importante tener en cuenta que en caso de que un recurso lance una excepción cuando intente cerrarla, cualquier otro recurso abierto dentro del mismo bloque try-with-resources se cerrará.
Otro dato a tener en cuenta es que, en una situación en la que el trybloque no produce una excepción y donde se producen múltiples excepciones al intentar .close()los recursos utilizados, la primera excepción se propagará a la pila de llamadas, mientras que las demás se eliminarán. .
Como puede ver en el código, puede obtener la lista de todas las excepciones suprimidas accediendo a la Throwablematriz devuelta por Throwable.getSuppressed().
Recuerde, solo se puede lanzar una excepción dentro del bloque try. Tan pronto como se lanza una excepción, se sale del código de bloque de prueba y Java intenta cerrar los recursos.

Conclusión

Debería utilizarse try-with-resources en lugar del try-catch-final cuando sea posible. Es fácil olvidarse de cerrar uno de sus recursos después de codificar durante horas u olvidarse de cerrar un recurso que acaba de agregar a su programa después de una explosión aleatoria de inspiración.
El código es más legible, más fácil de cambiar y mantener, y generalmente más corto.

Acerca de: Programator

Somos Instinto Programador

0 comentarios:

Publicar un comentario

Dejanos tu comentario para seguir mejorando!

Con tecnología de Blogger.