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
Excepciones de JavaManejo de excepcionesTirar declaración
Excepciones no verificadasManejo de excepciones comprobadasArroja declaración
Excepciones comprobadasManejo de excepciones no verificadasExcepciones de agrupación
Clases de excepciónExcepciones de lanzamientoExcepciones de anidación

¿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:
  1. Excepciones no verificadas (excepciones de tiempo de ejecución)
  2. 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 ArithmeticExceptionen 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 NullPointerExceptionTambién está entre las 4 principales excepciones de Java a las que se enfrentan los usuarios de Raygun. NullPointerExceptionsucede cuando su aplicación intenta usar nulldonde 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".
IOExceptionEs 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 IOExceptiony 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.
Excepciones comprobadas
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 ArithmeticExceptionIOExceptionestá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 Throwableclase es la superclase de todas las excepciones y errores de Java. Tiene dos subclases, ErrorExceptionaunque no representan marcada y sin marcar excepciones. La Exceptionclase tiene una subclase llamada RuntimeExceptionque contiene la mayoría de las excepciones no verificadas. Todas las demás subclases de Exceptionse 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 Exceptionexcepto las subclases de RuntimeExceptionse consideran excepciones comprobadas. - Las subclases de ErrorRuntimeExceptionse consideran como excepciones sin marcar.
Clases de excepción
Error,, ExceptionRuntimeExceptiontodos tienen varias subclases. Por ejemplo, IOExceptiones una subclase de ExceptionNullPointerExceptiones 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 trycatchfinallybloques. Puede usarlos para definir cómo desea manejar las excepciones cuando se producen. El trybloque debe incluir el código que puede o no lanzar una excepción. Cada catchbloque es un controlador de excepciones que trata con una excepción lanzada por el trybloque. El finallybloque se ejecuta en cualquier caso, ya sea que se haya lanzado una excepción o no.
Puedes incluir tantos catchbloques como quieras. Sin embargo, solo puede agregar uno finallya cada trybloque. Los programadores suelen utilizar finallybloques para realizar la limpieza después de que se hayan ejecutado los bloques trycatch.
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 IOExceptionejemplo que hemos discutido anteriormente, utilizando un try-catchbloque. Adjuntamos el código sensibles que podrían lanzar una IOExceptioncon un trybloque. El catchbloque solo se dispara si el trybloque 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 catchbloque. El código se lanza en FileNotFoundExceptionlugar de IOException, que es una subclase de IOExceptiony 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-catchbloques 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-catchbloque 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 throwdeclaración . ArithmeticException,, ArrayIndexOutOfBoundsExceptionNullPointerExceptionIOExceptionen nuestros ejemplos, todos fueron lanzados automáticamente por la plataforma Java.

La throwdeclaración

La throwdeclaración se puede utilizar con cualquier objeto lanzable que se hereda de la Throwableclase. Explica explícitamente una excepción desde cualquier bloque de código. Cada throwinstrucción dentro de un trybloque debe ser manejada por un catchbloque correspondiente .
Por ejemplo, nuestro IOExceptionejemplo 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 throwdeclaraciones a un trybloque como desee, sin embargo, cada una debe tener su propio catchbloque correspondiente .
Además, los catchbloques también pueden incluir su propia throwdeclaración. Podrías haber visto eso en el HttpServletRequestejemplo anterior. Cuando una catchdeclaració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 throwsdeclaración

Además throw, Java también tiene una throwsdeclaració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 throwspalabra clave, puede indicar que la persona que llama debe manejar esta excepción con su propio try-catchbloque.
Así es como se IOExceptionve 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-catchbloque. 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 throwspalabra 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 catchbloque. 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 catchcláusula separada , tendrá una base de código mucho más limpia.
Por ejemplo, puedes manejar IOExceptionIllegalAccessExceptionen el mismo catchbloque:
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 FileNotFoundExceptiones 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 catchclá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 IOExceptionejemplo:
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 catchbloque crea una segunda excepción llamada e2que especifica la razón e2y se refiere a e1la 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).
La Exceptionclase tiene cinco constructores posibles ; El ejemplo anterior utiliza el siguiente:
public Exception(String message, Throwable cause)
Si ejecuta el código de ejemplo, la consola imprime todo el seguimiento de la pila:
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 e2Esto muestra que la nueva excepción se ha anidado correctamente. La e2excepción también mantiene una referencia a e1, su excepción de anidación.
Tenga en cuenta que agregamos e2a la firma del método usando la throwspalabra clave. Entonces, el código que llama al main()método tendrá que manejarse e2con un try-catchbloque. 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.