Você está na página 1de 24

Excepciones y Finally en Java

Eduardo Ostertag Jenkins, Ph.D. OBCOM INGENIERIA S.A. (Chile) Eduardo.Ostertag@obcom.cl

Try Finally

Est liberando siempre los recursos?


public Properties leerPropiedades(String archivo) throws FileNotFoundException, IOException { Properties propiedades = new Properties(); FileInputStream fis = new FileInputStream(archivo); propiedades.load(fis); fis.close(); return propiedades; }

Se ejecuta siempre este close?

Siempre libere los recursos con finally


public Properties leerPropiedades(String archivo) throws FileNotFoundException, IOException { Properties propiedades = new Properties(); FileInputStream fis = new FileInputStream(archivo); try { propiedades.load(fis); } finally { fis.close(); } return propiedades; }

Program correctamente el finally?


public BigDecimal obtenerValorUF(DataSource dataSource, Date fecha) throws SQLException { Connection conn = null; CallableStatement call = null; try { conn = dataSource.getConnection(); call = conn.prepareCall("{call ObtenerValorUF(?,?)}"); call.setDate(1, fecha); call.registerOutParameter(2, Types.DECIMAL); call.execute(); return call.getBigDecimal(2); } finally { if (call != null) call.close(); if (conn != null) conn.close(); } }

Se ejecuta siempre este close?

Un finally debe liberar slo un recurso


public BigDecimal obtenerValorUF(DataSource dataSource, Date fecha) throws SQLException { final Connection conn = dataSource.getConnection(); try { final CallableStatement call = conn.prepareCall("{call ObtenerValorUF(?,?)}"); try { call.setDate(1, fecha); call.registerOutParameter(2, Types.DECIMAL); call.execute(); return call.getBigDecimal(2); } finally { call.close(); } } finally { conn.close(); } }

Comentarios y sugerencias de finally

Un finally se ejecuta siempre; da lo mismo cmo termin el try: normal, return, error Java garantiza que se ejecutar la primera sentencia del finally. Las otras puede que no se ejecuten debido a excepciones Se recomienda que un finally libere slo un recurso (que tenga slo una sentencia) Para varios recursos, se recomienda que anide los finally uno dentro de otro

Excepciones

Tipos de excepciones en Java


Throwable Exception RuntimeException NullPointerException FileNotFoundException SQLException

checked unchecked

Error
VirtualMachineError

Ejemplo: leer propiedades de un archivo


public Properties leerPropiedades(String archivo) throws FileNotFoundException, IOException { // Verificamos archivo if (archivo == null) throw new NullPointerException("archivo es null");
// Abrimos archivo y cargamos las propiedades Properties propiedades = new Properties(); FileInputStream fis = new FileInputStream(archivo); try { propiedades.load(fis); } finally { fis.close(); } // Retornamos propiedades return propiedades;

Tragarse (perder) las excepciones


public String obtenerNombreUsuario(String archivo) { try { Properties props = leerPropiedades(archivo); return props.getProperty("nombre.usuario"); } catch (Exception ex) { ex.printStackTrace(); // esto es muy return null; // asqueroso! } }

Perdemos toda la info de la excepcin (mensaje, stack, causa), y retornamos un valor especial El que llama debe revisar el valor retornado, y si se olvida, no se entera que ocurri un error

Declarar cada excepcin checked


public String obtenerNombreUsuario(String archivo) throws FileNotFoundException, IOException { Properties props = leerPropiedades(archivo); return props.getProperty("nombre.usuario"); }

El que llama puede usar catch selectivos Las excepciones dan detalles de implementacin: encapsulacin pobre y posible acoplamiento No podemos agregar y/o eliminar excepciones de la lista debido a cambios en la implemencin

Declarar una sola excepcin genrica


public String obtenerNombreUsuario(String archivo) throws Exception { Properties props = leerPropiedades(archivo); return props.getProperty("nombre.usuario"); }

Se pierde el detalle de los errores, y el que llama al mtodo no puede usar catch selectivos Podemos cambiar la implementacin interna sin tener que cambiar la declaracin del mtodo

Convertir checked en unchecked


public String obtenerNombreUsuario(String archivo) { try { Properties props = leerPropiedades(archivo); return props.getProperty("nombre.usuario"); } catch (Exception ex) { throw new RuntimeException(ex); } }

No perdemos la info de la excepcin (mensaje, stack, causa), y no tenemos que declarar Podemos cambiar la implementacin interna sin tener que cambiar la declaracin del mtodo

Disparar unchecked con valor agregado


public String obtenerNombreUsuario(String archivo) { try { Properties props = leerPropiedades(archivo); return props.getProperty("nombre.usuario"); } catch (Exception ex) { throw new RuntimeException( "No se pudo obtener nombre del usuario" + " desde el archivo: " + fileName, ex); } }

Con todas las ventajas de la tcnica anterior, pero ahora entregamos informacin del contexto del error (en este caso, el nombre del archivo)

Disparar unchecked customizada


public String obtenerNombreUsuario(String archivo) { try { Properties props = leerPropiedades(archivo); return props.getProperty("nombre.usuario"); } catch (Exception ex) { throw new ObtenerException( "No se pudo obtener nombre del usuario" + " desde el archivo: " + fileName, ex); } }

Con todas las ventajas de la tcnica anterior, pero ahora podemos atrapar la excepcin en catch sin confundir con otras excepciones

Declaracin de ObtenerException
public class ObtenerException extends RuntimeException { public ObtenerException(String message, Throwable cause) { super(message, cause); } }

Como se observa, definir una excepcin de este tipo requiere de programacin muy, muy simple Estas excepciones pueden ser de tipo checked (heredan de Exception) o unchecked (heredan de RuntimeException)

Logging de Excepciones

Logging en cuanto ocurre la excepcin


public String obtenerNombreUsuario(String archivo) throws Exception { try { Properties props = leerPropiedades(archivo); return props.getProperty("nombre.usuario"); } catch (Exception ex) { ex.printStackTrace(); // logging throw ex; } }

En cuanto ocurre un error, se hace logging de la info de la excepcin (mensaje, stack, causa) Logging: System.out, printStackTrace, log4j,

Error muchos mensajes de logging


Mtodo fuera de su control try { b(); } catch (Exception ex) { ex.printStackTrace(); }

El mtodo d dispara una excepcin, y se hace logging en c, b y a

try { c(); } catch (Exception ex) { ex.printStackTrace(); throw ex; }

try { d(); } catch (Exception ex) { ex.printStackTrace(); throw ex; }

Error un solo mensaje de logging


Mtodo fuera de su control

try { b(); } catch (Exception ex) { ex.printStackTrace(); }

El mtodo d dispara una excepcin, y se hace logging una sola vez en a

try { b c(); } catch (Exception ex) { throw new Exception("", ex); } try { c d(); } catch (Exception ex) { throw new Exception("", ex); }

Error un solo mensaje de logging

Regla: dispare (throw) una excepcin si ella podr ser atrapada (catch) en uno de sus mtodos, de lo contrario haga logging Debe hacer logging cuando vaya a perder control de la excepcin. Por ejemplo en:

Mtodo main o run de una hebra (Thread)

Mtodo en pgina JSP o accin de Struts


Mtodo de un Servicio Web o de un MDB

Comentarios finales

Siempre libere los recursos con finally


Nunca se trague (pierda) la informacin de

una excepcin: mensaje, stack, causa

Redispare excepciones con valor agregado,

incluyendo la excepcin original (causa)

Haga logging de una excepcin slo una vez, en el mtodo que inici el trabajo

Muchas gracias

Você também pode gostar