Qué es una excepción
Una excepción es la forma que tiene Java de decir «algo salió mal y no puedo continuar normalmente». En lugar de devolver un valor incorrecto o corromper tus datos en silencio, el entorno de ejecución crea un objeto de excepción que describe el problema y lo lanza. La ejecución normal se detiene en ese punto y Java empieza a buscar código que sepa cómo afrontar la situación.
Si nadie la maneja, la excepción llega a la parte superior de tu programa, la JVM imprime una traza de pila y el proceso termina con un estado distinto de cero.
Fíjate en que "after" nunca se imprime. En el instante en que se evalúa numbers[5], se lanza una ArrayIndexOutOfBoundsException y se abandona el resto de main.
Leer una traza de pila
Cuando una excepción queda sin manejar, obtienes una salida como esta. Parece intimidante, pero no es más que una lista:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.divide(Main.java:8)
at Main.main(Main.java:4)
Léela de arriba hacia abajo:
- La primera línea es el tipo (
ArithmeticException) y un mensaje (/ by zero). - Cada línea
at ...es un marco de pila. La de arriba es donde realmente se lanzó la excepción:divideen la línea 8. Debajo está el llamador,mainen la línea 4.
La primera línea at es donde miras primero. Los marcos que hay debajo responden a la pregunta «¿cómo llegamos hasta aquí?».
Ejecuta esto y la traza apunta directamente a la línea a / b, y luego muestra main como el llamador. Esa cadena de llamadas es la herramienta de depuración más útil que Java te ofrece gratis.
La jerarquía de excepciones
Toda excepción es un objeto, y todas descienden de Throwable. Las dos ramas que importan:
Error: problemas graves que lanza la JVM, comoOutOfMemoryErroroStackOverflowError. Por lo general no los capturas.Exception: problemas que tu programa puede anticipar y manejar razonablemente. Dentro de ella se encuentraRuntimeException, la madre de los errores cotidianos comoNullPointerException.
Throwable
├── Error (don't catch: OutOfMemoryError, StackOverflowError)
└── Exception
├── IOException (checked)
├── SQLException (checked)
└── RuntimeException (unchecked)
├── NullPointerException
├── ArithmeticException
└── ArrayIndexOutOfBoundsException
Como son clases reales, una excepción puede llevar un mensaje y puedes preguntarle sobre sí misma:
getMessage() devuelve el texto que aparece tras los dos puntos en la traza de pila; getClass().getSimpleName() te da el tipo de excepción por su nombre.
Comprobadas frente a no comprobadas
Esta es la distinción que más confunde a los principiantes.
- Las excepciones no comprobadas extienden
RuntimeException. Normalmente significan un error en tu código: unnullque no esperabas, un índice incorrecto, una división entre cero. El compilador no te obliga a manejarlas. - Las excepciones comprobadas extienden
Exceptionpero noRuntimeException(por ejemplo,IOException). Representan condiciones fuera de tu control: un archivo que falta, una conexión de red que se cae. El compilador te obliga a capturarlas o a declararlas.
Si un método puede lanzar una excepción comprobada, debe indicarlo con throws, y todo llamador debe ocuparse de ella:
Quita throws Exception de main y el código ni siquiera compilará: ese es el compilador imponiendo el contrato de las excepciones comprobadas. Las excepciones no comprobadas nunca requieren esto.
Lanzar las tuyas
No solo reaccionas ante las excepciones, también puedes provocarlas. Usa throw con un nuevo objeto de excepción para indicar que un argumento o un estado no es válido. Esto es mucho mejor que devolver un valor mágico como -1 y esperar que el llamador lo compruebe.
Incluye siempre un mensaje que explique qué salió mal e, idealmente, el valor problemático: tu yo del futuro, leyendo la traza de pila, te lo agradecerá. IllegalArgumentException e IllegalStateException son las dos que más usarás al validar entradas.
Errores comunes
- Tragarse las excepciones. Capturar una excepción y no hacer nada (un bloque vacío) oculta los errores. Como mínimo regístrala; lo normal es que debas manejarla o relanzarla.
- Capturar
Exceptionde forma demasiado amplia. Capturar laExceptionbase (o peor,Throwable) puede enmascarar problemas que no querías manejar. Captura el tipo específico que esperas. - Leer la traza de abajo hacia arriba. El marco más relevante es la línea
atde arriba, no la de abajo. Empieza por ahí. - Confundir
ErrorconException. No intentes recuperarte deOutOfMemoryErrorni deStackOverflowError; corrige la causa subyacente.
Siguiente: try-catch
Ahora ya sabes qué son las excepciones y cómo leerlas. La siguiente página trata sobre cómo manejarlas de verdad: envolver el código riesgoso en un bloque try, recuperarte en catch y ejecutar código de limpieza en finally para que tu programa siga adelante en lugar de fallar.
Preguntas frecuentes
¿Qué es una excepción en Java?
Una excepción es un objeto que representa un problema detectado mientras se ejecuta un programa, como dividir entre cero, acceder a un índice más allá del final de un arreglo o llamar a un método sobre null. Cuando ocurre el problema, Java lanza la excepción: detiene el flujo normal y busca código que pueda manejarla. Si nada la maneja, el programa imprime una traza de pila y termina.
¿Cuál es la diferencia entre una excepción comprobada y una no comprobada en Java?
Las excepciones comprobadas (subclases de Exception pero no de RuntimeException, por ejemplo IOException) deben capturarse o declararse con throws: el compilador lo obliga. Las excepciones no comprobadas (subclases de RuntimeException, por ejemplo NullPointerException, ArrayIndexOutOfBoundsException) suelen indicar errores de programación y no necesitan declaración. Error (como OutOfMemoryError) también es no comprobada y, por lo general, no está pensada para capturarse.
¿Cómo leo una traza de pila en Java?
Léela de arriba hacia abajo. La primera línea nombra el tipo de excepción y el mensaje (por ejemplo, java.lang.ArithmeticException: / by zero). Cada línea at ... que aparece debajo es un marco de pila que muestra el método, el archivo y el número de línea, comenzando por donde se lanzó la excepción y retrocediendo a través de los llamadores. La primera línea at casi siempre es el lugar por donde empezar a mirar.