Cómo usar Try With Resource en Java

Feb 21 2023
Cómo manejar excepciones usando la declaración try-with-resource La construcción Java try with resources, también conocida como Java try-with-resources, es un mecanismo de manejo de excepciones que puede cerrar automáticamente recursos como Java InputStream o una conexión JDBC cuando haya terminado con ellos . Oracle agregó la construcción try with resources al lenguaje Java en 2011 para ayudar a garantizar que objetos como sockets de red, conexiones de bases de datos y referencias a archivos y carpetas finalicen limpiamente después de su uso.

Cómo manejar excepciones usando la declaración try-with-resource

La construcción Java try with resources , también conocida como Java try-with-resources , es un mecanismo de manejo de excepciones que puede cerrar automáticamente recursos como Java InputStream o JDBC Connection cuando haya terminado con ellos.

Oracle agregó la construcción try with resources al lenguaje Java en 2011 para ayudar a garantizar que objetos como sockets de red, conexiones de bases de datos y referencias a archivos y carpetas finalicen limpiamente después de su uso. Si no se cierran estos recursos después de que un desarrollador abre un identificador para ellos, se pueden producir fugas de memoria , desencadenar rutinas de recolección de basura evitables y agotar la CPU de un servidor .

· Antes de Java 7
· ¿Cómo usar la instrucción try-with-resource?
· ¿ Por qué tengo que usar la instrucción try-with-resource?
· Ejemplo
· Excepciones suprimidas
· Ventajas de usar try-with-resources
· try-with-resources con varios recursos
· Java 9: ​​variables efectivamente finales

Antes de Java 7

En Java, si usa un recurso como flujos de entrada o salida, siempre debe cerrarlo después de usarlo. También puede generar excepciones, por lo que debe estar en un bloque de prueba y captura . El cierre tiene que estar en el bloque finalmente . Este es al menos el camino hasta Java 7. Esto tiene varias desventajas:

  • Tendrías que comprobar si tu recurso es nulo antes de cerrarlo
  • El cierre en sí mismo puede arrojar excepciones, por lo que finalmente tuvo que contener otro intento de captura
  • Los programadores tienden a olvidarse de cerrar sus recursos.

¿Cómo usar la declaración try-with-resource?

Inicialmente se introdujo en Java 7 y la idea detrás de esto era que el desarrollador no necesita preocuparse por la administración de recursos para los recursos que usan solo en un bloque try -catch-finally . Esto se logra al eliminar la necesidad de bloques finalmente , que los desarrolladores solo usaron para cerrar recursos en la práctica.

En Java, la declaración de prueba con recursos es una declaración de prueba que declara uno o más recursos. El recurso es como un objeto que debe cerrarse después de finalizar el programa. Cuando la ejecución abandona el bloque de prueba con recursos , cualquier recurso abierto dentro del bloque de prueba con recursos se cierra automáticamente, independientemente de si se lanzan excepciones desde dentro del bloque de prueba con recursos o al intentar cerrar Los recursos.

Para usar la función de lenguaje de prueba con recursos de Java, se aplican las siguientes reglas:

  • Todos los objetos administrados por una sentencia try with resources deben implementar la interfaz AutoCloseable.
  • Se pueden crear varios objetos AutoCloseable dentro del bloque Try with Resources de Java.
  • Los objetos declarados en una declaración de prueba con recursos tienen alcance dentro del bloque de prueba, pero no en los bloques de captura y finalmente.
  • El método close() de los objetos declarados en un bloque try with resources se invoca independientemente de si se lanza una excepción durante la ejecución.
  • Si se lanza una excepción en el método close(), puede clasificarse como una excepción suprimida .

El recurso al que hace referencia el objeto AutoCloseable siempre se cerrará si se usa una declaración de prueba con recursos, y se eliminan las posibles fugas de memoria causadas comúnmente por una mala asignación de recursos.

Sintaxis

