Вы находитесь на странице: 1из 21

Java World Captulo 5

If y Switch
Las sentencias if y switch generalmente se refieren a sentencias de decisin. Utilizamos las sentencias de decisin cuando
deseamos que nuestro programa ejecute un comportamiento u otro, dependiendo del estado de una o ms variables.

If-else
if (expresionBooleana) {
//Cdigo1 ...
} else if (expresionBooleana) {
//Cdigo2 ...
} else {
//Cdigo3 ...
}
Lo que hace el cdigo es lo siguiente:
1.
2.
3.

Evala la primer expresin booleana


Si el resultado es true
2.1. Se ejecuta Cdigo1
Si el resultado es false
3.1. Se verifica la segunda expresin booleana
3.2. Si el resultado es true
3.2.1. Se ejecuta Cdigo2
3.3. Si el resultado es false
3.4. Se ejecuta el else (condicin por defecto si no se cumplen los ifs)
3.4.1. Se ejecuta Cdigo3

Ahora, vamos a aclarar cmo puede llegar a ser la sintaxis:


Solo debe existir un if
Puede haber uno o ms else if, siempre que exista un if previo
Puede haber solo un else, siempre que esxista un if previo
No es necesario encerrar el contenido de las sentencias entre llaves (esto solo permite escribir cdigo de una lnea). No es
una prctica recomendada
Solo se pueden evaluar expresiones booleanas (esto no es C, un boolean true no es un int mayor que 0).
Los else if y else deben de estar encadenados al if (empiezan a medida que el otro finaliza). Si esta cadena se rompe
generar un error de compilacin.
Los else if y else son encadenados al if ms prximo.
Se ejecuta solo la primer condicin que califique (en caso de que no califique ninguna, se ejecuta si existe el else).
Hay que recordar que una sentencia de condicin, en Java, solo evala los tipos boolean. Es vlido asignar
un valor a una variable dentro de una condicin, pero si el tipo de da to almacenado no es de tipo boolean,
se generar un error de compilacin. De manera que una sentencia como if ( x = 9 ) generar un error de
compilacin.
Ejemplos de algunos tipos de expresiones vlidas, y no vlidas:
Expresin 1
static public void main(String[] args) {
boolean expresion = false
if (expresion)
System.out.println("Soy el valor 1");
System.out.println("Soy el valor 2");
System.out.println("Soy el valor 3");
}

h
t
t
p
:
/
/
g
u
s
t
a
v
o
a
l
b
e
r
o
l
a
.
b
l
o
g
s
p
o
t
.
c
o
m

h
t
t
p
:
/
/
v
a
l
o
r
c
r
e
a
t
i
v
o
.
b
l
o
g
s
p
o
t
.
c
o
m

Java World Captulo 5

Soy el valor 2
Soy el valor 3

Expresin 2
static public void main(String[] args) {
boolean expresion = false
if (expresion)
System.out.println("Soy el valor 1");
else
System.out.println("Soy el valor 2");
System.out.println("Soy el valor 3");
}

Soy el valor 2
Soy el valor 3
Expresin 3
static public void ejecutarIf(int valor) {
if (valor == 1) {
System.out.println("Soy el valor 1");
} else if ( valor > 0 ) {
System.out.println("Soy el valor 2");
} else {
System.out.println("Soy el valor 3");
}
}
static public void main (String[] args) {
ejecutarIf(1);
ejecutarIf(0);
ejecutarIf(87);
}
Soy el valor 1
Soy el valor 3
Soy el valor 2
Expresin 4
static public void main (String[] args) {
boolean expresion = false;
if (expresion)
System.out.println("Soy el valor 1");
System.out.println("Soy el valor 2");
else
System.out.println("Soy el valor 3");
}
Error de compilacin!
Como se puede apreciar en la expresin 1 solo tenemos el if. En la expresin 2, le sumamos un else. En ambas expresiones, no
utilizamos las {} para encerrar el cdigo, pero aun as es vlido, dado que ninguno de ellos ocupa ms de una lnea.

Java World Captulo 5

Que se escriba en un rengln no quiere decir que sea cdigo de una sola lnea. El ; delimita el fin de lnea
por ejemplo, de manera que un cdigo como int a;a++; son dos lneas.

