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
- 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.
- Si quieres una excepción verificada (checked exception), haz que tu clase extienda
- 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.
- 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.
public class ExcepcionDniInvalido extends Exception{
public ExcepcionDniInvalido(String mensaje) {
super(mensaje);
}
}
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.
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.
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());
}
}
}