Esto es, a mi modo de ver, otro de los grandes aciertos del java este. La idea es la siguiente: Siempre hay errores, siempre se producen excepciones y nosotros, como programadores debemos preveerlo. En ese sentido devemos preveer que pasa si se produce un error. Por ejemplo, si vas a abrir un archivo y el archivo no está, o. Algo mas grave, si vas a dividir por 0.
Igualment no es tan simple como un vulgar simple if, else. Cuando se produce un error, una excepción como les gusta llamrlo la rutina salta al gestor de excepciones y es alli donde se maneja. Y… ¿que es el gestor de excepciones?… ¡Bravo! Un objeto. Por lo tanto lo podemos manipular a nuestro antojo, le podemos pasar parametros, incluso podemos definir tantas excepciones como queramos.
if(t==null){
throw new NullPointerException(" ¡ t es nulo ! ");
}
Fijate que hasta el lenguaje es apropiado. Tira una (new porque es un objeto) excepcion. Igualmente, el throw hace que pasen varias cosas. Entre otras, hace que el método devuelta la excepcion y no lo que se esperaba que devolviese.
Entonces como funciona todo esto… Mu facil. Tu, cuando programas le dices.. prueba de hacer esto, y si falla atrapa la excepción. si hay una excepcion de tipo a haz esto. O si es del tipo b haz esto.
try{
divide por 3,2,1,0
}catch(a excepcion){
atrapa la excecion del tipo a e informa al usuario
System.out.printf("burricalvo, has intentado dividir por cero")
}catch(b exception){
atrapa la excepcion del tipo b e y no hagas nada
}
De este modo conseguimos varias cosas. Primero estar prácticamente seguros de que nunca pasará nada que no hayamos previsto y que no sepamos controlar. Segundo conseguimos que el código potencialmente peligroso que de a salvo dentro del bloque try{ … } Y tercero ganamos mucho en elegancia y limpieza del código separando en un sitio el código normal y en otro distinto los controles de seguridad.
Y como aqui estamos para aprender …. vas a hacer tu própia excepción. Así se verá mucho mejor como fuciona todo esto. Para crear mi própia excepcion debo heredar de alguna excepción. Si no tengo ninguna afín pues dejo que el compliador escoja. Vamos allá.
// ExcepcionSencilla.java
// posibilidades que ofrecen las exepciones
class ESencilla extends Exception{}
public class ExcepcionSencilla{
public void f() throws ESencilla{
System.out.println("lanzando una expecion sencilla desde f()");
throw new ESencilla();
}
public static void main(String[] args){
ExcepcionSencilla sed = new ExcepcionSencilla();
try{
sed.f();
}catch(ESencilla e){
System.err.println("¡Excepcion capturada!");
}
}
}
Vamos a analizar lo que hemos hecho. Hemos hecho una ESencilla que no es otra cosa que que una clase que extiende la clase excepcion. Y que además es tonta poque no hace nada de nada. Por otro lado está la clase ExcepcionSencilla que tienen el método f() que lo que hace es imprimir lo de lanzando… y despues lanza (throw) la excepción. Hasta aqui estamos construyendo la expeción. Ahora la vamos a usar en el método main. Main, como que es muy precavido intenta llamar al metodo f desde un buque try. Y como que somos tan cafres que hemos hecho que se lance siempre la expepcion ues siemmpre la capturará catch(ESencilla e) y hará lo conveniente.
Y …. una excepción un poco mejor.
// ConstructoresCompletos.java
// Excepcion con constructores sobrecargados
class MiExcepcion extends Exception{
public MiExcepcion() {}
public MiExcepcion(String msg){ super(msg); }
}
public class ConstructoresCompletos{
public static void f() throws MiExcepcion{
System.out.println("Lanzando MiExcepcion desde f()");
throw new MiExcepcion();
}
public static void g() throws MiExcepcion{
System.out.println("Lanzando MiExcepcion desde g()");
throw new MiExcepcion("originada en g()");
}
public static void main(String[] args){
try{
f();
}catch(MiExcepcion e){
e.printStackTrace(System.err);
}
try{
g();
}catch(MiExcepcion e){
e.printStackTrace(System.err);
}
}
}
A parte de aceptar los métodos sobrecargados fijate que aqui la información de la excepción no la saca por pantalla sinó que la saca por System.err. Que es el sitio adecuado. Fijate de la diferencia de comportamiento cuando lo ejecutas. En ejemplo anterior lo saca por pantalla y nada mas. Aqui System.err acaba saliendo tambien por pantalla, pero redirigido desde System.err.
Si te has fijado hay que especificar que un método lanza expeciones. Esto es muy útil porque de ese modo quien vaya a usarlo sabrá siempre cuantas y cuales excepciones posibles hay. La sintaxis es, tras la palabra clave throws listar todas la posibles expeciones por lo que el nombre de un método podría quedar así void f() throws MiExpecion, ESencilla, OtraExpecion { contenido; }
La respuesta es si. Como que todas las expeciones heredan de la base Excepcion. catch(Excepcion e){System.err.println(“excepcion capturada”);} . Esto recoge cualquier tipo de excepcion. pero al ser la clase base no es demasiado especifica y si se usa en una secuencia de catch se debe usar la última porque seguro que la captura. Igualmente ofrece los siguientes métodos para aportar un poco de información:
Vamos a verlo en acción:
// MetodosDeExcepcion.java
public class MetodosDeExcepcion{
public static void main(String[] args){
try{
throw new Exception("aqui esta mi excepcion");
}catch(Exception e){
System.err.println("Expepcion capturada");
System.err.println("e.getMessage():" + e.getMessage());
System.err.println("e.getLocalizedMessage():" + e.getLocalizedMessage());
System.err.println("e.toString():" + e);
System.err.println("e.printStackTrace():");
e.printStackTrace(System.err);
}
}
}
fijate que cada método te da una información distinta….
Expepcion capturada
e.getMessage():aqui esta mi excepcion
e.getLocalizedMessage():aqui esta mi excepcion
e.toString():java.lang.Exception: aqui esta mi excepcion
e.printStackTrace():
java.lang.Exception: aqui esta mi excepcion
at MetodosDeExcepcion.main(MetodosDeExcepcion.java:5)