Saltar al contenido principal

Crear nuevas excepciones

En Java, puedes crear excepciones personalizadas definiendo una nueva clase que extienda la clase Exception o RuntimeException, dependiendo de si quieres que la excepción sea verificada (checked) o no (unchecked).

Las excepciones personalizadas son útiles cuando quieres representar errores específicos de tu aplicación que no están cubiertos por las excepciones estándar de Java. Permiten añadir contexto e información adicional a los errores en tu aplicación, mejorando la capacidad de depuración y mantenimiento del código.

Pasos para crear una excepción personalizada

  1. Elige la superclase:
    • Si quieres una excepción verificada (checked exception), haz que tu clase extienda Exception.
    • Si quieres una excepción no verificada (unchecked exception), haz que tu clase extienda RuntimeException.
  2. Define un constructor:
    • Normalmente, creas varios constructores para pasar mensajes u otras excepciones encadenadas.
    • El constructor más común simplemente toma un mensaje como argumento.
  3. Implementa la clase de tu excepción:
    • Añade métodos adicionales o campos si necesitas almacenar información específica del error.

Excepción verificada personalizada

Aquí creamos una excepción verificada (checked exception) llamada ExcepcionPersonalizada que extiende Exception. Esto significa que será una excepción verificada, y el compilador obligará a manejarla o declararla.

// Excepción personalizada verificada
public class ExcepcionPersonalizada extends Exception {

// Constructor sin argumentos
public ExcepcionPersonalizada() {
super("Error personalizado ocurrido");
}

// Constructor que acepta un mensaje personalizado
public ExcepcionPersonalizada(String message) {
super(message);
}

// Constructor que acepta un mensaje y otra excepción como causa
public ExcepcionPersonalizada(String message, Throwable cause) {
super(message, cause);
}
}

Para usar esta excepción, podrías lanzarla con una sentencia throw en una parte del código donde desees detectar un error específico. Aquí un ejemplo de uso:

public class EjemploUso {
public static void main(String[] args) {
try {
lanzarError();
} catch (ExcepcionPersonalizada e) {
System.out.println("Capturada: " + e.getMessage());
}
}

public static void lanzarError() throws ExcepcionPersonalizada {
throw new ExcepcionPersonalizada("Algo salió mal.");
}
}

Excepción personalizada no verificada

Para crear una excepción no verificada (unchecked exception), haz que tu clase extienda RuntimeException. El compilador no obligará a manejar esta excepción.

// Excepción personalizada no verificada
public class ExcepcionRuntimePersonalizada extends RuntimeException {

// Constructor sin argumentos
public ExcepcionRuntimePersonalizada() {
super("Error en tiempo de ejecución personalizado");
}

// Constructor que acepta un mensaje personalizado
public ExcepcionRuntimePersonalizada(String message) {
super(message);
}

// Constructor que acepta un mensaje y otra excepción como causa
public ExcepcionRuntimePersonalizada(String message, Throwable cause) {
super(message, cause);
}
}

Y así sería su uso:

public class EjemploUsoRuntime {
public static void main(String[] args) {
try {
lanzarErrorRuntime();
} catch (ExcepcionRuntimePersonalizada e) {
System.out.println("Capturada excepción no verificada: " + e.getMessage());
}
}

public static void lanzarErrorRuntime() {
throw new ExcepcionRuntimePersonalizada("Error en tiempo de ejecución detectado.");
}
}

Cómo obtener el mensaje de error

Tenemos la siguiente excepción propia llamada Excepcion, que hereda de Exception:

class Excepcion extends Exception {
public Excepcion(String mensaje) {
super(mensaje); // Llamamos al constructor de la superclase Exception
}
}

Si la utilizamos en una clase con printStackTrace(), se nos mostrará el mensaje que indicamos en el constructor:

public class EjemploExcepcionPersonalizada {
public static void main(String[] args) {
try {
lanzarError();
} catch (Excepcion e) {
e.printStackTrace(); // Muestra la traza del error
}
}

public static void lanzarError() throws Excepcion {
throw new Excepcion("Error personalizado: ¡algo falló!");
}
}

Esto producirá el siguiente mensaje:

Excepcion: Error personalizado: ¡algo falló!
at EjemploExcepcionPersonalizada.lanzarError(EjemploExcepcionPersonalizada.java:12)
at EjemploExcepcionPersonalizada.main(EjemploExcepcionPersonalizada.java:6)

Si utilizamos e.getMessage() tan sólo obtendremos el mensaje:

try {
lanzarError();
} catch (Excepcion e) {
System.out.println("Excepción capturada: " + e.getMessage());
}

Consideraciones al crear excepciones personalizadas

  • Usa excepciones personalizadas cuando sea necesario: No abuses de ellas. Usa excepciones personalizadas sólo cuando tengan un significado específico para tu dominio o aplicación.
  • Mensajes claros: Siempre que sea posible, proporciona mensajes claros en tus excepciones para que sea fácil entender el error.
  • Encadenamiento de excepciones: Usa el encadenamiento (pasando la excepción original) para preservar el rastro de la pila de errores, lo que facilita la depuración.

Ejemplo

En este ejemplo, vamos a crear dos excepciones personalizadaS: una para cuando un DNI no es válido y otra para cuando una edad es negativa.

ExcepcionDniInvalido.java
public class ExcepcionDniInvalido extends Exception{
public ExcepcionDniInvalido(String mensaje) {
super(mensaje);
}
}
ExcepcionEdadNegativa.java
public class ExcepcionEdadNegativa extends Exception {
public ExcepcionEdadNegativa(String mensaje) {
super(mensaje);
}
}

La clase Persona utilizará las dos excepciones:

  • Controlamos que la edad no sea negativa en setEdad.
  • En setDNI, sólo controlamos que el DNI tenga 9 caracteres y que el último sea una letra. En un caso real tendríamos que comprobar que la letra se corresponde con las cifras.
Persona.java
public class Persona {
private String nombre;
private int edad;
private String dni;

public Persona(String nombre, int edad, String dni) throws ExcepcionEdadNegativa, ExcepcionDniInvalido {
this.nombre = nombre;
this.setEdad(edad);
this.setDNI(dni);
}

public void setEdad(int edad) throws ExcepcionEdadNegativa {
if(edad >= 0)
this.edad = edad;
else
throw new ExcepcionEdadNegativa("La edad no puede ser negativa.");
}

public void setDNI(String dni) throws ExcepcionDniInvalido {
if(dni.length() != 9)
throw new ExcepcionDniInvalido("El DNI no tiene 9 dígitos.");
if(!Character.isLetter(dni.charAt(8)))
throw new ExcepcionDniInvalido("El último carácter tiene que ser una letra.");
else this.dni = dni;
}
}

El objeto p creado tiene una edad negativa y un DNI no válido. La exepción que se mostrará será ExcepcionEdadNegativa, ya que es la primera que aparece después del try, a pesar de ser el DNI incorrecto.

Main.java
public class Main {
public static void main(String[] args){
try {
Persona p = new Persona("Antonio",-2, "000000A");
} catch (ExcepcionEdadNegativa e) {
System.out.println(e.getMessage());
} catch (ExcepcionDniInvalido e){
System.out.println(e.getMessage());
}
}
}