G.Bordel >Docencia >TAP | Técnicas Actuales de Programación | (curso 2010-2011) | |||||||
|
|||||||||
tema_anterior | Tema 5: Mecanismo de tratamiento de Excepciones y Errores | tema_siguiente |
|
5.2- Control de excepciones
Palabras reservadas en Java | |||||
abstract | boolean | break | byte | case | catch |
char | class | const* | continue | default | do |
double | else | extends | final | finally | float |
for | goto* | if | implements | import | instanceof |
int | interface | long | native | new | package |
private | protected | public | return | short | static |
strictfp** | super | switch | synchronized | this | throw |
throws | transient | try | void | volatile | while |
La separación de losbloques de código para una ejecución normal y para sus posibles situaciones excepcionales se lleva a cabo mediante una sentencia que se dejo sin ver en su momento para hecerlo ahora. se trata de la sentencia:
try sentencia [catch (clase_arrojable id) sentencia]+
finally sentencia
try
(normalmente un bloque {...}), se corresponderá
con el algoritmo a ejecutar en caso de que no surjan excepciones, y cada posible situación excepcional
será atendida por una sentencia (normalmente un bloque) asociada a un catch
(la "captura"
de un objeto arrojado en el momento de la excepción). Como puede verse, puede haber uno o más fragmentos
"catch" conforme sea necesario por el número de situaciones excepcionales posibles en el código "normal".
Estos fragmentos tienen, como si de rutinas se tratase, un parámetro al que se le da un identificador (id)
que será de una determinada clase "arrojable". Cuando se produzca una situación en que se arroje un objeto de
una determinada clase, será recogido por el fragmento catch que tenga el parámetro correspondiente.
Por último se tiene un fragmento finally
que será ejecutado siempre una vez que se haya
terminado la ejecución del try y los catch. Su función es la de terminar con todas aquellos requerimientos
que han de darse aún cuando se hayan seguido diferentes caminos (distintas excepciones o la ejecución
normal), como por ejemplo el cierre de ficheros, sockets, etc.
El siguiente ejemplo muestra esto y nos permite matizar alguna cuestión al respecto:
|
|
Aunque no se haya estudiado por ahora, puede entenderse facilmente que la clase
FileInputStream
es capaz de abrir un fichero para realizar lecturas de datos. En la
linea 1 se declara una variable referencia para un objeto de tal clase y en la 2 una variable
entera que podrá alojar un dato leido de un fichero. A continuación, en las lineas 3 a 7 se encuentra
un bloque de código tras el término try
que será el de la ejecución que queremos
realizar con nuestro fichero; por ejemplo abrir uno que tiene nombre "pepe", leer un entero sobre la variable
d, etc. De este modo puede escribirse el algoritmo a llevar a cabo sin "mezclarlo" con el control de
situaciones excepcionales. Este control se hace a continuación: si consultamos la documentación de la
clase FileInputStream
, veremos que en el momento de instanciar un objeto puede producirse un
error de clase FileNotFoundException
que obedece a la situación evidenciada por su nombre, de
modo que el bloque de las lineas 7 y 8, recibe un objeto de esta clase en caso de producirse y puede
actuar en consecuencia (nótese que el código de este catch puede hacer uso del objeto recibido o no). Del
mismo modo descubriremos en la documentaciñon del método read()
que en el pueden producirse
indeterminados errores de entrada/salida identificados con un objeto de clase IOException
(p.ej. faltas de permisos de acceso, ausencia de datos sin fin de fichero, etc). Las acciones a ejecutar en
tal caso se llevarian a cabo en el bloque 9-10. Si escribimos el total del bloque try
es posible que aparezcan más situaciones de error que podran ser ser atendidas en otros bloques
catch
(si se repite más de una vez la misma clase de excepción, será atendida por el mismo
bloque catch
, y podrá llegarse a distinguir situaciones analizando el objeto recibido).
Por último, el fragmento finally
de
las líneas 11-14 se ocupará de terminar con todo aquello que pueda haber quedado en situación inconclusa,
como por ejemplo de cerrar el fichero en caso de que se hubiese llegado a abrir.
Hay que mencionar dos detalles importantes...
En primer lugar que, dado que los objetos arrojables pertenecen
a una jerarquía, hay que ser cuidadoso al situar los catch, ya que el objeto será recogido por el primer
catch que se ajuste a su clase teniendo en cuenta la capacidad de polimorfismo. Por ejemplo, dado que
En segundo lugar hay que reforzar la idea de que el bloque
Aquí un método consiste en una sentencia
El único modo de que no se ejecute el bloque FileNotFoundException
es una clase descenciente de la clase catch
en orden inverso el asociado a FileNotFoundException
quedaría anulado al ser atendidas las
excepciones de esta clase por el catch
de IOException
(este problema es
detectado por el compilador)
finally
se realiza siempre,
y esto es así hasta el punto de que incluso aún cuando se encuentre un return
en algún
punto de los bloques try
o catch
, se ejecutará el finally antes de
llevarlo a cabo. Veamoslo con unejemplo amliado del anterior:
1-
2-
3-
4-
5-
6-
7-
8-
9-
10-
11-
12-
13-
14-
15-
16-
17-
18-
19-
public void procesaPepe() {
FileInputStream f=null;
int d;
try {
f=new FileInputStream("pepe");
d=f.read();
// aqui el resto de acciones que se quieran realizar con f
} catch (FileNotFoundException e) {
// aquí el código a ejecutar en caso de que no existiera el fichero "pepe"
return;
} catch (IOException e) {
// aquí el código a ejecutar en caso de que no se haya podido obtener f por otro motivo
return;
} finally {
if (f!=null) f.close();
// aquí otro código que deba ejecutarse en todo caso
}
// más código del método
}
try-actch-finally
y más código a
continuación. En una ejecución normal se llevarán a cabo las acciones del bloque try
,
a continuación las del bloque finally
y despues el resto del código del método. En una
ejecucióncon una excepcion, el bloque try
se abortará, se ejecutará el catch
correspondiente que acaba con un return
pero antes de terminar (de ejecutar el "retorno")
se ejecutará el bloque finally
.
finally
es que se produzca la terminación
de la aplicación (mediante System.exit(int)
).
//Se supone que el cliente no tiene código de promoción
int codigoPromocion=0;
//Se comprueba si llega código como parámetro
try {
codigoPromocion=Integer.parseInt(request.getParameter("codP"));
};
//Si no hay código o no es numérico se continua normalmente
catch (NumberFormatException ex) {}
catch (NullPointerException ex) {}
Siguiente punto: 5.3- Generación excepciones
Plataforma de soporte a curso y contenidos (c) German Bordel 2005. |