Patrón Try With Resources
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 62 de 87.
Al trabajar con recursos como flujos de archivos o conexiones a bases de datos, siempre debes cerrarlos al terminar; de lo contrario, corres el riesgo de sufrir fugas de memoria. El enfoque tradicional utiliza un bloque finally, pero es verboso y propenso a errores.
La sentencia try-with-resources de Java cierra automáticamente los recursos cuando el bloque finaliza. Cualquier clase que implemente la interfaz AutoCloseable puede utilizarse con esta sintaxis:
// Enfoque tradicional: verboso y arriesgado
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("file.txt"));
String line = reader.readLine();
} finally {
if (reader != null) {
reader.close(); // ¡También podría lanzar una excepción!
}
}
// Try-with-resources: limpio y seguro
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
String line = reader.readLine();
} // Se cierra automáticamente aquíPuedes gestionar múltiples recursos separándolos con puntos y coma. Se cierran en orden inverso al de su declaración:
try (FileReader fr = new FileReader("input.txt");
BufferedReader br = new BufferedReader(fr)) {
// Utilizar ambos recursos
} // br se cierra primero, luego frPara crear tu propia clase auto-closeable, implementa la interfaz AutoCloseable y su único método close():
public class DatabaseConnection implements AutoCloseable {
public DatabaseConnection() {
System.out.println("Connection opened");
}
@Override
public void close() {
System.out.println("Connection closed");
}
}Este patrón garantiza que los recursos se liberen siempre correctamente, incluso si se producen excepciones durante el procesamiento.
Desafío
Fácil¡Vamos a construir un sistema de gestión de recursos que demuestre el poder de try-with-resources! Crearás clases personalizadas auto-closeable que simulan la gestión de conexiones y sesiones, asegurando que siempre se limpien adecuadamente.
Organizarás tu código en tres archivos:
Connection.java: Crea una clase que simule una conexión a una base de datos. Tu claseConnectiondebe implementarAutoCloseable. Necesita un campo privado para el nombre de la conexión (String), un constructor que reciba el nombre e imprima[name] connection opened, un métodoquery(String sql)que imprimaExecuting on [name]: [sql], y el métodoclose()requerido que imprima[name] connection closed.Session.java: Crea otra clase auto-closeable que simule una sesión de usuario. Tu claseSessiontambién debe implementarAutoCloseable. Incluye un campo privado para el nombre de usuario (String), un constructor que reciba el nombre de usuario e imprimaSession started for [username], un métodoperformAction(String action)que imprima[username] performed: [action], y un métodoclose()que imprimaSession ended for [username].Main.java: ¡Une tu sistema de gestión de recursos! Recibirás tres entradas: un nombre de conexión, un nombre de usuario y una acción a realizar.Primero, demuestra la gestión de un solo recurso. Imprime
=== Single Resource ===, luego usa try-with-resources para crear unaConnectioncon el nombre dado. Dentro del bloque try, llama aquery("SELECT * FROM users"). La conexión debe cerrarse automáticamente cuando termine el bloque.A continuación, demuestra múltiples recursos. Imprime una línea en blanco, luego
=== Multiple Resources ===. Usa try-with-resources con unaConnection(usando el mismo nombre) y unaSession(usando el nombre de usuario), declaradas en ese orden con puntos y coma. Dentro del bloque try, primero llama aquery("INSERT INTO logs")en la conexión, luego llama aperformActioncon la acción de entrada en la sesión. ¡Observa cómo los recursos se cierran en orden inverso!
Recibirás tres entradas en orden: nombre de conexión (String), nombre de usuario (String) y acción (String).
Observa cómo try-with-resources elimina la necesidad de llamadas explícitas a close y bloques finally. ¡Se garantiza que los recursos se cierren incluso si ocurren excepciones, y múltiples recursos se cierran en el orden inverso a su declaración!
Hoja de referencia
La sentencia try-with-resources cierra automáticamente los recursos cuando el bloque finaliza. Se puede utilizar cualquier clase que implemente AutoCloseable:
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
String line = reader.readLine();
} // Se cierra automáticamente aquíSe pueden gestionar múltiples recursos separándolos con puntos y coma. Se cierran en orden inverso a su declaración:
try (FileReader fr = new FileReader("input.txt");
BufferedReader br = new BufferedReader(fr)) {
// Usar ambos recursos
} // br se cierra primero, luego frPara crear una clase auto-closeable personalizada, implemente la interfaz AutoCloseable y su método close():
public class DatabaseConnection implements AutoCloseable {
public DatabaseConnection() {
System.out.println("Connection opened");
}
@Override
public void close() {
System.out.println("Connection closed");
}
}Pruébalo tú mismo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String connectionName = scanner.nextLine();
String username = scanner.nextLine();
String action = scanner.nextLine();
// === Recurso Único ===
// TODO: Imprimir el encabezado
// TODO: Usar try-with-resources para crear una Connection
// TODO: Dentro del bloque try, llamar a query("SELECT * FROM users")
// === Múltiples Recursos ===
// TODO: Imprimir una línea en blanco y el encabezado
// TODO: Usar try-with-resources con Connection y Session
// TODO: Dentro del bloque try:
// - Llamar a query("INSERT INTO logs") en la conexión
// - Llamar a performAction con la acción de entrada en la sesión
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado10Manejo de excepciones en POO
Jerarquía de clases de excepcionesExcepciones personalizadasErrores Checked vs UncheckedPatrón Try With ResourcesResumen - Usuario validado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Iterator