try(declare resources here) {
    // use resources
}
catch(FileNotFoundException e) {
    // exception handling
}

En pocas palabras, para que se cierre automáticamente, un recurso debe declararse e inicializarse dentro de try :

try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {
    writer.println("Hello World");
}

La manera simple y obvia de usar la nueva funcionalidad de prueba con recursos es reemplazar el bloque tradicional y detallado de prueba, captura y final .

Comparemos los siguientes ejemplos de código.

El primero es un típico bloque try-catch-finally :

Scanner scanner = null;
try {
    scanner = new Scanner(new File("test.txt"));
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (scanner != null) {
        scanner.close();
    }
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

try (Scanner scanner = new Scanner(new File("test.txt"))) {
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

Cuando se trata de excepciones, hay una diferencia entre el bloque try-catch-finally y el bloque try-with-resources. Si se lanza una excepción tanto en el bloque try como en el bloque finalmente, el método devuelve la excepción lanzada en el bloque finalmente.

Para probar con recursos, si se lanza una excepción en un bloque de prueba y en una declaración de prueba con recursos, entonces el método devuelve la excepción lanzada en el bloque de prueba. Las excepciones lanzadas por try-with-resources se suprimen, es decir, podemos decir que el bloque try-with-resources lanza excepciones suprimidas.

¿Por qué tengo que usar la declaración try-with-resource?

La instrucción try-with-resources garantiza que cada recurso se cierre al final de la ejecución de la instrucción . Si no cerramos los recursos, puede constituir una fuga de recursos y también el programa podría agotar los recursos disponibles para él. eso es lo que sucede principalmente cuando usas el bloque try-catch-finally

Antes de Java SE 7, puede usar un bloque finalmente para asegurarse de que un recurso se cierre independientemente de si la declaración de prueba se completa de manera normal o abrupta. El siguiente ejemplo usa un bloque finalmente en lugar de una instrucción try -with-resources:

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
   
    FileReader fr = new FileReader(path);
    BufferedReader br = new BufferedReader(fr);
    try {
        return br.readLine();
    } finally {
        br.close();
        fr.close();
    }
}

En este ejemplo, si el método readLine arroja una excepción y la declaración br.close() en el bloque finalmente arroja una excepción, entonces FileReader se ha filtrado. Por lo tanto, use una declaración de prueba con recursos en lugar de un bloque finalmente para cerrar los recursos de su programa.

Ejemplo

El siguiente ejemplo lee la primera línea de un archivo. Utiliza una instancia de FileReader y BufferedReader para leer datos del archivo. FileReader y BufferedReader son recursos que deben cerrarse después de que el programa termine con él:

import java.io.*;
class Main {
  public static void main(String[] args) {
    String line;
    try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
      while ((line = br.readLine()) != null) {
        System.out.println("Line =>"+line);
      }
    } catch (IOException e) {
      System.out.println("IOException in try block =>" + e.getMessage());
    }
  }
}

Excepciones suprimidas

Si un bloque try genera una excepción y try-with-resources genera una o más excepciones, se suprimen las excepciones generadas por try-with-resources. En otras palabras, podemos decir que las excepciones lanzadas por try-with-resources son excepciones suprimidas.

Puede obtener estas excepciones utilizando el método getSuppress() de la clase Throwable.

Ejemplo :

En el ejemplo anterior, se pueden generar excepciones desde la instrucción try-with-resources cuando:

  • No se encuentra el archivo test.txt .
  • Cerrando el objeto BufferedReader .

Si se lanzan excepciones desde el bloque de prueba y la declaración de prueba con recursos , se lanza la excepción del bloque de prueba y se suprime la excepción de la declaración de prueba con recursos .

Recuperación de excepciones suprimidas

En Java 7 y versiones posteriores, las excepciones suprimidas se pueden recuperar llamando al método Throwable.getSuppressed() desde la excepción lanzada por el bloque try .

