Professional Documents
Culture Documents
Excepciones. Categoras.
Las excepciones son el mecanismo por el cual pueden controlarse en un
programa Java las condiciones de error que se producen. Estas condiciones de
error pueden ser errores en la lgica del programa como un ndice de un array
fuera de su rango, una divisin por cero o errores disparados por los propios
objetos que denuncian algn tipo de estado no previsto, o condicin que no
pueden manejar.
La idea general es que cuando un objeto encuentra una condicin que no sabe
manejar crea y dispara una excepcin que deber ser capturada por el que le
llam o por alguien ms arriba en la pila de llamadas. Las excepciones son
objetos que contienen informacin del error que se ha producido y que heredan
de la clase Throwable o de la clase Exception. Si nadie captura la excepcin
interviene un manejador por defecto que normalmente imprime informacin que
ayuda a encontrar quin produjo la excepcin.
Existen dos categoras de excepciones:
Excepciones verificadas: El compilador obliga a verificarlas. Son todas las
que son lanzadas explicitamente por objetos de usuario.
Excepciones no verificadas: El compilador no obliga a su verificacin.
Son excepciones como divisiones por cero, excepciones de puntero nulo, o
ndices fuera de rango.
Generacin de excepciones
Supongamos que tenemos una clase Empresa que tiene un array de objetos
Empleado (clase vista en captulos anteriores). En esta clase podramos tener
mtodos para contratar un Empleado (aadir un nuevo objeto al array),
despedirlo (quilarlo del array) u obtener el nombre a partir del nmero de
empleado. La clase podra ser algo as como lo siguiente:
publicclassEmpresa{
Stringnombre;
Empleado[]listaEmpleados;
inttotalEmpleados=0;
...
Empresa(Stringn,intmaxEmp){
nombre=n;
listaEmpleados=newEmpleado[maxEmp];
}
...
voidnuevoEmpleado(Stringnombre,intsueldo){
if(totalEmpleados<listaEmpleados.length){
listaEmpleados[totalEmpleados++]
=newEmpleado(nombre,sueldo);
}
}
}
Observese en el mtodo nuevoEmpleado que se comprueba que hay sitio en el
array para almacenar la referencia al nuevo empleado. Si lo hay se crea el objeto.
Pero si no lo hay el mtodo no hace nada ms. No da ninguna indicacin de si la
operacin ha tenido xito o no. Se podra hacer una modificacin para que, por
ejemplo el mtodo devolviera un valor booleano true si la operacin se ha
completado con xito y false si ha habido algn problema.
Otra posibilidad es generar una excepcin verificada (Una excepcin no
verificada se producira si no se comprobara si el nuevo empleado va a caber o no
en el array). Vamos a ver como se hara esto.
Las excepciones son clases, que heredan de la clase genrica Exception. Es
necesario por tanto asignar un nombre a nuestra excepcin. Se suelen asignar
nombres que den alguna idea del tipo de error que controlan. En nuestro ejemplo
le vamos a llamar CapacidadEmpresaExcedida.
Para que un mtodo lance una excepcin:
Debe declarar el tipo de excepcin que lanza con la clusula throws, en su
declaracin.
Debe lanzar la excepcin, en el punto del cdigo adecuado con la
sentencia throw.
En nuestro ejemplo:
voidnuevoEmpleado(String
nombre,intsueldo)throwsCapacidadEmpresaExcedida {
if(totalEmpleados<listaEmpleados.length){
listaEmpleados[totalEmpleados++]
=newEmpleado(nombre,sueldo);
}
elsethrownewCapacidadEmpresaExcedida(nombre);
}
Adems, necesitamos escribir la
clase CapacidadEmpresaExcedida.Sera algo as:
publicclassCapacidadEmpresaExcedidaextendsExceptio
n{
CapacidadEmpresaExcedida(Stringnombre){
super("Noesposibleaadirelempleado"+
nombre);
}
...
}
La sentencia throw crea un objeto de la
clase CapacidadEmpresaExcedida. El constructor tiene un argumento (el
nombre del empleado). El constructor simplemente llama al constructor de la
superclase pasndole como argumento un texto explicativo del error ( y el
nombre del empleado que no se ha podido aadir).
La clase de la excepcin puede declarar otros mtodos o guardar datos de
depuracin que se consideren oportunos. El nico requisito es que extienda la
clase Exception. Consultar la documentacin del API para ver una descripcin
completa de la clase Exception.
De esta forma se pueden construir mtodos que generen excepciones.
Captura de excepciones
Con la primera versin del mtodo nuevoEmpleado (sin excepcin) se invocara
este mtodo de la siguiente forma:
Empresaem=newEmpresa("LaMundial");
em.nuevoEmpleado("AdnPrimero",500);
Si se utilizara este formato en el segundo caso (con excepcin) el compilador
producira un error indicando que no se ha capturado la excepcin verificada
lanzada por el mtodo nuevoEmpleado. Para capturar la excepcin es utiliza la
construccin try / catch, de la siguiente forma:
Empresaem=newEmpresa("LaMundial");
try{
em.nuevoEmpleado("AdnPrimero",500);
}catch(CapacidadEmpresaExcedidaexc){
System.out.println(exc.toString());
System.exit(1);
}
Se encierra el cdigo que puede lanzar la excepcin en un bloque try /
catch.
A continuacin del catch se indica que tipo de excepcin se va a capturar.
Despus del catch se escribe el cdigo que se ejecutar si se lanza la
excepcin.
Si no se lanza la excepcin el bloque catch no se ejecuta.
El formato general del bloque try / catch es:
try{
...
}catch(Clase_Excepcionnombre){...}
catch(Clase_Excepcionnombre){...}
...
Observese que se puede capturar ms de un tipo de excepcin declarando ms de
una sentencia catch. Tambin se puede capturar una excepcin genrica (clase
Exception) que engloba a todas las dems.
En ocasiones el cdigo que llama a un mtodo que dispara una excepcin
tampoco puede (o sabe) manejar esa excepcin. Si no sabe que hacer con ella
puede de nuevo lanzarla hacia arriba en la pila de llamada para que la gestione
Clusula finally
La clusula finally forma parte del bloque try/ catchy sirve para
especificar un bloque de cdigo que se ejecutar tanto si se lanza la excepcin
como si no. Puede servir para limpieza del estado interno de los objetos afectados
o para liberar recursos externos (descriptores de FICHERO , por ejemplo). La
sintaxis global del bloque try/ catch/ finallyes:
try{
...
}catch(Clase_Excepcionnombre){...}
catch(Clase_Excepcionnombre){...}
...
finally{...}
http://www.cc.uah.es/jlcastillo/POO/media/JavaCap4.pdf
http://www.mundojava.net/excepciones.html?Pg=java_inicial_4_6.html
http://codehero.co/manejo-de-excepciones-parte/
http://www.cursohibernate.es/doku.php?id=patrones:excepciones
Excepciones en Java
Empecemos recordando los dos tipos de excepciones que hay en Java 1)
Excepciones Checked: Objetos de la clase Exception o cualquier otra clase que hereda
de ella, excepto si heredan de RuntimeException.
Excepciones Unchecked: Objetos de la clase RuntimeException o de cualquiera otra
clase que herede de ella.
Excepciones Checked
Las excepciones Checked son aquellas que deben declararse en el mtodo mediante la
palabra throws y que obligan al que lo llama a hacer un tratamiento de dicha excepcin.
Son excepciones Checked cualquier objeto de la clase Exception o de cualquier otra clase que
herede de ella, excepto si el objeto es de la clase RuntimeException o cualquier otra clase que
herede de sta ltima.
1:
2:
3:
4:
5:
6:
7:
9:
return a / b;
8:
El mtodo dividir lanza en la lnea 4 una Checked Exception por lo tanto el mtodo lo declara
mediante throws.
Ahora cualquiera que llame al mtodo dividir est obligado a tratar la excepcin Exception de
dos formas:
Mediante un try-cath:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
En las lneas 4,6,7 y 8, se usa un try-catch para atrapar la excepcin que puede
producir la llamada el mtodo dividir.
Declarndo a su vez en el mtodo que puede lanzar dicha excepcin:
1:
2:
3:
4:
5:
6:
7:
En la lnea 2 vemos como se declaraque el mtodo main puede lanzar una excepcin
del tipo Exception ya que dividir lo lanza y no se atrapa con un try-catch.
Excepciones Unchecked
Las excepciones Unchecked son aquellas que no se declaran en el mtodo y que no obligan al
que lo llama a hacer un tratamiento de dicha excepcin.
Son excepciones Unchecked
clase RuntimeException.
todas
aquellas
excepciones
que
heredan
de
la
6:
7:
return a / b;
8:
9:
El mtodo dividir lanza en la lnea 4 una unchecked Exception por lo que no es necesario hacer
nada especial con ella.
1:
2:
3:
4:
5:
6:
7:
Checked Exceptions
Las excepciones Checked son condiciones excepcionales del flujo del programa pero que no son
debido a un error del propio programa. Es decir si se lanza una excepcin checked el programa no
tiene ningn tipo de error y sigue funcionando correctamente, simplemente se ha producido una
situacin excepcional que hemos marcado como una excepcin.
Por ejemplo si tenemos una funcin que borra ficheros y al ir a borrarlo , dicho FICHERO ya no
existe, deberemos lanzar una FileNotFoundException indicando que el fichero no existe. Que
el fichero ya no exista no es ningn error en el programa, puede haberse borrado justo un instante
antes , sin embargo, si que es una situacin excepcional porque la mayora de las veces cuando
vayamos a borrarlo deber estar el fichero si hemos acabado de seleccionarlo.
De ah que al ser usa situacin legitima del programa pero poco probable los creadores de Java
han decidido que es necesario declararla en el mtodo y que sea obligatorio tratarla. Las Checked
Exceptions no tienen nada de malo y son muy tiles para realizar correctamente los programas.
La Checked Exceptions forman parte del flujo lgico de nuestro programa y al programar debemos
tenerlas en cuenta y tratarlas adecuadamente no vindolas como un problema del que debemos
deshacernos.
Aunque hemos puesto el mismo ejemplo del mtodo dividir tanto para explicar las excepciones
Checked o Uncheked tras la explicacin debe quedar claro que la excepcin que debe lanzar el
mtodo dividir debe ser del tipo unchecked.
Unchecked Exceptions
Este tipo de error es mucho mas sencillo de entender. Una excepcin unchecked es aquella que se
lanza cuando hay un error en el programa.
Por ejemplo en el caso anterior de la divisin por cero, es un error de programacin que alguien
nos pase como dividendo un cero, en ese caso lanzaremos un RuntimeException.
Al ser las unchecked Exceptions errores en el programa , poco podemos hacer por arreglarlas. Por
ello no es obligatorio tratarlas con un try-catch. Lo nico que podemos hacer en la mayora de
casos es hacer que el programa acabe fallando y que se muestre un mensaje de error al usuario.
Es decir, si el programa funciona mal , es mejor que no siga funcionando antes que hacer que
contine funcionado pero usando datos errneos, ya que en ese caso los resultados que generara
tambin podran ser errneos.
Las unchecked exceptions no debemos tratarlas ya que no forma parte de la lgica de la aplicacin
y no debemos hacer nada con ella, simplemente debemos preocuparnos en el mensaje que
acabar llegando al usuario. En una aplicacin Web es tan sencillo como tener pginas de error
personalizadas.
El problema de las excepciones es que en muchas APIs de Java se lanzan checked cuando
deberan ser unchecked.
Por ejemplo, en el API de JDBC al ejecutar una consulta mediante executeQuery() se lanzar la
excepcin java.sql.SQLException que es de tipo Checked si la SQL es erronea. Acaso eso
no es un error de programacin y por lo tanto debera ser de tipo unchecked? Es decir que
tenemos un problema ya que deberemos tratar excepciones Checked pero no se pueden hacer
ningn tratamiento para solucionar lo que gener dicha excepcin.
El verdadero problema de Java es que muchas API lanzan Checked exceptions cuando deberan
haber sido uncheked exceptions.
Como acabamos de decir, eso nos lleva a los programadores a capturar dichas excepciones y
tener que tratarlas. Pero como tratamos dichas excepciones Checked si realmente son errores de
programa y por lo tanto excepciones unchecked? Pues solo hay una forma de hacerlo, es
transformando las excepciones Checked en unchecked.
1:
2:
3:
4:
5:
try {
double c=matematicas.dividir(-1.6, 0);
} catch (Exception ex) {
throw new RuntimeException("Fallo al llamar a 'dividir'",ex)
}
Vemos en la lnea 4 como lanzamos una nueva excepcin del tipo unchecked pero dentro contiene
la excepcin original que se ha producido ya que se le pasa como argumento. Con sto hemos
solucionado el problema. Pero vuelvo a repetir sta construccin solo debe hacerse con aquellas
excepciones checked que consideramos que deberan haber sido unchecked.
Esta construccin tan sencilla que consiste en que las excepciones checked ,pero que deberan
haber sido uncheked, trasformarlas en excepciones uncheked nos soluciona prcticamente todos
nuestros problemas.
1:
2:
3:
4:
5:
try {
double c=matematicas.dividir(-1.6, 0);
} catch (Exception ex) {
throw new RuntimeException("Fallo al llamar a 'dividir'",ex)
}
Mas problemas
Veamos ahora otro problema de las excepciones.Hay excepciones unchecked , que segn su
significado, deberan haber sido del tipo checked ya que no son debido a errores del programa (lo
contrario del caso anterior).
La excepcin ConstraintViolationException se lanza cuando alguna validacin de una
entidad no se ha cumplido. Se suele utilizar para indicar que el usuario ha introducido algn dato
erroneo en la aplicacin. Entonces, porqu es una excepcin unchecked? Segn lo que se est
explicando no hay duda de que debera ser del tipo Checked ya que no se lanza por un error de
programacin sino a causa de un dato mal introducido por el usuario.
El problema que se genera con sto es que la excepcin ConstraintViolationException no
sabemos que mtodo la va a lanzar a no ser que nos leamos la documentacin, pero es importante
capturarla para poder mostrar un mensaje al usuario. Si hubiera sido declarada como Checked, el
propio compilador nos avisara de cuando capturarla. Todo sto nos puede llevar a que el usuario
acabe viendo nuestra pgina de error de la aplicacin simplemente porque se ha dejado un campo
sin rellenar.
Otro problema de Java es que hay APIs que lanzan UnChecked Exceptions cuando deberan haber
sido Cheked Exceptions.
La solucin a este problema consiste simplemente en leerse la documentacin para ver cuando se
lanza una excepcin unchecked , que debera haber sido Checked, para capturarla y hacer el
correcto tratamiento con ella.
Mas informacin sobre la excepcin ConstraintViolationException y como solucionar el
problema lo tenemos en Excepciones
ni
el
mtodo Throwable
getCause() que
obtiene
la
excepcin
encapsulada.
Throwable en Java 1.4: Ya dispone de un constructor al que pasarle otra excepcin y el
mtodo Throwable getCause().
Esto ltimo nos ha llevado a soluciones errneas como la siguiente:
1:
2:
3:
try {
double c=matematicas.dividir(-1.6, 0);
} catch (Exception ex) {
ejemplo
la
de
los
try {
double c=matematicas.dividir(-1.6, 0);
} catch (Exception ex) {
throw new MiExcepcion ("Fall al llamar a 'dividir'.");
}
En la lnea 4 se lanza la nueva excepcin MiExcepcion que no hace nada que no hiciera
ya RuntimeException e incluso seguimos perdiendo la excepcin original.
6:
7:
En la lnea 2 vemos ahora como el mtodo Main ahora tambin lanza una excepcin checked.
Ignorarla
Este es el peor error que podemos cometer al tratar una excepcin.Consiste simplemente en
ignorar la excepcin y que contine la ejecucin del programa. Esto es tan peligroso ya que si se
ha producido algn fallo en el programa lo ms seguro es hacer que se detenga cuanto antes y no
seguir haciendo operaciones con datos que quizs sean errneos.
1:
2:
3:
4:
5:
try {
double c=matematicas.dividir(-1.6, 0);
} catch (Exception ex) {
}
Vemos en la lnea 4 como no se realiza ninguna accin al capturar la excepcin, por lo tanto la
ejecucin seguir como si no hubiera pasado nada.
Log
Acabamos de ver en el apartado anterior que nunca
4)
ignorarla pero que aparenta ser mejor solucin es guardar en el log la excepcin que se ha
producido pero sin hacer nada mas.
try {
double c=matematicas.dividir(-1.6, 0);
3: } catch (RuntimeException ex) {
4:
Logger.getLogger(Main.class.getName()).log(Level.SEVERE,
ex);
5: }
1:
2:
null,
5)
Consola
Otra forma erronea de guardar las excepciones consiste en mostrar la traza del error por la
consola.
1:
2:
3:
4:
5:
try {
double c=matematicas.dividir(-1.6, 0);
} catch (RuntimeException ex) {
ex.printStackTrace();
}
Imprimirla
Por ltimo pero no por ello menos usada est la tcnica de imprimir el mensaje de la excepcin.
1:
2:
3:
4:
5:
try {
double c=matematicas.dividir(-1.6, 0);
} catch (RuntimeException ex) {
System.out.println("Fall al dividir");
}
Esta forma tiene los mismos problemas del anterior de imprimirla por consola pero sta es aun
peor, hemos perdido toda la informacin de la excepcin.
try {
double c=matematicas.dividir(-1.6, 0);
} catch (Exception ex) {
throw new RuntimeException("Fallo al llamar a 'dividir'",ex)
}
Este cdigo tiene unas pegas al respecto de las trazas que se generara por pantalla
6)
cuando se
2:
3:
4:
5:
at
Caused
at
at
ejemplo.Main.main(Main.java:17)
by: java.lang.Exception: El argumento b no puede ser 0
ejemplo.Matematicas.dividir(Matematicas.java:14)
ejemplo.Main.main(Main.java:15)
Como podemos ver en la traza, se muestran dos excepciones, la excepcin original en la lnea 3 y
la RuntimeExcepcion que encapsula a la excepcin original en la lnea 1. Esto es inevitable as
que por ahora lo vamos a asumir.
El
problema
viene
si
el
lanzar
tanto
una RuntimeException.
Veamos el cdigo modificado de dividir para que en caso de que algn nmero sea negativo se
produzca una RuntimeException:
public class Matematicas {
public double dividir(double a, double b) throws Exception {
3:
if (a<0) {
4:
throw new RuntimeException("El argumento a no puede ser
negativo");
5:
}
6:
if (b<0) {
7:
throw new RuntimeException("El argumento b no puede ser
negativo");
8:
}
1:
2:
9:
10:
if (b == 0) {
throw new Exception("El argumento b no puede ser 0");
}
11:
12:
13:
14:
15:
16:
return a / b;
Ahora
la
traza
si
que
ha
quedado
un
poco
mal.Hemos
encapsulado
una RuntimeException (lnea 3) dentro de otra RuntimeException (lnea 1) lo que tiene muy
poco sentido. Es decir que la traza ha quedado poco clara cuando no hay necesidad para ello. Esto
ocurre ya que RuntimeException hereda de Exception por lo que el catch tambin atrapa
la RuntimeException y la encapsula en otra RuntimeException.
La solucin a sto, es bastante sencilla.Si nos llega una RuntimeException simplemente la
volvemos a lanzar en vez de encapsularla.
public class Main {
public static void main(String[] args) {
3:
Matematicas matematicas=new Matematicas();
4:
try {
5:
double c=matematicas.dividir(-1.6, 0);
6:
} catch (RuntimeException ex) {
7:
throw ex;
8:
} catch (Exception ex) {
9:
throw new RuntimeException("Fallo
'dividir'",ex);
10:
}
11:
}
12: }
1:
2:
al
llamar
Es decir que ahora la traza para una RuntimeException es como debera ser ,ya que no queda
encapsulada por ninguna otra excepcin.
Por los ejemplos puede parecer un poco exagerado querer que no se encapsulen las excepciones
pero pongo aqu un ejemplo de excepciones en Hibernate:
Exception in thread "main" org.hibernate.MappingException: Could not get
constructor for org.hibernate.persister.entity.SingleTableEntityPersister
at
org.hibernate.persister.internal.PersisterFactoryImpl.create(PersisterFac
toryImpl.java:185)
at
org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersist
er(PersisterFactoryImpl.java:135)
at
org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:
367)
at
org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:17
40)
at
curshibernatet03e01.CursHibernateT03E01.main(CursHibernateT03E01.java:23)
Caused by: org.hibernate.HibernateException: Unable to instantiate
default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]
at
org.hibernate.tuple.entity.EntityTuplizerFactory.constructTuplizer(Entity
TuplizerFactory.java:138)
at
org.hibernate.tuple.entity.EntityTuplizerFactory.constructDefaultTuplizer
(EntityTuplizerFactory.java:188)
at
org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:34
1)
at
org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEnt
ityPersister.java:502)
at
org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTa
bleEntityPersister.java:144)
Method)
at
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAc
cessorImpl.java:57)
at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConst
ructorAccessorImpl.java:45)
at
java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at
org.hibernate.persister.internal.PersisterFactoryImpl.create(PersisterFac
toryImpl.java:163)
... 4 more
Caused by: java.lang.reflect.InvocationTargetException
at
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method)
at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAc
cessorImpl.java:57)
at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConst
ructorAccessorImpl.java:45)
at
java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at
org.hibernate.tuple.entity.EntityTuplizerFactory.constructTuplizer(Entity
TuplizerFactory.java:135)
... 13 more
Caused by: org.hibernate.PropertyNotFoundException: Could
getter for domicilio in class curshibernatet03e01.Cliente
not
find
at
org.hibernate.property.BasicPropertyAccessor.createGetter(BasicPropertyAc
cessor.java:316)
at
org.hibernate.property.BasicPropertyAccessor.getGetter(BasicPropertyAcces
sor.java:310)
at org.hibernate.mapping.Property.getGetter(Property.java:320)
at
org.hibernate.tuple.entity.PojoEntityTuplizer.buildPropertyGetter(PojoEnt
ityTuplizer.java:436)
at
org.hibernate.tuple.entity.AbstractEntityTuplizer.<init>(AbstractEntityTu
plizer.java:200)
at
org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.j
ava:82)
... 18 more
Realmente la informacin mas til la encontramos justamente en la primera excepcin que se
produce. Sin embargo est justamente al final de toda la traza:
PropertyNotFoundException: Could not find a getter for domicilio in class
curshibernatet03e01.Cliente
As que si no se hubiera encapsulado la excepcin se vera en la primera lnea en vez de ir a
buscarla al final de la traza.
La solucin definitiva
La solucin definitiva es que las excepciones checked tenga tambin una traza limpia como las
unchecked. Antes hemos comentado que es imposible pero hay un truco en Java que permite
hacerlo, no voy a explicar como funciona el truco simplemente voy a explicar como hacerlo.
Se debe crear la siguiente clase:
1:
2:
3:
public
class RelanzadorExcepciones {
RelanzadorExcepciones.<RuntimeException>lanzarComoUnchecked(ex);
5:
6:
throw new AssertionError("Esta lnea
Java no lo sabe");
7:
}
8:
9:
private
static
<T
extends
lanzarComoUnchecked(Exception toThrow) throws T{
10:
throw (T) toThrow;
11:
}
12: }
Exception>
void
Vemos como ahora para relanzar la excepcin en la lnea 22 usamos el nuevo mtodo que hemos
creado RelanzadorExcepciones.lanzar.
Si ejecutamos ahora la aplicacin y vemos la traza, queda de la siguiente forma:
Exception in thread "main" java.lang.Exception: El argumento b no puede
ser 0
at ejemplo.Matematicas.dividir(Matematicas.java:21)
at ejemplo.Main.main(Main.java:15)
Es decir que nicamente se ve la excepcin checked sin que quede encapsulada por nadie.!!
Por fin con este ultimo truco hemos conseguido simplificar la traza con todas las excepciones.
Referencias
Java theory and practice: The exceptions debate
Effective Java (2nd Edition)
Thinking in Java, 4th edition
Expert One-on-One J2EE Design and Development
The Java Tutorials.Unchecked ExceptionsThe Controversy
Throwing Checked Exceptions Like Unchecked Exceptions in Java
13 Exceptional Exception Handling Techniques