El lenguaje de programación Java viene con funciones avanzadas de manejo de excepciones que ayudan a los programadores a gestionar eventos excepcionales. En Java, las compilaciones son lanzadas por el compilador o ocurren durante la ejecución del programa. Las excepciones detienen el flujo normal del programa, por lo que debe manejarlas adecuadamente.
En este artículo, veremos todos los términos y ejemplos que necesita saber sobre las excepciones de Java en 2018.
Navegación rápida
¿Qué son las excepciones de Java?
Las excepciones de Java son eventos que interrumpen la ejecución normal del programa. El principal objetivo de las excepciones es separar el manejo de errores del código regular. Las excepciones pueden deberse a una amplia gama de problemas, como la falta de recursos, los errores de codificación, los errores de memoria y otros. En Java, hay dos tipos de excepciones:
- Excepciones no verificadas (excepciones de tiempo de ejecución)
- Excepciones comprobadas ( excepciones en tiempo de compilación)
1. Excepciones no verificadas
Las excepciones sin marcar son problemas que ocurren en tiempo de ejecución. También se llaman excepciones no capturadas o en tiempo de ejecución. Como las excepciones no marcadas no se marcan en el momento de la compilación, no es necesario que especifique o maneje la excepción (aunque puede hacerlo si lo desea). Por lo general, son el resultado de malas prácticas de codificación o errores lógicos, como errores de datos, argumentos no válidos o recursos faltantes.
Los errores aritméticos básicos, como la división por cero, son el ejemplo más sencillo de las excepciones no verificadas. Por ejemplo, aquí hay un ejemplo de código que se lanza
ArithmeticException
en tiempo de ejecución:public class ArithmeticException {
public static void main(String[] args) {
int a = 0;
int b = 100;
int c = b/a;
System.out.println("Result: " + c);
}
}
Por supuesto, dividir por cero es una operación que es imposible de ejecutar. La salida de la consola es:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at arithmetic.ArithmeticException.main(ArithmeticException.java:9)
Querer acceder a datos no existentes es otro ejemplo típico de excepciones no verificadas. Supongamos que tiene una matriz de seis elementos e intente imprimir el elemento en el índice 10:
public class InvalidArrayIndex {
public static void main(String[] args) {
int myArray[] = {0, 1, 2, 3, 4, 5};
System.out.println(myArray[10]);
}
}
Como no hay nada en el índice 10, el ejemplo de código anterior arroja
ArrayIndexOutOfBoundsException
:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
at invalidarrayindex.InvalidArrayIndex.main(InvalidArrayIndex.java:8)
También hay ejemplos más complicados de excepciones no verificadas. Se llama la excepción no verificada más frecuente
NullPointerException
. También está entre las 4 principales excepciones de Java a las que se enfrentan los usuarios de Raygun. NullPointerException
sucede cuando su aplicación intenta usar null
donde se requiere un objeto. Esto puede deberse a diferentes motivos, como acceder a una variable sin inicializar o llamar al método de instancia de un objeto nulo.2. Excepciones comprobadas
Las excepciones comprobadas también se denominan excepciones de tiempo de compilación, ya que surgen en el tiempo de compilación. El código Java que contiene cualquier excepción marcada no se compilará. Cuando intenta ejecutar dicho código, el compilador le advierte sobre la presencia de la excepción verificada. Si aún elige compilar el código, aparecerá el mensaje "Problemas de compilación no resueltos".
IOException
Es una de las excepciones comprobadas más comunes en Java. Es causado por diferentes problemas de entrada-salida, como el acceso a archivos no válidos o errores de red.Aquí hay un ejemplo. El siguiente código intenta acceder a un archivo que no existe, luego escribir algo en él:
import java.io.FileWriter;
public class FileNotFound {
public static void main(String args[]) {
FileWriter myWriter = new FileWriter("C://filenotfound.txt");
myWriter.write("Hi, I'm trying to write something.");
myWriter.close();
}
}
No hace falta decir que no es posible escribir nada en un archivo que no existe. Mi IDE de Eclipse me informa sobre la presencia
IOException
y me pregunta si todavía quiero compilar el código.Recuerde que el compilador no tuvo quejas en el caso de excepciones no controladas, ya que se lanzarán solo en tiempo de ejecución.
Si continúo con la excepción no controlada, el compilador devuelve el siguiente mensaje de error:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
Unhandled exception type IOException
Unhandled exception type IOException
Unhandled exception type IOException
at fileNotFound.FileNotFound.main(FileNotFound.java:8)
Para resolver el problema de compilación, el método en el que se produce la excepción comprobada debe manejarlo o al menos especificarlo. Antes de mostrar cómo hacerlo, echemos un vistazo a la jerarquía de clases de excepción de Java.
3. Clases de excepción.
Las clases de excepción son clases de Java que incluyen todas las excepciones marcadas y no marcadas. Las excepciones que mencioné anteriormente, como
ArithmeticException
y IOException
están representadas por una clase de excepción. De hecho, Java tiene una jerarquía extensa de clases primarias y secundarias que cubren la mayoría de los problemas que pueden ocurrir durante la compilación o en tiempo de ejecución.Sin embargo, la clasificación de las excepciones de Java es un poco confusa. La
Throwable
clase es la superclase de todas las excepciones y errores de Java. Tiene dos subclases, Error
y Exception
aunque no representan marcada y sin marcar excepciones. La Exception
clase tiene una subclase llamada RuntimeException
que contiene la mayoría de las excepciones no verificadas. Todas las demás subclases de Exception
se manejan como excepciones verificadas. Además de las excepciones de tiempo de ejecución, los errores también cuentan como excepciones no verificadas.Entonces: - Las subclases de
Exception
excepto las subclases de RuntimeException
se consideran excepciones comprobadas. - Las subclases de Error
y RuntimeException
se consideran como excepciones sin marcar.Error
,, Exception
y RuntimeException
todos tienen varias subclases. Por ejemplo, IOException
es una subclase de Exception
y NullPointerException
es una subclase de RuntimeException
.Es posible que haya notado que Java diferencia los errores de las excepciones.
¿Por qué es así?
En Java, los errores indican condiciones anormales como el desbordamiento de pila que las aplicaciones no deberían intentar detectar. En su mayoría son causados por el entorno, en oposición a las excepciones que son causadas por el programa en sí.
Las excepciones se detectan en tiempo de compilación o en tiempo de ejecución. Los errores terminan el programa con seguridad y no se pueden manejar de ninguna manera. Sin embargo, las excepciones pueden ser recuperadas por ciertas técnicas de programación.
4. Manejo de excepciones.
El manejo de excepciones en Java sucede con los
try
, catch
y finally
bloques. Puede usarlos para definir cómo desea manejar las excepciones cuando se producen. El try
bloque debe incluir el código que puede o no lanzar una excepción. Cada catch
bloque es un controlador de excepciones que trata con una excepción lanzada por el try
bloque. El finally
bloque se ejecuta en cualquier caso, ya sea que se haya lanzado una excepción o no.Puedes incluir tantos
catch
bloques como quieras. Sin embargo, solo puede agregar uno finally
a cada try
bloque. Los programadores suelen utilizar finally
bloques para realizar la limpieza después de que se hayan ejecutado los bloques try
y catch
.Aquí está la sintaxis general del manejo de excepciones de Java:
try {
// Code that might throw exceptions.
} catch (Exception e1) {
// Catch block 1. Executes if try block throws e1.
} catch (Exception e2) {
// Catch block 2. Executes if try block throws e2.
} catch (Exception e3) {
// Catch block 3. Executes if try block throws e3.
} finally {
// Cleanup code. Always executes.
}
Manejo de excepciones comprobadas
Aquí es cómo puede manejar el
IOException
ejemplo que hemos discutido anteriormente, utilizando un try-catch
bloque. Adjuntamos el código sensibles que podrían lanzar una IOException
con un try
bloque. El catch
bloque solo se dispara si el try
bloque lanza un IOException
.public class FileNotFound {
public static void main(String args[]) {
FileWriter myWriter;
try {
myWriter = new FileWriter("C://filenotfound.txt");
myWriter.write("Hi, I'm trying to write something.");
myWriter.close();
} catch (IOException e) {
System.out.println("Exception thrown: " + e);
} finally {
System.out.println("End of execution.");
}
}
}
Ahora, la salida de la consola cambia del mensaje generado por el sistema a las instrucciones que hemos dado dentro del
catch
bloque. El código se lanza en FileNotFoundException
lugar de IOException
, que es una subclase de IOException
y proporciona la descripción más cercana del problema.Exception thrown: java.io.FileNotFoundException: C:\filenotfound.txt (Access is denied)
End of execution.
Manejo de excepciones no verificadas
También puede usar
try-catch
bloques para manejar una excepción sin marcar. Si bien el manejo de excepciones sin marcar no es obligatorio, es una buena idea usar un try-catch
bloque para fines de registro y monitoreo. El siguiente ejemplo es del Wikilibro de programación de Java y muestra cómo el registro de una excepción no verificada puede ser útil en la programación de servlets:public long getLastModified(HttpServletRequest req) {
try {
...
return getTimeStamp();
...
} catch(RuntimeException e) {
log.error("Error during handling post request", e);
throw e;
}
}
El código anterior se llama cuando un servidor de aplicaciones realiza una solicitud al servidor. Primero, captura las excepciones de tiempo de ejecución para fines de registro. Luego, los arroja de vuelta al servidor para que pueda manejarlos. De esta manera, la aplicación tiene su propio sistema de registro independiente del registro del servidor y puede detectar todas las excepciones de tiempo de ejecución por su cuenta.
Excepciones de lanzamiento
Lanzar excepciones es una técnica de programación específica en Java. Solo puede capturar una excepción que se haya lanzado antes, ya sea por la plataforma Java o por un código personalizado. Excepción de lanzamiento en Java sucede con la
throw
declaración . ArithmeticException
,, ArrayIndexOutOfBoundsException
y NullPointerException
, IOException
en nuestros ejemplos, todos fueron lanzados automáticamente por la plataforma Java.La throw
declaración
La
throw
declaración se puede utilizar con cualquier objeto lanzable que se hereda de la Throwable
clase. Explica explícitamente una excepción desde cualquier bloque de código. Cada throw
instrucción dentro de un try
bloque debe ser manejada por un catch
bloque correspondiente .Por ejemplo, nuestro
IOException
ejemplo también podría escribirse de esta manera:public class FileNotFound {
public static void main(String args[]) {
FileWriter myWriter;
try {
myWriter = new FileWriter("C://filenotfound.txt");
myWriter.write("Hi, I'm trying to write something.");
myWriter.close();
throw new IOException();
} catch (IOException e) {
System.out.println("Exception thrown: " + e);
} finally {
System.out.println("End of execution.");
}
}
}
Puede agregar tantas
throw
declaraciones a un try
bloque como desee, sin embargo, cada una debe tener su propio catch
bloque correspondiente .Además, los
catch
bloques también pueden incluir su propia throw
declaración. Podrías haber visto eso en el HttpServletRequest
ejemplo anterior. Cuando una catch
declaración lanza una excepción, debe ser manejada por el código que llama al método. Esta técnica también se conoce como volver a lanzar una excepción.La throws
declaración
Además
throw
, Java también tiene una throws
declaración. Se puede usar en la firma de cualquier método que pueda generar una excepción marcada. Supongamos que tiene una excepción marcada que evitaría que el código se compile, pero no quiere o no puede manejarlo dentro del método actual. Usando la throws
palabra clave, puede indicar que la persona que llama debe manejar esta excepción con su propio try-catch
bloque.Así es como se
IOException
ve nuestro ejemplo cuando no lo manejamos directamente, sino que lo delegamos al método del llamador:public class FileNotFound {
public static void main(String args[]) throws IOException {
FileWriter myWriter;
myWriter = new FileWriter("C://filenotfound.txt");
myWriter.write("Hi, I'm trying to write something.");
myWriter.close();
}
}
Como puedes ver, no hay manejo con un
try-catch
bloque. Solo indicamos la presencia de la excepción en la firma del método para que la persona que llama pueda decidir cómo quiere manejarlo.Puede agregar tantas excepciones después de la
throws
palabra clave en la firma del método como desee. Por ejemplo:public static void main(String args[]) throws IOException, IllegalAccessException
Excepciones de agrupación
Agrupar excepciones es un acceso directo de programación que le permite manejar múltiples excepciones en un solo
catch
bloque. Esta técnica está disponible desde Java 7 . Es una gran solución cuando desea ejecutar el mismo código en diferentes excepciones. Como no tiene que manejar cada excepción en una catch
cláusula separada , tendrá una base de código mucho más limpia.Por ejemplo, puedes manejar
IOException
y IllegalAccessException
en el mismo catch
bloque:catch (IOException | IllegalAccessException e) {
System.out.println("Exception thrown: " + e);
}
Sin embargo, hay una regla importante. Solo puede agrupar las excepciones que no están relacionadas entre sí. No está permitido agrupar excepciones que tengan una relación padre-hijo. Por ejemplo, el siguiente código no se compilará, ya que
FileNotFoundException
es una subclase de IOException
:catch (IOException | FileNotFoundException e) {
System.out.println("Exception thrown: " + e);
}
El compilador devuelve un mensaje de "problema de compilación no resuelto":
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The exception FileNotFoundException is already caught by the alternative IOException
at fileNotFound.FileNotFound.main(FileNotFound.java:22)
Excepciones de anidación
La anidación de excepciones ocurre en Java cuando una excepción da como resultado una segunda excepción que se traduce en una tercera excepción, etc. Al lidiar con toda una cadena de excepciones, las excepciones anidadas también se denominan excepciones encadenadas . El seguimiento de pila de una excepción contiene la cadena de excepciones que han conducido a la excepción final.
Puede anidar una excepción de Java en otra utilizando la
catch
cláusula. Las excepciones anidadas pueden ayudarlo a identificar por qué se ha lanzado una excepción.Por ejemplo, así es como funciona el anidamiento de excepciones con nuestro
IOException
ejemplo:public class FileNotFound {
public static void main(String args[]) throws Exception {
FileWriter myWriter;
try {
myWriter = new FileWriter("C://filenotfound.txt");
myWriter.write("Hi, I'm trying to write something.");
myWriter.close();
} catch (IOException e1) {
Exception e2 = new Exception("Couldn't write into a non-existent file.", e1);
throw e2;
}
}
}
Como puede ver, el
catch
bloque crea una segunda excepción llamada e2
que especifica la razón e2
y se refiere a e1
la causa de la excepción. Luego, vuelve a lanzar la nueva excepción para que el método del llamador pueda manejarla (o volver a lanzarla).public Exception(String message, Throwable cause)
Exception in thread "main" java.lang.Exception: Couldn't write into non-existent file.
at fileNotFound.FileNotFound.main(FileNotFound.java:21)
Caused by: java.io.FileNotFoundException: C:\filenotfound.txt (Access is denied)
at java.base/java.io.FileOutputStream.open0(Native Method)
at java.base/java.io.FileOutputStream.open(Unknown Source)
at java.base/java.io.FileOutputStream.<init>(Unknown Source)
at java.base/java.io.FileOutputStream.<init>(Unknown Source)
at java.base/java.io.FileWriter.<init>(Unknown Source)
at fileNotFound.FileNotFound.main(FileNotFound.java:14)
El seguimiento de la pila comienza con el mensaje personalizado que definimos como el primer argumento de
e2
. Esto muestra que la nueva excepción se ha anidado correctamente. La e2
excepción también mantiene una referencia a e1
, su excepción de anidación.Tenga en cuenta que agregamos
e2
a la firma del método usando la throws
palabra clave. Entonces, el código que llama al main()
método tendrá que manejarse e2
con un try-catch
bloque. Este tipo de conversión de excepción puede ocurrir siempre y cuando el método de la persona que llama esté dispuesto a manejarlo, en lugar de simplemente volver a lanzarlo a la siguiente persona que llama.
0 Comentarios