mvnForum Homepage Bienvenido domingo  |  Terminar sesión   
  Búsqueda  
  Indice |  Temas Recientes |  Quién Está en Línea |  Lista de Usuarios |  Mi Perfil |  Búsqueda |  Ayuda


Ir a »
Total de mensajes en este tema: 5 [Eliminar este Tema] [Mover este Tema]
[Ańadir a Mis Favoritos] [Ańadir un aviso a este tema] [Publicar nuevo tema]
Autor
Tema Anterior Este tema ha sido visto 81 veces y tiene 4 respuestas Tema Siguiente
Masculino rsm
Extranjero



Ingresó: Jul 1, 2004
Mensajes: 11
Estado: Desconectados

Adjuntar archivo   Editar este mensaje   Excepciones. Acerca de throw. Responder a este mensaje
Responder citando
[Eliminar este Tema]

Hola.

He estado leyendo la teoría de excepciones del módulo 2 y no me ha quedado claro el punto 2.1.3. Lanzamiento de excepciones. Entiendo que con el bloque catch se capturan las excepciones que se producen. ¿Pero que hace throw? ¿Lanza la excepción manualmente en lugar de lanzarse automáticamente? ¿Si es así la excepción busca un bloque manejador en el bloque en el que se encuentra? ¿Si el bloque que la maneja no existe en esa función busca en la de nivel superior? ¿Tiene que tener la función superior alguna declaración para capturar la excepcion? ¿Y si la excepción no se ha lanzado con throw sino automáticamente puede pasar al nivel superior?

Agradecería que alguien me ayudara a entender esto y si es posible que adjunte algún ejemplo donde se vea claro. Un saludo.
[Jul 12, 2004 5:00:00 PM] Print Post    rjsm1@alu.ua.es Reportar mensaje ofensivo  Ir al inicio 
Masculino nacho
Miembro



Ingresó: Feb 1, 2004
Mensajes: 63
Estado: Desconectados

Adjuntar archivo   Editar este mensaje   Re: Excepciones. Acerca de throw. Responder a este mensaje
Responder citando
[Eliminar este mensaje]

Hola.

Vamos a ver, intentaré resumirlo todo lo que pueda smile

Cuando en un método de una clase Java puede producirse un error, y ese error es de lo que en los apuntes llama "tipo checked" (es decir, algo así como "predecible"), se debe o bien capturar, o bien lanzar la excepción correspondiente, para que quien llame a ese método tenga en cuenta que se puede producir ese error.

Si aplicamos esto a los sucesivos niveles de llamadas, resulta que un throw que se produce en un método, puede volverse a producir en el que le llama, y en el que llama a este segundo... y así sucesivamente.

El tema está entonces en ver hasta dónde queremos que llegue el error. Si en uno de esos métodos intermedios hacemos un "catch" de la excepción, capturamos el error, y sacamos el mensaje correspondiente o hacemos lo que toque. En ese momento la propagación del error termina.

Si en ningún método capturamos el error, el "main" que hayamos ejecutado será su última parada, antes de salir por el monitor.

Un método útil para seguir todo esto es "printStackTrace" de la clase "Exception" (y por ende, de todas sus subclases). Con este método puedes ver una traza de por dónde ha ido propagándose una determinada excepción.

Como pone en los apuntes, hay dos tipos de excepciones básicamente: las checked y las no checked. Las primeras, cuando llamamos al método que las produce, tenemos OBLIGACION de capturarlas, o bien de pasarlas con otro "throw" al siguiente método en el árbol de llamadas. Eso durará como mucho hasta llegar al "main" que ejecutemos, donde obligatoriamente tendremos que capturarla para que el programa compile.

Las no checked no hace falta capturarlas, porque en teoría no se sabe cuándo pueden producirse. Estas no dan errores de compilación si no las capturamos ni las lanzamos, y si no tenemos cuidado pueden provocar excepciones en la ejecución principal.

Veamos un ejemplo de tratamiento de excepciones con checked y no checked.

----------------------------------------------------------
EJEMPLO con tipo checked:

