apuntes:excepciones
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
apuntes:excepciones [2019/02/14 22:12] – Santiago Faci | apuntes:excepciones [2023/06/04 18:31] (current) – [Excepciones] Santiago Faci | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== | + | ====== |
- | \part*{Gestión de las Excepciones} | + | ===== Excepciones |
- | \section{Las excepciones} | + | Las excepciones |
+ | serie de errores que deben ser corregidos para que el programa pueda compilarse y generarse. Más tarde, durante la ejecución del mismo, | ||
+ | puedne producirse una serie de errores, los cuales son imposibles de detectar durante la fase de compilación. Son este tipo de errores los | ||
+ | que, en Java, acaban lanzando una excepción si llegan a producirse: | ||
- | Las excepciones son errores que se producen | + | * Estamos escribiendo |
- | Fallos como que el disco duro esté lleno, que no se pueda acceder | + | * Estamos descargando un fichero y cae la conexión a Internet ('' |
- | en un momento determinado y otro tipo de causas | + | * Estamos recorriendo un array en un bucle y accedemos |
- | controladas para que el fallo que puedan ocasionar se contenga y no permita que el programa falle. | + | * Accedemos atributos o métodos de un objeto cuyo valor es nulo ('' |
+ | * Realizamos una operación matemática | ||
- | Para controlar las excepciones | + | En Java se propone el control de excepciones |
- | forma podemos asociar un caso de error en caso de que se produzca dicha excepción, | + | |
- | aplicación pueda seguir ejecutándose sin problemas. Podríamos, por ejemplo, ofrecer | + | |
- | le podemos sugerir diferentes causas del error (quizás se haya quedado sin conexión o tenga que comprobar si tiene permisos para escribir en | + | |
- | la carpeta | + | |
- | \section{Recuperación | + | Se recomienda excepciones como '' |
- | \begin{lstlisting}[language=java] | + | ==== Tipos de Excepciones ==== |
+ | |||
+ | === Checked Exceptions === | ||
+ | |||
+ | * Excepciones que deben ser capturadas o declaradas en el método donde se producen | ||
+ | * Heredan directamente de la clase '' | ||
+ | * Por norma general serán el tipo de excepciones que deberemos capturar siempre en nuestro código | ||
+ | * '' | ||
+ | |||
+ | === Unchecked Exceptions === | ||
+ | |||
+ | * Excepciones que pueden ser lanzadas sin ser capturadas o declaradas | ||
+ | * Heredan de la clase '' | ||
+ | * Por norma general serán el tipo de excepciones que no deberemos capturar. Deberíamos evitar que se produjeran como, por ejemplo, en el caso de la excepción // | ||
+ | * '' | ||
+ | |||
+ | ==== Bloque try-catch ==== | ||
+ | |||
+ | El bloque // | ||
+ | para corregir o notificar el problema (parte // | ||
+ | |||
+ | < | ||
. . . | . . . | ||
try { | try { | ||
- | | + | |
- | } catch (< | + | } catch (Exception e1) { |
- | instrucciones_en_caso_de_que_se_produzca_la_excepcion; | + | } catch (Exception e2) { |
- | } [ finally | + | } . . . |
- | instrucciones_en_cualquier_caso; | + | |
- | } ] | + | |
. . . | . . . | ||
- | \end{lstlisting} | + | </ |
- | \begin{lstlisting}[language=java] | + | En este caso, el código que hay asociado al bloque //try// se ejecutará de forma que, si dentro de él se produjera una excepción, el flujo de ejecución pasaría al bloque //catch// de la excepción que corresponda. A continuación, |
+ | el grupo // | ||
+ | |||
+ | < | ||
. . . | . . . | ||
+ | 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(); | ||
} | } | ||
. . . | . . . | ||
- | \end{lstlisting} | + | </ |
- | \section{Creación y activación de Excepciones} | + | ==== Instrucción throws ==== |
- | También podemos | + | También podemos, |
- | tiempo | + | |
- | Para eso, primero tendremos | + | <code java> |
- | \verb throw . | + | 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 que utilizamos para parsear fechas en nuestra aplicación. Cuando el texto que se le pase no se corresponda con un formato válido de fecha, lanzará una excepción. Pero justamente en el método no tenemos muy 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> | ||
+ | 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 //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 //try//. De esta forma nos aseguramos que siempre se liberen correctamente, | ||
+ | |||
+ | <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 // | ||
+ | |||
+ | Por ejemplo, en una aplicación | ||
- | \begin{lstlisting}[language=java] | + | < |
- | public class NoRevisadoException | + | public class FueraDeStockException |
- | public | + | public |
super(); | super(); | ||
} | } | ||
- | public | + | public |
- | super(mensaje); | + | super(mensaje); |
} | } | ||
} | } | ||
- | \end{lstlisting} | + | </ |
- | A continuación, podremos utilizar la excepción | + | Así, cuando |
- | excepciones serán normalmente casos en los que el fallo está directamente relacionado con el funcionamiento de la propia lógica de negocio. | + | |
- | En el ejemplo siguiente, cuando se entrega un coche al cliente hay que comprobar que éste esté revisado previamente. En caso de que no lo | + | <code java> |
- | esté se producirá un error de tipo \verb NoRevisadoException | + | . . . |
- | \verb throws | + | private void anadirProductoAlCarrito(Producto producto) { |
- | \verb try-catch | + | if (producto.getStock() <= 0) { |
+ | throw new FueraDeStockException(); | ||
+ | } | ||
+ | } | ||
+ | . . . | ||
+ | </ | ||
- | \begin{lstlisting}[language=java] | + | Y de esta manera, por ejemplo, en el controlador o interaz de la aplicación, |
+ | |||
+ | <code java> | ||
+ | public class Ventana | ||
+ | . . . | ||
+ | try { | ||
+ | . . . | ||
+ | anadirProductoAlCarrito(producto); | ||
+ | . . . | ||
+ | | ||
+ | JOptionPane.showMessageDialog(. . .); | ||
+ | fdse.printStackTrace(); | ||
+ | } | ||
+ | . . . | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Bloques multi-catch ==== | ||
+ | |||
+ | También es posible capturar más de un tipo de excepción bajo un mismo bloque //catch//, aunque no es una práctica recomendada ya que no permite afinar el caso de error en algunos casos, pero bien utilizado permite que agrupemos en el caso de que varias excepciones tengan asociado el mismo bloque de código. | ||
+ | |||
+ | <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 // | ||
+ | |||
+ | < | ||
. . . | . . . | ||
- | 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 '' | ||
+ | |||
+ | <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 '' | ||
+ | |||
+ | Veamos un ejemplo: | ||
+ | |||
+ | <code java> | ||
. . . | . . . | ||
- | \end{lstlisting} | + | 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; | ||
+ | . . . | ||
+ | </ | ||
+ | |||
+ | Si ejecutamos el código anterior con la opción '' | ||
+ | <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-{{date> |
apuntes/excepciones.1550182379.txt.gz · Last modified: 2019/02/14 22:12 by Santiago Faci