Introducción
Contenido
try-with-resources es uno de los varios try
declaraciones en Java, destinadas a liberar a los desarrolladores de la obligación de liberar los recursos utilizados en un try
bloquear.
Inicialmente se introdujo en Java 7 y la idea subyacente era que el desarrollador no necesita preocuparse por la administración de recursos para los recursos que usan solo en un bloque try-catch-finalmente. Esto se logra eliminando la necesidad de finally
blocks, que los desarrolladores solo usaron para cerrar recursos en la práctica.
Además, el código que usa try-with-resources suele ser más limpio y legible, por lo tanto, hace que el código sea más fácil de administrar, especialmente cuando se trata de muchos try
bloques.
Sintaxis
La sintaxis de try-with-resources es casi idéntica a la sintaxis habitual de try-catch-finalmente. La única diferencia son los paréntesis después de try
en el que 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í:
Te puede interesar:Algoritmos de búsqueda en Javatry(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 su .close()
métodos tan pronto como termine con el trabajo en el bloque try. Si se lanza una excepción mientras estoy en el bloque try, cerraré esos recursos de todos modos.
Antes de que se introdujera este enfoque, el cierre de recursos se realizaba manualmente, como se ve en el código anterior. Esto era esencialmente código repetitivo, y las bases de código estaban llenas de ellos, lo que reducía la legibilidad y dificultaba su mantenimiento.
los catch
y finally
parte del trabajo de prueba con recursos como se esperaba, con catch
bloques que manejan sus respectivas excepciones y el finally
bloque 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-resources. En su lugar, podemos hacer algo como esto:
Te puede interesar:Leer un archivo línea por línea en JavaBufferedWriter 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
}
Múltiples recursos
Otro buen aspecto de try-with-resources es la facilidad para 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, abriríamos los archivos en el try()
declaración y sepárelos 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()
en todos los recursos que hemos abierto en try()
.
Nota: Están cerrados en orden de declaración inverso, lo que significa que, en nuestro ejemplo, scanner
estará cerrado antes del writer
.
Clases admitidas
Todos los recursos declarados en try()
debe implementar el AutoCloseable
interfaz. Suelen tratarse de varios tipos de escritores, lectores, sockets, flujos de entrada o salida, etc. Todo lo que necesite escribir resource.close()
una vez que haya terminado de trabajar con él.
Esto, por supuesto, incluye objetos definidos por el usuario que implementan la AutoClosable
interfaz. 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 el AutoCloseable
o Closeable
(solo para preservar la compatibilidad con versiones anteriores, prefiera AutoCloseable
) interfaz y anular la .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 dentro de un bloque de prueba con recursos de Java, cualquier recurso abierto entre paréntesis de try
el bloque aún se cerrará automáticamente.
Como se mencionó anteriormente, try-with-resources funciona igual que try-catch-finalmente, excepto con una pequeña adición. La adición se llama excepciones suprimidas. Es no Es necesario comprender las excepciones suprimidas para poder usar try-with-resources, pero leer sobre ellas puede ser útil para depurar cuando nada más parece funcionar.
Imagina una situación:
Te puede interesar:Métodos de objetos de Java: toString ()- 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()
sobre todos los recursos declarados entry()
- Uno de los
.close()
los métodos arrojan una excepción - ¿Qué excepción sería la
catch
bloquear «captura»?
Esta situación nos introduce en 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 se lanza una excepción desde el try
bloque también.
Esas excepciones son excepciones que ocurren en el .close()
métodos y se accede a ellos de forma diferente a las excepciones «normales».
Es importante comprender que el orden de ejecución es:
- bloque try-with-resources
- implícito finalmente
- catch block (si se lanzó una excepción [1] y / o [2])
- (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 se puede ejecutar. Puede usarlo para experimentar con el uso de múltiples MyResource
objetos o ver lo que sucede cuando try-with-resources no lanza una excepción, pero .close()
hace.
Insinuación: 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 arroje una excepción cuando intente cerrarlo, cualquier otro recurso abierto dentro del mismo bloque try-with-resources seguirá cerrado.
Otro hecho a tener en cuenta es que en una situación en la que el try
block no lanza una excepción, y donde hay múltiples excepciones lanzadas al intentar .close()
los recursos utilizados, el primero La excepción se propagará por la pila de llamadas, mientras que las demás se suprimirán.
Como puede ver en el código, puede obtener la lista de todas las excepciones suprimidas accediendo al Throwable
matriz devuelta por Throwable.getSuppressed()
.
Recuerde, solo se puede lanzar una única excepción dentro del bloque try. Tan pronto como se lanza una excepción, se sale del código del bloque try y Java intenta cerrar los recursos.
Te puede interesar:Métodos de objetos de Java: clone ()Conclusión
try-with-resources debe usarse en lugar del try-catch-finalmente habitual siempre que 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, por lo general, más corto.