getSuppress() Devuelve una matriz que contiene todas las excepciones que fueron suprimidas por la instrucción try-with-resources. Si no se suprimieron excepciones o si la supresión está deshabilitada, se devuelve una matriz vacía.

Obtenemos las excepciones suprimidas en el bloque catch .

catch(IOException e) {
  System.out.println("Thrown exception=>" + e.getMessage());
  Throwable[] suppressedExceptions = e.getSuppressed();
  for (int i=0; i<suppressedExceptions.length; i++) {
    System.out.println("Suppressed exception=>" + suppressedExceptions[i]);
  }
}

Estas son las ventajas de usar Try-with-Resources:

  • Código más legible y fácil de escribir.
  • Gestión automática de recursos.
  • Se reduce el número de líneas de código.
  • Cuando se abren múltiples recursos en try-with-resources, los cierra en el orden inverso para evitar cualquier problema de dependencia.

Antes de que Java 7 introdujera esta función, teníamos que usar el bloque finalmente para asegurarnos de que el recurso esté cerrado para evitar fugas de recursos.

Aquí hay un programa que es similar al Ejemplo 1 . Sin embargo, en este programa, hemos utilizado finalmente bloque para cerrar recursos.

Ejemplo: Cerrar recurso usando bloque finalmente

import java.io.*;
class Main {
  public static void main(String[] args) {
    BufferedReader br = null;
    String line;
    try {
      System.out.println("Entering try block");
      br = new BufferedReader(new FileReader("test.txt"));
      while ((line = br.readLine()) != null) {
        System.out.println("Line =>"+line);
      }
    } catch (IOException e) {
      System.out.println("IOException in try block =>" + e.getMessage());
    } finally {
      System.out.println("Entering finally block");
      try {
        if (br != null) {
          br.close();
        }
      } catch (IOException e) {
        System.out.println("IOException in finally block =>"+e.getMessage());
      }
    }
  }
}

Entering try block
Line =>line from test.txt file
Entering finally block

¿Observe el bloque try... catch en el bloque finalmente también? Esto se debe a que también puede ocurrir una IOException al cerrar la instancia de BufferedReader dentro de este bloque finalmente para que también sea capturado y manejado.

La instrucción try-with-resources realiza una gestión automática de recursos . No necesitamos cerrar explícitamente los recursos ya que JVM los cierra automáticamente. Esto hace que el código sea más legible y más fácil de escribir.

try-with-resources con múltiples recursos

Podemos declarar varios recursos muy bien en un bloque de prueba con recursos separándolos con un punto y coma:

try (Scanner scanner = new Scanner(new File("testRead.txt"));
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
    while (scanner.hasNext()) {
	writer.print(scanner.nextLine());
    }
}

Antes de Java 9, solo podíamos usar variables nuevas dentro de un bloque de prueba con recursos :

try (Scanner scanner = new Scanner(new File("testRead.txt")); 
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { 
    // omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

final Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
try (scanner;writer) { 
    // omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

Como se muestra arriba, la variable del escáner se declara final explícitamente, por lo que podemos usarla con el bloque de prueba con recursos . Aunque la variable escritor no es explícitamente final, no cambia después de la primera asignación. Entonces, también podemos usar la variable escritor .

Feliz aprendizaje

Únete al grupo de WhatsApp de Mouad Oumous Java ÚNETE

Únete al canal Mouad Oumous Telegram ÚNETE

Apoya nuestra publicación siguiéndola

Guía para el mapeo de objetos con ModelMapper en Java Primeros pasos con Spring Boot: un tutorial completo para principiantes Spring Boot Security | inicio de sesión único | OAuth2 con Okta La pregunta de entrevista más frecuente basada en secuencias de Java8 — Parte 2 Codificación: aplanar una matriz en Javascript La pregunta de entrevista más frecuente basada en secuencias de Java8 — Parte 1