Supongamos que tenemos un método que puede lanzar una excepcion de tipo MiExcepcion (que es de tipo checked):

public void metodo() throws MiExcepcion
{
if (... condicion ...)
throw new MiExcepcion ("Error en el metodo...");

... resto del codigo del método
}

Al ser de tipo checked, si queremos lanzarla en un método tenemos que poner la cláusula "throws" en su cabecera, y luego lanzarla con un throw dentro.

Supongamos que luego tenemos otro método "m2" que llama a este. El compilador nos dará ERROR si no capturamos la excepción:

public void m2()
{
try
{
metodo(); // Esta línea sin el try daría ERROR
} catch (MiExcepcion e) {
e.printStackTrace();
}
}

o bien declaramos que puede lanzarse a otro nivel:

public void m2() throws MiExcepcion
{
if (... condicion...)
throw new MiExcepcion ("Propagando el error...");
...
// Aqui no hace falta try
//porque declaras que puede lanzarse
metodo();
...
}

Si optamos por lo primero, ahí se acaba el error. Si elegimos lo segundo, la cadena continuará hasta que la capturemos en otro método después. Como muy tarde, deberemos capturarla en el método "main" que ejecutemos, que será el último método de todos. Ahí ya no podemos hacer más "throw".

En resumen, siempre que estemos tratando una excepción de tipo checked tenemos OBLIGACION de capturarla, o de declarar que se puede lanzar. Si no no podremos compilar el programa.

----------------------------------------------------------

EJEMPLO con tipo no checked:

Supongamos por otra parte que tenemos un método que recorre un array. Si no tenemos cuidado, puede ser que nos salgamos de los límites del array, y salte una excepción de tipo ArrayIndexOutOfBoundsException. Sin embargo, esta excepción no es checked, así que no tenemos obligación de capturarla.

Es decir, si el método lo dejamos así:

public void m3()
{
int[] elementos = new int[4];
for (int i = 0; i < 10; i++)
{
System.out.println("Elemento: " + elementos);
}
}

Como tenemos un array de 4 elementos, en cuanto el bucle pase de la 4ª posicion lanzará una excepción de tipo ArrayIndexOutOfBounds. No nos va a dar error de compilación como en las checked. Así que este tipo de excepciones es voluntario capturarlas. Podríamos dejar el método bien hecho con algo como:

public void m3()
{
int[] elementos = new int[4];
for (int i = 0; i < 10; i++)
{
try
{
System.out.println("Elemento: " + elementos);
} catch (ArrayIndexOutOfBoundsException e) {}
}
}

Pero como digo, no es necesario
----------------------------------------------------------

Bueno, después de todo este "rollazo", espero haber sido de ayuda. Si no, dímelo e intentaré explicártelo de otra forma, pero no te quedes con la duda porque las excepciones son básicas para todo lo que va a venir después.

Un saludo!

Nacho.
[Jul 12, 2004 5:57:14 PM] Print Post    iiborra@dccia.ua.es Reportar mensaje ofensivo  Ir al inicio 
Masculino rsm
Extranjero



Ingresó: Jul 1, 2004
Mensajes: 11
Estado: Desconectados

Adjuntar archivo   Editar este mensaje   Re: Excepciones. Acerca de throw. Responder a este mensaje
Responder citando
[Eliminar este mensaje]

Hola de nuevo.

Gracias por la explicación. Entonces, si no lo he entendido mal, lo que hace throw es pasar la excepción al métdo superior. ¿Me equivoco?

Pero aún no me he enterado bien y me quedan algunas dudas acerca de cómo debemos usar el throw cuando queremos que una excepción se propague. En el caso de try-catch, se especifica un bloque donde "permanecer alerta" y, si se produce una excepción pasar el control al bloque catch. En estos casos la excepción salta automáticamente cuando se viola una determinada condición. ¿Pero qué pasa con throw? ¿Tenemos que chequear nosotros si se cumple una condición y entonces lanzar la excepción? Creía que la excepción ArrayIndexOutOfBoundsException, por ejemplo, se producía automáticamente al acceder fuera de los límites de un array... ¿Qué hace el programa cuando llega a un throw? ¿Se detiene y pasa al nivel superior en busca de un catch? ¿Cómo se volvería a lanzar la excepción hacia el siguiente nivel desde allí? ¿...?

