Ya hemos visto que es try/catch/finally y como se usan para el manejo de excepciones en Java. Algo muy cool añadido a partir de Java 7 es algo llamado try-with-resources. Para entender en que consiste eso vamos a revisar un ejemplo. Vamos a suponer que quiero hacer un programita para abrir un archivo de texto que se encuentra en el disco duro (o disco de estado solido para los ricos) de la computadora, y quiero imprimir en pantalla cada una de las lineas que contiene ese archivo. A continuación se muestra el código Java que hace precisamente eso:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ReadFile {
public static void main(String[] args) {
readFile("myFavoriteOldGames.txt");
}
private static void readFile(String string) {
Scanner myScanner = null;
try {
myScanner = new Scanner(new File(string));
while (myScanner.hasNext()) {
System.out.println(myScanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (myScanner != null) {
myScanner.close();
}
}
}
}
El programa trata de leer un objeto File usando el archivo llamado myFavoriteOldGames.txt para después ir iterando cada linea a través de un objeto Scanner. El archivo de texto al que se hace referencia contiene las siguientes lineas:
Super Mario World
Megaman X3
Mario Kart 64
Super Mario 64
The Legend of Zelda: Ocarina of Time
Al ejecutar este código con la salida es la siguiente:
run:
Super Mario World
Megaman X3
Mario Kart 64
Super Mario 64
The Legend of Zelda: Ocarina of Time
BUILD SUCCESSFUL (total time: 0 seconds)
Todo funciona bien, sin errores. Se puede apreciar el uso de try/catch/finally tal cual como se ha venido explicando en los posts anteriores, si por ejemplo, ocurre un error porque el archivo que se desea usar no existe, el flujo del programa irá hacia el catch, y finalmente el flujo irá hacia finally para cerrar recursos, en este caso el scanner.
Este código se puede mejorar usando try-with-resources en vez de try/catch/finally, el cual nos permite declarar el o los recursos que serán usado dentro del try con la garantía de que serán cerrados automáticamente una vez la ejecución del bloque try haya terminado, osea que no tenemos que indicar explicitamente que se cierre el o los recursos, el try-with-resources lo hará por nosotros. Refactorizando el código anterior quedaría así:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ReadFile {
public static void main(String[] args) {
readFile("C:\\myFavoriteOldGames.txt");
}
private static void readFile(String string) {
try(Scanner myScanner = new Scanner(new File(string))){
while (myScanner.hasNext()) {
System.out.println(myScanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
// No es necesario cerrar myScanner aquí
// El try-with-resources lo hará por nosotros
}
}
}
Como se puede ver, en la linea 12 se declara e inicializa el objeto Scanner el cual en ningún momento se indica de manera explicita el cerrar dicho recurso, el try-with-resources se encargará de ello, lo cual nos permite tener un código mas reducido y limpio, a diferencia al ejemplo anterior. El resultado al ejecutar este código es igual a del ejemplo anterior.
Unas ultimas cosas a mencionar respecto a try-with-resources. Primero, es posible tener mas de un recurso declarado dentro del try, únicamente se deberá separar cada uno de ellos por punto y coma. Segundo, todo recurso que se deseé usar dentro del try deberá implementar la interfaz java.lang.AutoCloseable e implementar el método close de dicha interfaz, lo cual significa que tu podrías crear tus clases que hereden de ella y se puedan usar en un try-with-resources. La clase Scanner implementa AutoCloseable, es por eso que funcionó el demo.