apuntes:excepciones
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
apuntes:excepciones [2019/02/16 11:31] – Santiago Faci | apuntes:excepciones [2021/03/10 13:39] – Santiago Faci | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== | + | ====== |
- | ===== Las excepciones | + | ===== Excepciones |
- | Las excepciones son errores que se producen en tiempo de ejecución | + | Las excepciones |
- | controladas para que el fallo que puedan ocasionar se contenga y no permita que el programa falle. | + | serie de errores |
+ | puedne producirse una serie de errores, los cuales son imposibles de detectar durante | ||
+ | que, en Java, acaban lanzando una excepción si llegan a producirse: | ||
- | Para controlar las excepciones existe, | + | * Estamos escribiendo |
- | le podemos sugerir diferentes causas del error (quizás se haya quedado sin conexión | + | * Estamos descargando un fichero |
+ | * Estamos recorriendo un array en un bucle y accedemos | ||
+ | * Accedemos atributos | ||
+ | * Realizamos una operación matemática no válida (división por cero) (\verb ArithmeticException | ||
- | ===== Recuperación | + | En Java se propone el control |
+ | estructuras \verb if que controlen que no ocurre nada anómalo que impida la ejecución de un cierto código. Así, lo que haremos será colocar | ||
+ | dentro un bloque controlado todo el código (y el que dependa de éste) que sea susceptible de producir una excepción, sin interrumpir el | ||
+ | flujo de nuestro programa (al contrario de lo que ocurre añadiendo sentencias \verb if ). | ||
+ | |||
+ | Se recomienda excepciones como \verb NullPointerException | ||
+ | general, corresponderán a errores de codificación, | ||
+ | esperando capturarlas cuando se produzcan. Son dos excepciones que derivan de \verb RuntimeException . Son lo que se conoce como | ||
+ | \emph{unchecked exceptions}. Echa un vistazo a | ||
+ | | ||
+ | |||
+ | \subsection{Bloque try-catch} | ||
+ | |||
+ | El bloque \verb try-catch | ||
+ | para corregir o notificar el problema (parte \verb catch ). | ||
<code java> | <code java> | ||
. . . | . . . | ||
try { | try { | ||
- | | + | |
- | } catch (< | + | } catch (Exception e1) { |
- | instrucciones_en_caso_de_que_se_produzca_la_excepcion; | + | } catch (Exception e2) { |
- | } [ finally | + | } . . . |
- | instrucciones_en_cualquier_caso; | + | |
- | } ] | + | |
. . . | . . . | ||
</ | </ | ||
+ | |||
+ | En este caso, el código que hay asociado al bloque \verb try se ejecutará de forma que, si dentro de él se produjera una excepción, el | ||
+ | flujo de ejecución pasaría al bloque \verb catch de la excepción que corresponda. A continuación, | ||
+ | el grupo \verb try-catch . | ||
<code java> | <code java> | ||
. . . | . . . | ||
+ | File fichero = null; | ||
+ | FileReader lectorFichero = null; | ||
+ | BufferedReader buffer = null; | ||
try { | try { | ||
- | | + | |
- | | + | |
- | | + | |
- | } catch (NumberFormatException nfe) { | + | System.out.println(linea); |
- | | + | } |
- | | + | buffer.close(); |
- | System.out.println(" | + | } catch (FileNotFoundException fnfe) { |
+ | | ||
+ | | ||
+ | } catch (IOException ioe) { | ||
+ | System.out.println(" | ||
+ | ioe.printStackTrace(); | ||
} | } | ||
. . . | . . . | ||
</ | </ | ||
- | ===== Creación y activación de Excepciones ===== | + | ==== Instrucción throws |
- | También podemos | + | También podemos, |
+ | estoy desarrollando una clase que debe controlar una determinada excepción, quizás me pueda resultar interesante hacerla " | ||
+ | para que sea controlada, por ejemplo, | ||
+ | podamos ajustar mejor el comportamiento en caso de error. | ||
- | Para eso, primero tendremos | + | <code java> |
+ | public class Util { | ||
+ | public static Date parseFecha(String fecha) throws ParseException { | ||
+ | SimpleDateFormat sdf = new SimpleDateFormat(" | ||
+ | return sdf.parse(fecha); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | El ejemplo de arriba es un caso en el que tenemos un método estático | ||
+ | texto que se le pase no se corresponda con un formato válido | ||
+ | claro que hacer puesto que dicho método lo utilizarán desde diferentes localizaciones del código en la aplicación. Por eso es mejor que | ||
+ | lancemos fuera la excepción para que sea quién utilice este método quién deba decidir qué hacer en caso de fallo. Por ejemplo: | ||
<code java> | <code java> | ||
- | public class NoRevisadoException extends Exception | + | public class Ventana |
+ | . . . | ||
+ | private JTextField tfFecha; | ||
+ | . . . | ||
+ | private void comprobarInput() { | ||
+ | . . . | ||
+ | |||
+ | try { | ||
+ | . . . | ||
+ | Date fecha = Util.parseFecha(tfFecha.getText()); | ||
+ | . . . | ||
+ | } catch (ParseException pe) { | ||
+ | JOptionPane.showMessageDialog(. . .); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
- | | + | ==== Bloque try-catch-finally ==== |
+ | |||
+ | Se puede añadir también un tercer bloque de código asociado a la parte \verb try que permite añadir código que se ejecutará siempre, de | ||
+ | forma que incluso lo hará cuando se produzca una excepción no controlada. Normalmente se utiliza para la zona donde liberar recursos que | ||
+ | hayan sido ocupados durante el bloque \verb try . De esta forma nos aseguramos que siempre se liberen correctamente, | ||
+ | de ejecución del código se vea interrumpido por una excepción. | ||
+ | |||
+ | <code java> | ||
+ | . . . | ||
+ | BufferedReader buffer = null; | ||
+ | try { | ||
+ | buffer = new BufferedReader(new FileReader(new File(" | ||
+ | String linea = null; | ||
+ | while ((linea = buffer.readLine()) != null) { | ||
+ | System.out.println(linea); | ||
+ | } | ||
+ | } catch (FileNotFoundException fnfe) { | ||
+ | System.out.println(" | ||
+ | fnfe.printStackTrace(); | ||
+ | } catch (IOException ioe) { | ||
+ | System.out.println(" | ||
+ | ioe.printStackTrace(); | ||
+ | } finally { | ||
+ | if (buffer != null) { | ||
+ | try { | ||
+ | buffer.close(); | ||
+ | } catch (IOException ioe) { | ||
+ | ioe.printStackTrace(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | . . . | ||
+ | </ | ||
+ | |||
+ | ==== Cómo crear tus propias excepciones ==== | ||
+ | |||
+ | Como ya hemos visto, Java tiene una serie de \emph{unchecked} y \emph{checked exceptions} que son lanzadas en determinadas situaciones. | ||
+ | Vamos a ver ahora cómo también podemos crear nuestras propias excepciones y lanzarlas cuando se produzcan situaciones de "más alto nivel" en | ||
+ | nuestra lógica de la aplicación. | ||
+ | |||
+ | Por ejemplo, en una aplicación para la gestión de inventarios, | ||
+ | |||
+ | <code java> | ||
+ | public | ||
+ | |||
+ | public FueraDeStockException() { | ||
super(); | super(); | ||
} | } | ||
- | public | + | public |
- | super(mensaje); | + | super(mensaje); |
} | } | ||
} | } | ||
</ | </ | ||
- | A continuación, podremos utilizar la excepción | + | Así, cuando |
- | En el ejemplo | + | <code java> |
+ | . . . | ||
+ | private void anadirProductoAlCarrito(Producto producto) { | ||
+ | if (producto.getStock() <= 0) { | ||
+ | throw new FueraDeStockException(); | ||
+ | } | ||
+ | } | ||
+ | . . . | ||
+ | </ | ||
+ | |||
+ | Y de esta manera, por ejemplo, | ||
+ | |||
+ | <code java> | ||
+ | public class Ventana { | ||
+ | . . . | ||
+ | try { | ||
+ | . . . | ||
+ | anadirProductoAlCarrito(producto); | ||
+ | . . . | ||
+ | } catch (FueraDeStockException fdse) { | ||
+ | JOptionPane.showMessageDialog(. . .); | ||
+ | fdse.printStackTrace(); | ||
+ | } | ||
+ | . . . | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Bloques multi-catch ==== | ||
+ | |||
+ | También es posible capturar más de un tipo de excepción bajo un mismo bloque \verb catch , aunque no es una práctica recomendada ya que no | ||
+ | permite afinar el caso de error en algunos casos, pero bien utilizado permite | ||
+ | asociado el mismo bloque | ||
+ | |||
+ | <code java> | ||
+ | public class Ventana { | ||
+ | . . . | ||
+ | try { | ||
+ | . . . | ||
+ | anadirProductoAlCarrito(producto); | ||
+ | . . . | ||
+ | } catch (FueraDeStockException | ProductoDescatalogadoException e) { | ||
+ | JOptionPane.showMessageDialog(. . .); | ||
+ | fdse.printStackTrace(); | ||
+ | } | ||
+ | . . . | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Uso de recursos en bloques try-catch ==== | ||
+ | |||
+ | Como hemos visto en el primer ejemplo, accedíamos a un fichero en la excepción, para luego acabar liberando los recursos al finalizar el | ||
+ | bloque | ||
+ | liberen al terminar. Así, ese ejemplo podría escribirse de la siguiente forma: | ||
<code java> | <code java> | ||
. . . | . . . | ||
- | public void entregarVehiculo() throws NoRevisadoException | + | try (BufferedReader buffer = |
- | + | new BufferedReader(new FileReader(new File(" | |
- | | + | |
- | | + | |
+ | | ||
} | } | ||
+ | } catch (FileNotFoundException fnfe) { | ||
+ | System.out.println(" | ||
+ | fnfe.printStackTrace(); | ||
+ | } catch (IOException ioe) { | ||
+ | System.out.println(" | ||
+ | ioe.printStackTrace(); | ||
+ | } | ||
+ | . . . | ||
+ | </ | ||
+ | |||
+ | Para este caso, hay que tener en cuenta que, para que Java pueda liberar automáticamente los recursos de una clase Java, debemos implementar | ||
+ | uno de los interfaces \verb java.lang.AutoClosable | ||
+ | |||
+ | <code java> | ||
+ | public class MiRecurso implements AutoCloseable { | ||
. . . | . . . | ||
. . . | . . . | ||
+ | public void close() throws Exception { | ||
+ | // Aqui hay que liberar los recursos | ||
+ | // Se ejecutará automáticamente | ||
+ | . . . | ||
+ | . . . | ||
+ | } | ||
} | } | ||
+ | </ | ||
+ | |||
+ | ===== Aserciones ===== | ||
+ | |||
+ | Las aserciones son sentencias utilizadas para comprobar si una condición es cierta (o no) y controlar asi los errores en el código. | ||
+ | Básicamente equivale a una sentencia \verb if que evalúa una condición y genera una Excepción \verb AssertException | ||
+ | mostrando el mensaje asociado a la misma. De forma similar a | ||
+ | cómo hacen las excepciones, | ||
+ | sólo tienen efecto si se pasa la opción \verb -ea o \verb -enableassertions | ||
+ | forma sólo se activan cuando es necesario o interesa utilizarlas. | ||
+ | |||
+ | Veamos un ejemplo: | ||
+ | |||
+ | <code java> | ||
+ | . . . | ||
+ | String cadena = "Esto es un texto"; | ||
+ | . . . | ||
+ | . . . | ||
+ | assertion cadena == null : "La cadena es nula"; | ||
+ | . . . | ||
+ | // También se puede especificar una condición sin mensaje | ||
+ | assertion cadena == null; | ||
. . . | . . . | ||
</ | </ | ||
- | ====== Ejemplos ====== | + | Si ejecutamos el código anterior con la opción \verb -ea activada como opción de la JVM, se nos mostrará el siguiente mensaje de error: |
+ | |||
+ | <code bash> | ||
+ | run: | ||
+ | Exception in thread " | ||
+ | at com.sfaci.prueba.JavaApplication5.main(JavaApplication5.java: | ||
+ | / | ||
+ | BUILD FAILED (total time: 0 seconds) | ||
+ | </ | ||
---- | ---- | ||
- | (c) 2019 Santiago Faci | + | (c) 2019-2021 Santiago Faci |
apuntes/excepciones.txt · Last modified: 2023/06/04 18:31 by Santiago Faci