Por último, en el método divide del ejercicio 7 de la sesión 6, ¿por qué no se pone divide(int dividendo, int divisor) throws IllegalArgumentException?

Saludos.
[Jul 14, 2004 12:34:18 AM] Print Post    rjsm1@alu.ua.es Reportar mensaje ofensivo  Ir al inicio 
Masculino rsm
Extranjero



Ingresó: Jul 1, 2004
Mensajes: 11
Estado: Desconectados

Adjuntar archivo   Editar este mensaje   Re: Excepciones. Acerca de throw. Responder a este mensaje
Responder citando
[Eliminar este mensaje]

NOTA: A la última pregunta ya he encontrado la solución en los ejercicios.
[Jul 14, 2004 12:48:57 AM] Print Post    rjsm1@alu.ua.es Reportar mensaje ofensivo  Ir al inicio 
Masculino nacho
Miembro



Ingresó: Feb 1, 2004
Mensajes: 63
Estado: Desconectados

Adjuntar archivo   Editar este mensaje   Re: Excepciones. Acerca de throw. Responder a este mensaje
Responder citando
[Eliminar este mensaje]

Hola otra vez smile

El "throw" se puede usar con cualquier excepción (es decir, puedes lanzar cualquier excepción), la diferencia está en que las que no son tipo checked (como ArrayIndexOutOfBounds, o IllegalArgument) no lo necesitan para lanzarse, como tampoco necesitan el "throws". Simplemente cuando suceda un error del tipo de la excepción se lanzará la misma.

Eso sí, cuando uses "throw" tienes que comprobar tú a mano que se está produciendo un error. Es decir, si quieres lanzar un IllegalArgumentException tú, y no dejar que lo haga el programa, tienes que comprobar tú a mano que el argumento no es válido. De la misma forma, si quieres indicar que se está saliendo de los límites de un array, debes comprobar tú esos límites y lanzar el ArrayIndexOutOfBounds. Si no lo haces tú, lo hará el programa. La diferencia está en que si lo haces tú controlas un poco más cuándo y dónde se produce ese error.

Sobre lo de cómo propagar el throw de un nivel al siguiente, es sencillo. Si por ejemplo todo empieza aquí:

public void m1() throws UnaExcepcion
{
if (...condicion...)
throw new UnaExcepcion(...);
}

Y luego este método llama al anterior:

public void m2()
{
m1();
}

Tenemos dos opciones:

- Capturar la excepcion y acabar con la propagación del error. Para eso ponemos un bloque try...catch y listo:

public void m2()
{
try
{
m1();
} catch (UnaExcepcion e) {
...
}
}

- Propagar la excepción. Basta con definir en la cabecera del método, con un "throws", que este método puede lanzar excepciones de ese tipo. No hace falta que hagamos un "throw" dentro, porque eso ya lo hace el método que la lanzó originalmente:

public void m2() throws UnaExcepcion
{
m1();
}

De esta otra forma, un método m3 que llame al anterior podría optar por lo mismo:

public void m3()
{
try {
m2();
} catch (UnaExcepcion e) {}
}

o bien

public void m3() throws UnaExcepcion
{
m2();
}

... y así sucesivamente.


De todas formas, es IMPORTANTE que tengas en cuenta que todo esto se aplica OBLIGATORIAMENTE para excepciones de tipo checked (es decir, las que no sean subtipos de RuntimeException). Para las otras, es voluntario tratar todo esto, puesto que serán excepciones que se considera que no se pueden predecir.
[Jul 14, 2004 9:20:08 AM] Print Post    iiborra@dccia.ua.es Reportar mensaje ofensivo  Ir al inicio 
[Versión imprimible] [Publicar nuevo tema]