En la expresin 3 agregamos un else if a la condicin, y las {}. Como vers, al llamar a la expresin con el 1, podra calificar para
la primera sentencia, o para la segunda, pero como la primera es quien la captura primero, se ejecuta esta.
En la expresin 4 nos encontramos con un error de ejecucin. Este se produce por el precepto de que los else else if, deben
de estar encadenados unos a otros comenzando por el if. Como vern, al no tener {}, dentro del if solo entra el print para Soy
el valor 1. Luego se ejecuta el print Soy el valor 2, y el else a continuacin. Dado que la sentencia anterior no fue un if, o
else if, se genera un error de compilacin.
Veamos un ejemplo un poco ms complicado:
public class ifTest {
static public void main(String[]
if (expresion)
if (expresion2)
System.out.println("Me ejecuto
else
System.out.println("Me ejecuto
else
System.out.println("Me ejecuto
}
}

args) {
1");
2");
3");

En realidad, no es ms difcil que lo anterior, solamente tiene un if anidado, una indentacin que no sirve para nada, pero el
examen es generado dinmicamente, por lo cual, los creadores admiten que podemos llegar a enco ntrarnos con cdigo como este.
Ahora pensemos, que valor veramos si, expresion es true y expresion2 es false?
Me ejecuto 2

Y si expresion es false y expresion2 es true?


Me ejecuto 3

Y si expresion es false y expresion2 es false?


Me ejecuto 3

Para que vean ms claramente, el cdigo indentado y con llaves sera el siguiente:
public class ifTest {
static public void main(String[]
if (expresion) {
if (expresion2) {
System.out.println("Me ejecuto
} else {
System.out.println("Me ejecuto
}
} else {
System.out.println("Me ejecuto
}
}
}

args) {
1");
2");

3");

Si quieren hacer la prueba se darn cuenta de que el cdigo resultante es el mismo.

Switch

Una manera de simular el uso de mltiples else if es la sentencia switch.


Bsicamente, cuando tengan que verificar una variable por algunos valores en concreto, lo mejor es utilizar switch. Cuando el
conjunto de valores a verificar es muy grande (ejemplo, cualquier valor menor que 100), se utiliza if.
Estructura de la sentencia switch:

h
t
t
p
:
/
/
g
u
s
t
a
v
o
a
l
b
e
r
o
l
a
.
b
l
o
g
s
p
o
t
.
c
o
m

h
t
t
p
:
/
/
v
a
l
o
r
c
r
e
a
t
i
v
o
.
b
l
o
g
s
p
o
t
.
c
o
m

Java World Captulo 5


static public class switchtest {
static public void main(String[] args) {
int x = 45;
switch (x) {
case 1:
System.out.println("valor: 1");
break;
case 2:
System.out.println("valor: 2");
break;
case 3:
case 4:
System.out.println("valor: 3 o 4");
break;
case 5:
System.out.println("valor: 5");
break;
default:
System.out.println("Ningn valor fue tenido en cuenta");
}
}
}
Iremos explicando el cdigo anterior por pasos.
Primero, tengamos en cuenta las condiciones que debe cumplir una sentencia switch para ser vlida:
Cada valor especificado en el case debe de ser un literal o una constante final cargada en tiempo de compilacin (cuando se
declara se inicializa. final int a = 1;)
Solo se puede comparar contra un valor, no contra un rango (>, <, >=, <= no estn permitidos).
La sentencia break es opcional, pero si no se especifica, se seguirn ejecutando las lneas inferiores hasta toparse con otro
break o terminar la sentencia switch.
Los valores tanto para el case, como para la entrada del switch, solo pueden ser aquellos que se puedan tipificar como
int (no importa que el casteo sea implcito). Tampoco califica un String. Puede llegar calificar un enum.
No pueden haber dos case que comparen el mismo valor.
Si se utilizan tipos de dato que no sean int, tener mucho cuidado, ya que si alguno de los valores de un case produce un
overflow, se genera un error de compilacin.
Se pueden combinar varios case sucesivamente (ver ejemplo case 3: case 4:) puede calificar con cualquiera de los
valores, y solo es necesario que califique para 1.
La sentencia default se ejecuta si no calific ningn case. Esta no necesita estar al final.
Por ms que se ejecute default, si no se especifica un break, y hay ms sentencias debajo de esta, se ejecutarn como con
un case nor mal.

Java World Captulo 5

Bucles e iteraciones
En java existen tres sentencias para bucles: while, do y for (este ltimo tiene dos alternativas).

While
La sentencia while es adecuada cuando no tenemos idea de cuantas veces se ejecutar un bloque de cdigo, pero si queremos que
en algn momento, este finalice.
La sintaxis del while:
while (condicion) {
//Bloque de cdigo ...
}
Siempre que la condicin sea verdadera se ejecutar el bloque de cdigo.
Puede que el bloque de cdigo no se ejecute nunca, si la condicin inicialmente es false.
La condicin tiene que ser una expresin booleana.
Cualquier variable utilizada dentro del while debe de ser declarada previamente (es ilegal declarar una variable dentro de
la condicin).

Do
La sentencia do es semejante al while, son la diferencia de que primero ejecuta el bloque de cdigo, y luego evala la condicin (al
revs del while).
La sintaxis del do:
do {
//Bloque de cdigo ...
} while (condicin);
A diferencia del while:
La condicin se ejecutara al menos una vez.
El while se finaliza con ;.

For
El for es un poco ms complejo, pero simplemente porque contiene ms elementos en su invocacin que la condicin . Estos se
pueden r esumir de la siguiente manera:
for ( inicializacion ; condicion ; incremento variables contador ) {
//Bloque de cdigo ...
}
Vamos a describir que hace, y que se puede hacer en cada seccin:
Inicializacin
En esta parte se pueden asignar valores a variables ya declaradas, as como declarar una variabl e (esta solo ser
visible para la sentencia for) e inicializarla.
Condicin
Al igual que en las sentencias de bucle anteriores, la condicin indica si se vuelve a ejecutar el bloque de cdigo o
no.
Incremento variables contador
Aqu se incrementan las vari ables que son utilizadas para verificar la condicin (en realidad, se pueden incrementar
o decrementar con cualquier operacin matemtica). A su vez, esta seccin permite realizar cualquier accin, hasta puedes
realizar un print dentro de la misma.
Veamos una sentencia real:

h
t
t
p
:
/
/
g
u
s
t
a
v
o
a
l
b
e
r
o
l
a
.
b
l
o
g
s
p
o
t
.
c
o
m

h
t
t
p
:
/
/
v
a
l
o
r
c
r
e
a
t
i
v
o
.
b
l
o
g
s
p
o
t
.
c
o
m

Java World Captulo 5


int y = 0;
int x = 0;
for ( x = 0, y = 3 ; x == 0 && y < 10 ; y++, x-- ) {
//Bloque de cdigo ...
}
Algunas cuestiones sobre la sentencia for:
A diferencia de los bucles anteriores, el for es utilizado cuando conocemos la cantidad de veces que queremos que se
ejecute un bloque de cdigo.
En la inicializacin podemos especificar varias variables, separadas cada una por una coma, pero solo una accin
o Podemos cambiar el valor de variables ya declaradas previamente al for
o Podemos declarar e inicializar variables solo para el for, que no se encuentren definidas previamente en el mismo
scope.
Solo podemos evaluar una condicin (esto no quiere decir que no podamos combinar sentencias con los operadores &&, &,
|| y |).
Podemos realizar cualquier operacin matemtica sobre las variables en el incremento de variables contador.
La seccin de incremento variables contador se ejecuta cada vez que se completa el bloque de cdigo.
Para separar elementos en la misma seccin se utiliza la ,.
En un bucle for, no es nec esario especificar ninguna de las tres secciones. Se las puede dejar en blanco. Un
ejemplo vlido sera for( ; ; ){}.
En la seccin incremento variables contador, en realidad podemos realizar cualquier operacin,
indistintamente de que la misma sea incremento, o una salida por pantalla.

For-each
Es una nueva funcionalidad que se encuentra disponible a partir de java 6, la cual permite realizar una iteracin de un array o
coleccin.
En vez del tradicional for el cual contiene tres secciones, el for-each contiene dos secciones.
Veamos un ejemplo con los dos tipos de sintaxis:
//Sintaxis for
int[] arr = {1, 2, 3, 4, 5};
for (int x = 0 ; x < arr.length ; x++ ){
System.out.println(a[x]);
}
//Sintaxis for-each
int[] arr = {1, 2, 3, 4, 5};
for (int x : arr) {
System.out.println(x);
}
La nueva sintaxis est formada por:
for ( declaracin : expresin ) {
//Bloque de cdigo ...
}
Vamos a describir que hace, y que se puede hacer en cada seccin:
Declaracin
o Permite declarar una variable, la cual se ir completando con cada elemento del array/coleccin.
o La variable declarada debe ser del mismo tipo que cada elemento dentro del array, o un tipo compatible (casteo
implcito, o dentro del mismo rbol de herencia siempre que sea downcasting, no se permite upcasting).

Java World Captulo 5


o La variable no debe de existir en el mismo nivel de visin (scope).
Expresin
o Especifica el array o coleccin sobre el cual se realiza la iteracin.
o Se puede especificar la llamada a un mtodo, siempre que este devuelva un array o coleccin.
o El tipo del array puede ser cualquiera: primitivas, objetos, incluso array de arrays.
Algunos ejemplos de for-eachs vlidos:
class Vehiculo {
public String toString(){
return "Soy un vehiculo";
}
}
class Auto extends Vehiculo {
public String toString() {
return "Soy un auto";
}
}
class Moto extends Vehiculo {
public String toString() {
return "Soy una moto";
}
}
public class forEachTest {
static public void main(String[] args) {
int[] intArray = {1, 2, 3};
int[][] intIntArray = {{1, 2}, {3, 4}, {5, 6}};
Vehiculo[] vehiculoArray = {new Auto(), new Moto()};
System.out.println("intArray:");
for (int x : intArray) {
System.out.println(x);
}
System.out.println("\nintIntArray:");
for (int[] x : intIntArray) {
System.out.println(x);
}
System.out.println("\nvehiculoArray:");
for (Vehiculo x : vehiculoArray) {
System.out.println(x);
}
}
}

h
t
t
p
:
/
/
g
u
s
t
a
v
o
a
l
b
e
r
o
l
a
.
b
l
o
g
s
p
o
t
.
c
o
m

h
t
t
p
:
/
/
v
a
l
o
r
c
r
e
a
t
i
v
o
.
b
l
o
g
s
p
o
t
.
c
o
m

Java World Captulo 5

Break y continue
Estos operadores pueden ser utilizados para salir del bucle, o para saltar a la siguiente iteracin.

continue debe de declararse dentro de un bucle, dentro de una sentencia switch generar un error de
compilacin. Break puede ser utilizado dentro de un bucle o sentencia switch.

Pero que significa esto, bueno, vamos a ver en profundidad cada una de las sentencias dentro de un bucle if.
Ejemplo con continue:
if ( int x = 0 ; x < 10 ; x++ ) {
if ( x == 3 )
continue;
System.out.print(x);
}
System.out.println("\nSe termin el if");

12456789
Se termin el if

Podemos ver como continue hace que se pase a la siguiente iteracin.


Ejemplo con break:
if ( int x = 0 ; x < 10 ; x++ ) {
if ( x == 3 )
break;
System.out.print(x);
}
System.out.println("\nSe termin el if");

12
Se termin el if
En este caso, al ejecutarse el break se sale del bucle, lo que produce la salida anterior.
Los continue y break sin etiqueta (label) afectan al bucle ms profundo sobre el que se encuentren.

En el siguiente cdigo podemos apreciar el nivel sobre el que afecta el break:


if ( int x = 0 ; x < 3 ; x++ ) {
if ( int y = 0 ; y < 2 ; y++ ) {
if ( x > 0 )
break;
System.out.print(" y:" + y);
}
System.out.print(" x:" + x);
}
Cuando se ejecuta el break, solo sale del bucle de mayor anidacin, que en el caso anterior, es el if ( int y
Veamos una anidacin de ifs con breaks y continues ms compleja para entender cmo funciona:

Java World Captulo 5


public class breakTest {
static public void main(String[] args) {
for ( int x = 0 ; x < 5 ; x++ ) {
if ( x == 4 ) //El bucle correspondiente a X=4 no se ejecuta
break;
for ( int y = 0 ; y < 3 ; y++ ) {
System.out.print(" y:" + y);
if ( y == 1 ) { //y=1 hace que se pase a la siguiente iteracin
continue;
} else if ( y == 2 ) {
break; //y=2 hace que se corte el bucle for( int y
} else {
System.out.print(" z:" + y); //Si y=0 se muestra z
}
if ( x == 2 )
continue;
System.out.println(" x:" + x); //Solo cuando y=0 && x!=2 se llega a este punto
}
}
}
}
Es tortuoso el solo mirar este cdigo, pero si puedes obtener la salida por pantalla, significa que eres uno con los bucles.
La salida por pantalla sera:
y:0
y:1
y:1
y:1

z:0 x:0
y:2 y:0 z:0 x:1
y:2 y:0 z:0 y:1 y:2 y:0 z:0 x:3
y:2

Sentencias de ruptura con etiquetas


La etiqueta permite identificar a un bucle mediante un nombr e, de manera que cuando ejecutamos un break o continue, se le
puede especificar a qu bucle deseamos que afecte, sin importar donde se encuentre.
Las etiquetas deben de cumplir con las reglas de identificadores legales y convenciones de Java.
La sentencia de ruptura que llame a una etiqueta debe de estar contenida dentro del bucle con dicha
etiqueta, de lo contrario generar un error.
Ejemplo:
exterior:
for(int a = 0 ; a < 10 ; a++ ) {
for(b = 0 ; b < 3 ; b++ ) {
if (a == 3)
break exterior;
System.out.println("B:" + b);
continue exterior;
}
System.out.println("A:" + a);
}
B:0
B:1
B:2
Como vern, nunca se ejecuta la salida por pantalla de A, ni ninguna de B para valores de b>0. Esto es porque las sentencias de
ruptura no afectan al elemento ms prximo, sino al que contiene la etiqueta, que en este caso es el ms externo.

10

h
t
t
p
:
/
/
g
u
s
t
a
v
o
a
l
b
e
r
o
l
a
.
b
l
o
g
s
p
o
t
.
c
o
m

11

h
t
t
p
:
/
/
v
a
l
o
r
c
r
e
a
t
i
v
o
.
b
l
o
g
s
p
o
t
.
c
o
m

Java World Captulo 5

Manejo de excepciones
Una excepcin significa una condicin excepcional, la cual altera el flujo normal de ejecucin del programa.
El manejo de excepciones en Java permite una manera limpia de manejar las mismas aislndolas del cdigo que las puede lanzar, sin
tener que escribir cdigo que veri fique los valores de retorno. Adems, permite utilizar la misma forma de tratar una excepcin para
un rango de estas.

Capturando una excepcin utilizando try y catch


Cuando se genera una excepcin se dice que esta se lanza (throw). El cdigo encargado de manejar la excepcin es el manejador de
excepciones (exception handler), y este atrapa (catch) la excepcin lanzada.
Para poder especificar que cdigo ejecutar si es que una excepcin es lanzada, utilizamos la sintaxis try catch.
try {
//Bloque de cdigo a verificar ...
} catch(excepcion) {
//Excepcin con que se verifica ...
} finally {
//Bloque de cdigo que se ejecutar siempre.
}
Dentro del try se coloca todo el bloque de cdigo que pueda llegar a lanzar una excepcin y quisiramos verificar y/o, qu e dependa
de algn otro bloque que puede llegar a lanzar la excepcin.
Dentro del catch se especifica el cdigo a ejecutar en caso de identificarse la excepcin declarada.
Dentro del finally se pone el bloque de cdigo que se ejecutar siempre, sin importar si se lanz o no alguna excepcin, sea cual
sea.
Algunas cuestiones
Try
o
o
o

Una vez que se lance una excepcin, no se contina ejecutando el bloque de cdigo del try.
Solo se detecta la primera excepcin lanzada.
Si se especifica un try, se debe especificar un catch y/o un finally.

Catch
o Se pueden especificar la cantidad de catch que se desee, con las siguientes condiciones
Estos se deben de ubicar inmediatamente despus del try y antes del finally si es que se especifica.
Si hay ms de un catch, estos se deben de especificar uno a continuacin del otro.
No es posible especificar dos catch que manejen la misma excepcin
No es posible especificar un catch que maneja una excepcin que un catch anterior tambin lo hace (el
catch anterior es la superclase, y el catch siguiente una subclase. Genera error de compilacin).
Un catch puede manejar un tipo de excepcin que admita un grupo de estas
o Una vez que se detecta una excepcin, se entra en el primer catch que califique con el tipo de excepcin lanzada
o No hay forma de que una vez cargado el catch se contine con la ejecucin del try.
o Es posible no especificar un catch y que la compilacin sea vlida (siempre que se especifique un throws en la
firma).
Finally
o Este bloque es opcional.
o Se ejecutar siempre, por ms que se lance una excepcin o no, sea cual sea (en realidad es un 90% cierto). Es
posible que no se ejecute si se lanza un return en alguna de las sentencias try o catch.
o Se ejecuta luego del try y catch.
o

Debe especificarse inmediatamente luego de un bloque catch (si es que se lo especific), en su defecto, del try.

Propagacin de excepciones
En realidad no es necesario capturar una excepcin inmediatamente. A lo que me refiero es que cada cdigo que pueda lanzar una
excepcin no necesariamente debe de estar rodeado por un try.
Cuando un mtodo no captura la excepcin de esta manera, se dice que la est esquivando (ducking).

Java World Captulo 5


Pero hay una regla fundamental, si se produce una excepcin, alguien la tiene que capturar, o lo har la JVM y creme, no te
agradar que lo haga (si lo hace, detendr la ejecucin del programa, y mostrar por pantalla la excepcin lanzada, junto con el stack
de la misma).
Veamos un ejemplo simple:
public class exceptionDividoPorCero {
static public int tercerMetodo() {
return 4/0; //Ouch!, dividido por 0...
}
static public int segundoMetodo() {
return exceptionDividoPorCero.tercerMetodo();
}
static public int primerMetodo() {
return exceptionDividoPorCero.segundoMetodo();
}
static public void main(String[] args) {
System.out.println("Valor:" + exceptionDividoPorCero.primerMetodo());
}
}
Como podemos apreciar, una divisin por 0 lanza una excepcin en tiempo de ejecucin. En la salida por pantalla (producida porque
Exception in thread "main" java.lang.ArithmeticException: / by zero
at exceptionDividoPorCero.tercerMetodo(exceptionDividoPorCero.java:3)
at exceptionDividoPorCero.segundoMetodo(exceptionDividoPorCero.java:7)
at exceptionDividoPorCero.primerMetodo(exceptionDividoPorCero.java:11)
at exceptionDividoPorCero.main(exceptionDividoPorCero.java:14)
la excepcin llego hasta la JVM, o dicho de otra forma, la excepcin fue esquivada por el mtodo main), vemos dos cosas:
El tipo de excepcin lanzada: java.lang.ArithmeticException con el texto / by zero (dividido por cero) que en realidad es
una excepcin de tipo RuntimeException.
El stack (pila) de llamadas, desde donde se lanzo la excepcin, hasta el main. Tambin informa las lneas de las llamadas
(esto ltimo es muy til para rastrear los errores).

Definiendo que es una excepcion

En Java, o es una primitiva o es un Objeto, y dado que ya cubrimos todas las primitivas, nos queda as es, una Excepcin es un
Objeto. Con la salvedad de que todas las excepciones tienen en su rbol de herencia a la clase java.lang.Exception.
toda excepcin contiene en su rbol de herencia java.lang.Exception. Pero no es necesario que her ede
directamente, puede ser una subclase, o ms niveles de herencia como se desee. Pero siempre, al final del
camino habr una clase Exception esperando.

12

h
t
t
p
:
/
/
g
u
s
t
a
v
o
a
l
b
e
r
o
l
a
.
b
l
o
g
s
p
o
t
.
c
o
m

13

h
t
t
p
:
/
/
v
a
l
o
r
c
r
e
a
t
i
v
o
.
b
l
o
g
s
p
o
t
.
c
o
m

Java World Captulo 5

Jerarqua de excepciones
Object
Throwable

Error

Jerarqua de
excepciones

Exception

RuntimeException

Error

Toda clase que herede de Error representa un problema que no es generado por el programa, y generalmente es
insalvable. Un ejemplo puede ser el overflow de memoria por parte de la JVM.

Exception

De esta se desprenden dos categoras de excepciones: Excepciones que son posibles de interceptar, y excepciones
en tiempo de ejecucin, que son muy difciles de detectar, y que pueden derivarse de errores del programa.
Para el examen solo debes de saber que cualquier tipo de excepcin derivable de Throwable, Error,
Exception y RuntimeException puede ser lanzada con un throw, y que todos los tipos derivados de
estos pueden ser capturados (aunque es muy raro capturar otra cosa que no sea una Exception).

Java World Captulo 5

Atrapando excepciones
Cuando decimos que se puede atrapar una excepcin por su tipo, o por un tipo de una de sus superclases, nos referimos al
comportamiento habitual de un objeto con respecto a los parmetros de un mtodo.
Solo hay que tener en cuenta una cuestin, cuando en una sentencia try-catch se lanza una excepcin, se verifican los catch
desde arriba hacia abajo, y se ejecuta el que primero califique para la excepcin.
Veamos un ejemplo: (No se pr eocupen en entender ahora el por qu de las clases que cree, solo sepan que podemos crear nuestras
propias excepciones)
class PadreException extends Exception{
public PadreException(){}
public PadreException(String s){ super(s); }
}
class HijoException extends PadreException{
public HijoException(){}
public HijoException(String s){ super(s); }
}
class NietoException extends HijoException{
public NietoException(){}
public NietoException(String s){ super(s); }
}
public class pruebaExcepciones_1 {
static public void metodoLanzaException() throws NietoException{
throw new NietoException();
}
static public void main(String[] args) {
try {
pruebaExcepciones_1.metodoLanzaException();
} catch(PadreException e) {
System.out.println(e);
}
try {
pruebaExcepciones_1.metodoLanzaException();
} catch(HijoException e) {
System.out.println(e);
}
try {
pruebaExcepciones_1.metodoLanzaException();
} catch(NietoException e) {
System.out.println(e);
}
try {
pruebaExcepciones_1.metodoLanzaException();
} catch(NietoException e){
System.out.println("Nieto");
} catch(HijoException e){
System.out.println("Hijo");
} catch(PadreException e){
System.out.println("Padre");
}
}
}

14

h
t
t
p
:
/
/
g
u
s
t
a
v
o
a
l
b
e
r
o
l
a
.
b
l
o
g
s
p
o
t
.
c
o
m

15

h
t
t
p
:
/
/
v
a
l
o
r
c
r
e
a
t
i
v
o
.
b
l
o
g
s
p
o
t
.
c
o
m

Java World Captulo 5

NietoException
NietoException
NietoException
Nieto

Como vern, la excepcin puede ser captura por el tipo de la clase o de alguna de sus superclases.
Tambin se puede apreciar como en la coleccin de catchs califica en el primer intento.
Si se especifican varios catch, y alguno de estos es una subclase de otro, la misma debe posicionarse
siempre por encima de sus clases padres. Si por ejemplo en el cdigo anterior, NietoException se hubiera
especificado luego de alguna de las otras dos, hubiera generado un error de compilacin, dado que esa
excepcin ya se est capturando.

Declaracion de excepciones e interface pblica


Como vern en el ejemplo anterior, el mtodo que lanza la excepcin tiene en su firma un throws, esto es as porque las
excepciones que puede llegar a generar un mtodo o clase son parte de la firma.
Todo mtodo que lance (throw) o esquive (duck) una excepcin, a menos que sea una
RuntimeException o subclase de esta, debe declararla (throws) o capturarla (try-catch).

Java World Captulo 5

Relanzando excepciones
Si utilizas un try-catch, al capturar la excepcin puedes relanzarla, o lanzar otro tipo.
Veamos un ejemplo:
class MyException extends Exception{
public MyException(){}
public MyException(String s){ super(s); }
}
public class ejemploRelanzarException{
static public void metodoTercero() throws Exception{
try{
throw new Exception(); //Lanza una excepcion
}catch(Exception ex){
//La atrapa (catch)
throw ex;
//La vuelve a relanzar y se produce un duck (sale del mtodo)
}
}
static public void metodoSegundo() throws MyException{
try{
ejemploRelanzarException.metodoTercero(); //Llama a un mtodo que puede devolver
una excepcion de tipo Exception
}catch(Exception ex){
//Verifica por la excepcion de ese tipo
throw new MyException(ex.toString()); //Relanza una nueva excepcion con el
informe de la primera como mensaje
}
}
static public void main(String[] args){
try{
ejemploRelanzarException.metodoSegundo(); //Verifica un mtodo que puede devolver
una excepcion de tipo MyException
}catch(MyException ex){ //Atrapa la excepcion
System.out.println(ex); //Muestra la informacin de la excepcion
}
}
}
Demasiadas excepciones! Ahhh ERROR!!!
Vamos, que no es tan difcil. Primero prestemos atencin a las firmas de cada mtodo:
metodoSegundo dice lanzar una excepcin de tipo myException
metodoTercero dice lanzar una excepcin de tipo Excepcion
En el caso del metodoTercero, este lanza la excepcin, la captura, y relanza la misma (cuando hace el segundo throw, no tiene el
new).
segundoMetodo captura la excepcin, y en respuesta lanza una nueva excepcin de tipo MyException.
Dado que el mtodo main solo interactua con metodoSegundo, cuando se realiza el try, solo buscamos por la excepcin lanzada por
este (de todas maneras, si hubiramos especificado como tipo Exception hubiera sido vlido, dado que MyException her eda de
esta).
Cuando una excepcin es atrapada (try-catch), y como consecuencia, se relanza otra excepcin, la
informacin de la anterior se pierde. Salvo que se pase dicha informacin como descripcin a la nueva
excepcin.

16

h
t
t
p
:
/
/
g
u
s
t
a
v
o
a
l
b
e
r
o
l
a
.
b
l
o
g
s
p
o
t
.
c
o
m

17

h
t
t
p
:
/
/
v
a
l
o
r
c
r
e
a
t
i
v
o
.
b
l
o
g
s
p
o
t
.
c
o
m

Java World Captulo 5

Errores y excepciones comunes

Dado que en la ltima versi n del examen de Java se agregaron a varias preguntas las opciones de error de
compilacin, error de ejecucin, y se lanza una excepcin, es imperativo conocer cmo funcionan
estas, y saber determinar cundo sern lanzadas.

De donde provienen las excepciones


Es importante conocer que causa los errores y excepciones, y de donde provienen. Para propsitos del examen, dividimos los
orgenes en dos categoras:
Excepciones de la JVM
Excepciones de programacin

Aquellas que son lanzadas por la JVM.


Aquellas que son lanzadas explcitamente mediante un throw.

Veamos una tabla que resume las excepciones que necesitamos conocer para el examen:
Excepcin
Descripcin

Lanzado por

ArrayIndexOutOfBoundsException

JVM

ClassCastException
IllegalArgumentException
IllegalStateException
NullPointerException

NumberFormatException

AssertionError
ExceptionInInitializerError
StackOverflowError

NoClassDefFoundError

Lanzada cuando se intenta acceder a un elemento


del array con un ndice negativo o mayor a la
cantidad de elementos contenidos (length 1).
Lanzado cuando se intenta castear una clase que
falla a la verificacin Is-A.
Lanzada cuando un mtodo recibe un a rgumento
formateado de forma diferente a la que lo espera.
Lanzada cuando el estado del ambiente no coincide
con la operacin solicitada.
Lanzado cuando se intenta acceder a un objeto a
travs de una referencia que contiene un valor nulo
(null).
Lanzada cuando un mtodo que convierte un
String en un nmero recibe una cadena que no
puede ser formateada como tal.
Lanzada cuando una sentencia de verificacin
booleana detecta un false.
Lanzado cuando intentas inicializar una variable
esttica o un bloque de inicializacin.
Lanzada generalmente cuando un mtodo se llama
recursivamente muchas veces (cada invocacin se
agrega al stack).
Lanzada cuando la JVM no puede encontrar una
clase que necesita, debido a un error en la lnea de
comandos, un problema con los classpaths, o un
.class que falta.

JVM
Programticamente
Programticamente
JVM

Programticamente

Programticamente
JVM
JVM

JVM

Afirmaciones
Las afirmaciones (assertions), son una herramienta para poder verificar aquellas partes del cdigo que creemos no fallarn nu nca en
nuestro cdigo, pero que si las tuviramos que verificar, tendramos que empezar a generar ms excepciones.

Java World Captulo 5

Un vistazo a las afirmaciones


Supongamos que tienes un cdigo como el siguiente:
private float hazAlgo(int valor1, int valor2) {
float resultado = 0.0f;
if ( valor 2 != 0 ) {
resultado = (float)(valor1 / valor2);
} else {
//Nunca debera de suceder este caso
System.out.println("Error crtico. Tenemos una divisin por 0!!!! Ahhhhhh!!!!");
//El mensaje lo exager un poco para acentuar el problema de mostrar este mensaje
al usuario
}
return resultado;
}
Si no quisieras realizar excepciones para verificar esta condicin, y no deseas hacer un if/else, ya que si no se da la condicin, en
realidad el programa its toast.
Las afirmaciones nos permiten realizar esta verificacin de manera que la verificacin que realic emos tiene dos posibilidades:
Si es true

El cdigo contina ejecutndose con naturalidad

Si es false

Se detiene la ejecucin del programa y se lanza una AssertionException.

Jams debes atrapar esta excepcin. Debes esperar a que t programa literalmente explote y rastrear el
error utilizando como ayuda el stack de la excepcin.

Otro punto interesante de las afirmaciones, es que estas solo se ejecutan cuando las mismas se encuentran habilitadas, caso
contrario es como si no existieran. Esto es muy prctico cuando se trabaja en el ambiente de desarrollo, pero no querrs que el
programa que publicaste en el ambiente de produccin se detenga totalmente por haberse lanzado una afirmacin.
De todas formas, las afirmaciones siguen existiendo por ms que estn deshabilitadas, es solo que la JVM las ignora. Esto facilita que
si tenemos algn error en produccin que era verificado por las afirmaciones, estas pueden ser habilitadas para detectar el
problema ms rpido.

Reglas de sintaxis de las afirmaciones


Una afirmacin tiene dos tipos de sintaxis, la simple y la detallada.

Afirmacin simple
private float hazAlgo(int valor1, int valor2) {
assert (valor2 != 0);
return (float)(valor1 / valor2);
}
Verifica una condicin. Si esta se cumple la ejecucin contina, caso contrario, lanza la excepcin AssertionExcepcion.

Afirmacin detallada

private float hazAlgo(int valor1, int valor2) {


assert (valor2 != 0) : "valor1:" + valor1 + " - valor2:" + valor2;
return (float)(valor1 / valor2);
}

18

h
t
t
p
:
/
/
g
u
s
t
a
v
o
a
l
b
e
r
o
l
a
.
b
l
o
g
s
p
o
t
.
c
o
m

19

h
t
t
p
:
/
/
v
a
l
o
r
c
r
e
a
t
i
v
o
.
b
l
o
g
s
p
o
t
.
c
o
m

Java World Captulo 5


Se comporta de la misma manera que la afirmacin simple, con la diferencia de que aade una expresin. La funcin del segundo
parmetro es simplemente la de aadirse al stack para brindar un detalle del error ocurrido.
La expresin debe de resultar en un valor, no importa si se utiliza un enumerador, se llama a un mtodo, o
se pasa un String.

El prototipo de la sintaxis sera el siguiente:


assert (condicion) : expresion;
Condicin: debe resultar siempre en un valor de tipo boolean.
Expresin: puede resultar en un valor de cualquier tipo, pero debe de especificarse un valor.

Habilitando las afirmaciones


Es importante saber cmo ejecutar y cmo compilar cdigo con afirmaciones.
Un problema que nos podemos llegar a encontrar es que en versiones anteriores de Java, assert se poda utilizar como
identificador o como palabra reservada. A partir de Java 6, assert es una palabra reservada, cualquier intento de utilizarla como
variable derivar en un error de compilacin.
Por defecto las afirmaciones se encuentran desactivadas, pero podemos habilitarlas en tiempo de ejecucin.
Al invocar nuestro programa desde la consola de comandos, le indicamos si se encuentran activadas o no.
Ejemplo de llamada con afirmaciones habilitadas:
java -ea MiClase
java -enableassertions MiClase

Ejemplo de llamada con afirmaciones deshabilitadas:


java -da MiClase
java -disableassertions MiClase

Utilizando la sintaxis para afirmaciones deshabilitadas obtenemos el mismo comportamiento que la invocacin por defecto, pero ,
cambia cuando lo utilizamos de manera selectiva.

Habilitando afirmaciones de manera selectiva


Podemos aplicar la habilitacin o des habilitacin sobre una clase o package (y sus subpaquetes) especfico.
Ejemplo de llamada con afirmaciones selectivas habilitadas:
java -ea:MiOtraClase MiClase
java -ea:com.utils MiClase

En este ejemplo, solo habilitamos las afirmaciones para la clase MiOtraClase, y en la segunda llamada, para el paquete com.ut ils y
todos sus subpaquetes.
Ejemplo de llamada con afirmaciones selectivas deshabilita das:
java -da:MiOtraClase MiClase

Como mencionamos anteriormente, tampoco es de mucha ayuda este cdigo, dado que por defec to, las afirmaciones se encuentran
deshabilitadas.
Cul es el secreto entonces?
Se pueden combinar un comando general y uno selectivo, siempre que sean opuestos (uno habilita y el otro deshabilita).
Ejemplos de combinaciones:
java -da -ea:MiOtraClase MiClase
java -ea -da:com.utils... MiClase

En el primero, se encuentran deshabilitadas, salvo en la clase MiOtraClase.


En el segundo, se encuentran habilitadas, salvo dentro del paquete com.utils y sus subpaquetes.

Utilizar las afirmaciones apropiadamente


No utilices nunca las afirmaciones para validar los parmetros de un mtodo public, si deseas validar la entrada de un
parmetro, puedes utilizar la excepcin IllegalArgumentException.
Utiliza las afirmaciones para verificar los parmetros de un mtodo privado. Cuando asumes que los parmetros que le
envas son correctos, verifica esto con una afirmacin.

Java World Captulo 5


No utilices nunca las afirmaciones para validar los argumentos de
entrada de la lnea de comandos. En todo caso, utiliza una excepcin.
Utiliza las afirmaciones para verificar cdigo que nunca debera de
ejecutarse.
No utilices nunca las afirmaciones cuando estas puedan causar efectos
secundarios. El programa no debe de modificarse porque una
afirmacin se encuentra habilitada.
private x;
private void verificaAsertion (int valor) {
assert(validacionAsertion());
//Se llama a un mtodo que modifica un
atributo de la clase
}

Lo que se viene
En la prxima entrega estaremos
adentrndonos en la API de Java para
Entrada/Salida.
Veremos como escribir en archivos de
texto, y como obtener la informacin
almacenada.
Aprenderemos como funcionan a bajo
nivel los Strings, tanto los literales como
la instanciacin mediante new.
Descubriremos
objetos.

la

serializacin

de

Y aprenderemos a manejar fechas en


Java.

private boolean validacionAsertion() {


x++;
return true;
}

20

h
t
t
p
:
/
/
g
u
s
t
a
v
o
a
l
b
e
r
o
l
a
.
b
l
o
g
s
p
o
t
.
c
o
m

21

h
t
t
p
:
/
/
v
a
l
o
r
c
r
e
a
t
i
v
o
.
b
l
o
g
s
p
o
t
.
c
o
m

Java World Captulo 5

Вам также может понравиться