Java: prueba con recursos

1. Información general

El soporte para try-with-resources, introducido en Java 7, nos permite declarar recursos que se usarán en un bloque try con la seguridad de que los recursos se cerrarán después de la ejecución de ese bloque.

Los recursos declarados deben implementar la interfaz AutoCloseable .

2. Uso de recursos de prueba

En pocas palabras, para que se cierre automáticamente, un recurso debe declararse e inicializarse dentro del intento , como se muestra a continuación:

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

3. Reemplazo de try - catch-finalmente con try-with-resources

La forma simple y obvia de usar la nueva funcionalidad try-with-resources es reemplazar el tradicional y detallado bloque try-catch-finalmente .

Comparemos los siguientes ejemplos de código: primero es un bloque típico try-catch-finalmente , luego el nuevo enfoque, usando un bloque equivalente try-with-resources:

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(); } }

Y aquí está la solución súper sucinta usando try-with-resources:

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

Aquí es donde puede explorar más a fondo la clase Scanner .

4. probar con recursos con múltiples recursos

Se pueden declarar varios recursos sin problemas en un bloque try-with-resources 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()); } }

5. Un recurso personalizado con AutoCloseable

Para construir un recurso personalizado que será manejado correctamente por un try-con-recursos bloque, la clase debe implementar las que se puede cerrar o AutoCloseable interfaces y anular el cierre método:

public class MyResource implements AutoCloseable { @Override public void close() throws Exception { System.out.println("Closed MyResource"); } }

6. Orden de cierre de recursos

Los recursos que se definieron / adquirieron primero se cerrarán al final; veamos un ejemplo de este comportamiento:

Recurso 1:

public class AutoCloseableResourcesFirst implements AutoCloseable { public AutoCloseableResourcesFirst() { System.out.println("Constructor -> AutoCloseableResources_First"); } public void doSomething() { System.out.println("Something -> AutoCloseableResources_First"); } @Override public void close() throws Exception { System.out.println("Closed AutoCloseableResources_First"); } } 

Recurso 2:

public class AutoCloseableResourcesSecond implements AutoCloseable { public AutoCloseableResourcesSecond() { System.out.println("Constructor -> AutoCloseableResources_Second"); } public void doSomething() { System.out.println("Something -> AutoCloseableResources_Second"); } @Override public void close() throws Exception { System.out.println("Closed AutoCloseableResources_Second"); } }

Código:

private void orderOfClosingResources() throws Exception { try (AutoCloseableResourcesFirst af = new AutoCloseableResourcesFirst(); AutoCloseableResourcesSecond as = new AutoCloseableResourcesSecond()) { af.doSomething(); as.doSomething(); } } 

Salida:

Constructor -> AutoCloseableResources_First

Constructor -> AutoCloseableResources_Second

Algo -> AutoCloseableResources_First

Algo -> AutoCloseableResources_Second

Cerrado AutoCloseableResources_Second

Cerrado AutoCloseableResources_First

7. atrapar y finalmente

A try-with-resources block can still have the catch and finally blocks – which will work in the same way as with a traditional try block.

8. Java 9: Effectively FinalVariables

Before Java 9, we only could use fresh variables inside a try-with-resources block:

try (Scanner scanner = new Scanner(new File("testRead.txt")); PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { // omitted }

As shown above, this was especially verbose when declaring multiple resources. As of Java 9 and as part of JEP 213, we can now use final or even effectively final variables inside a try-with-resources block:

final Scanner scanner = new Scanner(new File("testRead.txt")); PrintWriter writer = new PrintWriter(new File("testWrite.txt")) try (scanner;writer) { // omitted }

Put simply, a variable is effectively final if it doesn't change after the first assignment, even though it's not explicitly marked as final.

As shown above, the scanner variable is declared final explicitly, so we can use it with the try-with-resources block. Although the writer variable is not explicitly final, it doesn't change after the first assignment. Therefore, we're allowed to use the writer variable, too.

9. Conclusion

En este artículo, hemos discutido cómo usar try-with-resources, cómo reemplazar try , catch y finalmente try-with-resources, creando recursos personalizados con AutoCloseable y el orden en que se cierran los recursos.

El código fuente completo para el ejemplo está disponible en este proyecto de GitHub.