2. Java World Capítulo 5
2
If y Switch h
Las sentencias if y switch generalmente se refieren a sentencias de decisión. Utilizamos las sentencias de decisión cuando t
deseamos que nuestro programa ejecute un comportamiento u otro, dependiendo del estado de una o más variables. t
If-‐else p
:
if (expresionBooleana) { /
//Código1 ...
} else if (expresionBooleana) { /
//Código2 ... g
} else {
//Código3 ...
u
} s
Lo que hace el código es lo siguiente: t
a
1. Evalúa l a primer expresión booleana v
2. Si el resultado es true
o
2.1. Se ejecuta Código1
3. Si el resultado es false
a
3.1. Se verifica l a s egunda expresión booleana l
3.2. Si el resultado es true b
3.2.1. Se ejecuta Código2 e
3.3. Si el resultado es false r
3.4. Se ejecuta el else (condición por defecto si no s e cumplen los if´s)
o
3.4.1. Se ejecuta Código3
l
Ahora, vamos a a clarar cómo puede llegar a s er la s intaxis: a
.
Solo debe existir un if
b
Puede haber uno o más else if, siempre que exista un if previo
l
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 código de una línea). No es o
una práctica r ecomendada g
Solo s e pueden evaluar expresiones booleanas (esto no es C, un boolean true no es un int mayor que 0). s
Los else if y else deben de estar encadenados al if (empiezan a medida que el otro finaliza). Si esta cadena se rompe p
generará un error de compilación. o
Los else if y else son encadenados al if más próximo. t
Se ejecuta solo l a primer condición que califique (en caso de que no califique ninguna, s e ejecuta si existe el else).
.
c
Hay que recordar que una s entencia de condición, en Java, solo evalúa l os tipos boolean. Es válido a signar
o
un valor a una variable dentro de una condición, pero si el tipo de da to almacenado no es de tipo boolean,
if ( x m
compilación.
Ejemplos de algunos tipos de expresiones válidas, y no válidas:
Expresión 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");;
}
3. 3 Java World Capítulo 5
h
t Soy el valor 2
t Soy el valor 3
p
: Expresión 2
/
static public void main(String[] args) {
/ boolean expresion = false
v if (expresion)
System.out.println("Soy el valor 1");;
a else
l System.out.println("Soy el valor 2");;
System.out.println("Soy el valor 3");;
o }
r
c
Soy el valor 2
r
Soy el valor 3
e
a Expresión 3
t static public void ejecutarIf(int valor) {
i if (valor == 1) {
System.out.println("Soy el valor 1");;
v } else if ( valor > 0 ) {
o System.out.println("Soy el valor 2");;
} else {
. System.out.println("Soy el valor 3");;
b }
l }
o static public void main (String[] args) {
g ejecutarIf(1);;
ejecutarIf(0);;
s
ejecutarIf(87);;
p
}
o
Soy el valor 1
t
Soy el valor 3
. Soy el valor 2
c
o Expresión 4
m 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 compilación!
Como se puede apreciar en la expresión 1 solo tenemos el if. En la expresión 2, le sumamos un else. En ambas expresiones, no
utilizamos l as {} para encerrar el código, pero aun así es válido, dado que ninguno de ellos ocupa más de una l ínea.
4. Java World Capítulo 5
4
h
Que se escriba en un renglón no quiere decir que sea código de una sola línea. El ; delimita el fin de línea t
por ejemplo, de manera que un código como int a;a++; son dos líneas. t
p
En la expresión 3 agregamos un else if a la condición, y las {}. Como verás, al llamar a la expresión con el 1, podría calificar para
:
la primera sentencia, o para la s egunda, pero como la primera es quien la captura primero, se ejecuta esta. /
En la expresión 4 nos encontramos con un error de ejecución. Este se produce por el precepto de que los else else if, deben /
de estar encadenados unos a otros comenzando por el if. Como verán, al no tener {}, dentro del if solo entra el print g
print else a continuación. Dado que la sentencia anterior no fue un if, o u
else if, se genera un error de compilación. s
Veamos un ejemplo un poco más c omplicado:
t
public class ifTest {
static public void main(String[] args) {
a
if (expresion) v
if (expresion2) o
System.out.println("Me ejecuto 1");;
else a
System.out.println("Me ejecuto 2");; l
else
System.out.println("Me ejecuto 3");; b
} e
}
r
En realidad, no es más difícil que lo anterior, solamente tiene un if o
examen es generado dinámicamente, por lo cual, l os creadores a dmiten que podemos llegar a enco ntrarnos con c ódigo como este. l
Ahora pensemos, que valor veríamos si, expresion es true y expresion2 es false? a
Me ejecuto 2
.
Y si expresion es false y expresion2 es true?
Me ejecuto 3 b
Y si expresion es false y expresion2 es false? l
Me ejecuto 3
o
Para que vean más claramente, el código i ndentado y con l laves s ería el siguiente:
g
public class ifTest {
s
static public void main(String[] args) {
if (expresion) { p
if (expresion2) { o
System.out.println("Me ejecuto 1");;
} else { t
System.out.println("Me ejecuto 2");; .
}
} else { c
System.out.println("Me ejecuto 3");; o
}
}
m
}
Si quieren hacer la prueba s e darán cuenta de que el código resultante es el mismo.
Switch
Una manera de simular el uso de múltiples else if es la s entencia switch.
Básicamente, 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 s entencia switch:
5. 5 Java World Capítulo 5
h static public class switchtest {
static public void main(String[] args) {
t int x = 45;;
t switch (x) {
case 1:
p System.out.println("valor: 1");;
: break;;
case 2:
/ System.out.println("valor: 2");;
/ break;;
v case 3:
case 4:
a System.out.println("valor: 3 o 4");;
l break;;
case 5:
o System.out.println("valor: 5");;
r break;;
default:
c
System.out.println("Ningún valor fue tenido en cuenta");;
r }
e }
}
a
t Iremos explicando el código a nterior por pasos.
Primero, tengamos en cuenta las condiciones que debe cumplir una s entencia s witch para ser válida:
i
v Cada valor especificado en el case debe de ser un literal o una constante final cargada en tiempo de compilación (cuando se
o declara s e inicializa. final int a = 1;)
. Solo s e puede comparar contra un valor, no contra un rango (>, <, >=, <= no están permitidos).
b La sentencia break es opcional, pero si no se especifica, se seguirán ejecutando las líneas i nferiores hasta toparse con otro
l break o terminar l a s entencia switch.
Los valores tanto para el case, como para la entrada del switch, solo pueden ser aquellos que se puedan tipificar como
o
int (no importa que el casteo sea implícito). Tampoco califica un String. Puede llegar calificar un enum.
g No pueden haber dos case que comparen el mismo valor.
s 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
p overflow, se genera un error de compilación.
o Se pueden combinar varios case sucesivamente (ver ejemplo case 3: case 4:) puede calificar con cualquiera de los
t valores, y solo es necesario que califique para 1.
. La sentencia default se ejecuta si no c alificó ningún case. Esta no necesita estar al final.
c Por más que se ejecute default, si no se especifica un break, y hay más s entencias debajo de esta, se ejecutarán como con
un case nor mal.
o
m
6. Java World Capítulo 5
6
Bucles e iteraciones h
En java existen tres sentencias para bucles: while, do y for (este último tiene dos alternativas). t
t
While
p
La sentencia while es adecuada cuando no tenemos idea de cuantas veces se ejecutará un bloque de código, pero si queremos que :
en algún momento, este finalice.
/
La sintaxis del while:
/
while (condicion) {
//Bloque de código ...
g
} u
s
Siempre que la condición sea verdadera s e ejecutará el bloque de código.
t
Puede que el bloque de código no s e ejecute nunca, si la condición i nicialmente es false.
La condición tiene que ser una expresión booleana.
a
Cualquier variable utilizada dentro del while debe de ser declarada previamente (es ilegal declarar una variable dentro de v
la condición). o
a
Do l
La sentencia do es semejante al while, son la diferencia de que primero ejecuta el bloque de código, y luego evalúa l a condición (al b
revés del while). e
La sintaxis del do: r
do { o
//Bloque de código ...
} while (condición);; l
a
A diferencia del while: .
b
La condición se ejecutara al menos una vez.
l
El while se finaliza con ;.
o
For g
El for es un poco más complejo, pero simplemente porque contiene más elementos en su invocación que la condición . Estos se s
pueden r esumir de la siguiente manera: p
for ( inicializacion ;; condicion ;; incremento variables contador ) { o
//Bloque de código ... t
} .
c
Vamos a describir que hace, y que se puede hacer en cada sección:
o
Inicialización m
En esta parte se pueden asignar valores a variables ya declaradas, así como declarar una variabl e (esta solo será
visible para la s entencia for) e inicializarla.
Condición
Al igual que en las sentencias de bucle anteriores, la condición indica si se vuelve a ejecutar el bloque de código o
no.
Incremento variables c ontador
Aquí se incrementan las vari ables que son utilizadas para verificar la condición (en realidad, se pueden incrementar
o decrementar con cualquier operación matemática). A su vez, esta sección permite realizar cualquier acción, hasta puedes
realizar un print dentro de la misma.
Veamos una sentencia real:
7. 7 Java World Capítulo 5
h int y = 0;;
int x = 0;;
t for ( x = 0, y = 3 ;; x == 0 && y < 10 ;; y++, x-- ) {
t //Bloque de código ...
}
p
: Algunas c uestiones s obre l a s entencia 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 código.
v En la i nicialización podemos especificar varias variables, s eparadas cada una por una coma, pero solo una a cción
a o Podemos cambiar el valor de variables ya declaradas previamente al for
l o Podemos declarar e inicializar variables solo para el for, que no se encuentren definidas previamente en el mismo
o scope.
r Solo podemos evaluar una condición (esto no quiere decir que no podamos combinar sentencias con los operadores &&, &,
|| y |).
c
Podemos realizar c ualquier operación matemática sobre las variables en el incremento de variables contador.
r
La sección de incremento variables contador se ejecuta cada vez que se completa el bloque de código.
e
Para separar elementos en la misma s ección s e utiliza l a ,.
a
t
En un bucle for, no es nec esario especificar ninguna de las tres secciones. Se las puede dejar en blanco. Un
i ejemplo válido s ería for( ; ; ){}.
v En la sección incremento variables contador, en realidad podemos realizar cualquier operación,
o indistintamente de que la misma s ea i ncremento, o una salida por pantalla.
.
For-‐each
b
l Es una nueva funcionalidad que se encuentra disponible a partir de java 6, la cual permite realizar una iteración de un array o
o colección.
En vez del tradicional for el cual c ontiene tres secciones, el for-‐each contiene dos secciones.
g
Veamos un ejemplo con los dos tipos de sintaxis:
s
//Sintaxis for
p int[] arr = {1, 2, 3, 4, 5};;
o for (int x = 0 ;; x < arr.length ;; x++ ){
t System.out.println(a[x]);;
}
.
c //Sintaxis for-each
int[] arr = {1, 2, 3, 4, 5};;
o for (int x : arr) {
m System.out.println(x);;
}
La nueva sintaxis está formada por:
for ( declaración : expresión ) {
//Bloque de código ...
}
Vamos a describir que hace, y que se puede hacer en cada sección:
Declaración
o Permite declarar una variable, la cual s e irá completando con cada elemento del array/colección.
o La variable declarada debe ser del mismo tipo que cada elemento dentro del array, o un tipo compatible (casteo
implícito, o dentro del mismo árbol de herencia siempre que sea downcasting, no se permite upcasting).
8. Java World Capítulo 5
8
o La variable no debe de existir en el mismo nivel de visión (scope). h
Expresión
t
o Especifica el a rray o colección s obre el cual se realiza la i teración.
t
o Se puede especificar l a llamada a un método, siempre que este devuelva un array o c olección.
o El tipo del a rray puede ser cualquiera: primitivas, objetos, incluso array de arrays. p
:
Algunos ejemplos de for-‐eachs válidos: /
class Vehiculo { /
public String toString(){
return "Soy un vehiculo";; g
} u
}
class Auto extends Vehiculo {
s
public String toString() { t
return "Soy un auto";;
a
}
} v
class Moto extends Vehiculo { o
public String toString() {
return "Soy una moto";; a
} l
}
b
public class forEachTest { e
static public void main(String[] args) { r
int[] intArray = {1, 2, 3};;
int[][] intIntArray = {{1, 2}, {3, 4}, {5, 6}};; o
Vehiculo[] vehiculoArray = {new Auto(), new Moto()};; l
System.out.println("intArray:");; a
for (int x : intArray) { .
System.out.println(x);;
}
b
l
System.out.println("nintIntArray:");; o
for (int[] x : intIntArray) {
System.out.println(x);; g
} s
System.out.println("nvehiculoArray:");; p
for (Vehiculo x : vehiculoArray) { o
System.out.println(x);;
}
t
} .
} c
o
m
9. 9 Java World Capítulo 5
h Break y continue
t Estos operadores pueden ser utilizados para salir del bucle, o para s altar a la siguiente iteración.
t
p continue debe de declararse dentro de un bucle, dentro de una sentencia switch generará un error de
: compilación. 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 s entencias dentro de un bucle if.
v Ejemplo con continue:
a if ( int x = 0 ;; x < 10 ;; x++ ) {
l if ( x == 3 )
continue;;
o System.out.print(x);;
r }
c System.out.println("nSe terminó el if");;
r
e
a 12456789
t Se terminó el if
i
v
Podemos ver como continue hace que se pase a la s iguiente iteración.
o
. Ejemplo con break:
b if ( int x = 0 ;; x < 10 ;; x++ ) {
l if ( x == 3 )
break;;
o System.out.print(x);;
g }
System.out.println("nSe terminó el if");;
s
p
12
o
Se terminó el if
t
. En este caso, al ejecutarse el break se sale del bucle, lo que produce la salida a nterior.
c
o Los continue y break sin etiqueta (label) afectan al bucle más profundo sobre el que se encuentren.
m
En el siguiente código 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 anidación, que en el caso a nterior, es el if ( int y
Veamos una anidación de if´s con breaks y continues más compleja para entender cómo funciona:
10. Java World Capítulo 5
10
public class breakTest { h
static public void main(String[] args) {
t
for ( int x = 0 ;; x < 5 ;; x++ ) {
if ( x == 4 ) //El bucle correspondiente a X=4 no se ejecuta t
break;; p
for ( int y = 0 ;; y < 3 ;; y++ ) {
System.out.print(" y:" + y);; :
if ( y == 1 ) { //y=1 hace que se pase a la siguiente iteración /
continue;;
} else if ( y == 2 ) { /
break;; g
} else {
u
System.out.print(" z:" + y);; //Si y=0 se muestra z
} s
if ( x == 2 ) t
continue;;
System.out.println(" x:" + x);; //Solo cuando y=0 && x!=2 se llega a este punto a
} v
}
} o
} a
l
Es tortuoso el solo mirar este código, pero si puedes obtener la salida por pantalla, significa que eres uno con los bucles.
La salida por pantalla s ería: b
e
y:0 z:0 x:0
r
y:1 y:2 y:0 z:0 x:1
y:1 y:2 y:0 z:0 y:1 y:2 y:0 z:0 x:3 o
y:1 y:2 l
a
.
Sentencias de ruptura con etiquetas
b
La etiqueta permite identificar a un bucle mediante un nombr e, de manera que cuando ejecutamos un break o continue, se le
l
puede especificar a qué bucle deseamos que afecte, sin importar donde se encuentre.
o
Las etiquetas deben de cumplir con las r eglas de identificadores legales y c onvenciones de Java.
g
La sentencia de ruptura que llame a una etiqueta debe de estar contenida dentro del bucle con dicha s
etiqueta, de lo contrario generará un error. p
o
Ejemplo:
t
exterior:
for(int a = 0 ;; a < 10 ;; a++ ) { .
for(b = 0 ;; b < 3 ;; b++ ) { c
if (a == 3)
break exterior;; o
System.out.println("B:" + b);; m
continue exterior;;
}
System.out.println("A:" + a);;
}
B:0
B:1
B:2
Como verán, 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 más próximo, sino al que contiene la etiqueta, que en este caso es el más externo.
11. 11 Java World Capítulo 5
h Manejo de excepciones
t Una excepción signi
t El manejo de excepciones en Java permite una manera limpia de manejar l as mismas aislándolas del código que las puede lanzar, sin
tener que escribir código que veri fique los valores de retorno. Además, permite utilizar la misma forma de tratar una excepción para
p
un rango de estas.
:
/ Capturando una excepción utilizando try y catch
/ Cuando se genera una excepción se dice que esta se lanza (throw). El código encargado de manejar la excepción es el manejador de
v excepciones (exception handler), y este atrapa (catch) la excepción lanzada.
a Para poder especificar que código ejecutar si es que una excepción es lanzada, utilizamos la s intaxis try catch.
l try {
//Bloque de código a verificar ...
o } catch(excepcion) {
r //Excepción con que se verifica ...
c } finally {
//Bloque de código que se ejecutará siempre.
r }
e
Dentro del try se coloca todo el bloque de código que pueda llegar a l anzar una excepción y quisiéramos verificar y/o, qu e dependa
a
de algún otro bloque que puede llegar a lanzar la excepción.
t Dentro del catch se especifica el código a ejecutar en caso de identificarse la excepción declarada.
i Dentro del finally se pone el bloque de código que se ejecutará siempre, sin importar si s e lanzó o no alguna excepción, sea cual
v sea.
o Algunas c uestiones
.
Try
b o Una vez que se lance una excepción, no se continúa ejecutando el bloque de código del try.
l o Solo s e detecta la primera excepción l anzada.
o o Si s e especifica un try, se debe especificar un catch y/o un finally.
g Catch
s o Se pueden especificar l a c antidad de catch que se desee, con las siguientes condiciones
Estos se deben de ubicar i nmediatamente después del try y antes del finally si es que se especifica.
p
Si hay más de un catch, estos se deben de especificar uno a c ontinuación del otro.
o
No es posible especificar dos catch que manejen la misma excepción
t No es posible especificar un catch que maneja una excepción que un catch anterior también lo hace (el
. catch anterior es la s uperclase, y el catch siguiente una subclase. Genera error de compilación).
c Un catch puede manejar un tipo de excepción que admita un grupo de estas
o o Una vez que se detecta una excepción, se entra en el primer catch que califique con el tipo de excepción lanzada
m o No hay forma de que una vez cargado el c atch s e continúe con l a ejecución del try.
o Es posible no especificar un catch y que la compilación sea válida (siempre que se especifique un throws en la
firma).
Finally
o Este bloque es opcional.
o Se ejecutará siempre, por más que se lance una excepción o no, sea cual sea (en realidad es un 90% cierto). Es
posible que no se ejecute si s e lanza un return en alguna de las sentencias try o catch.
o Se ejecuta luego del try y catch.
o Debe especificarse i nmediatamente luego de un bloque catch (si es que se lo especificó), en su defecto, del try.
Propagación de excepciones
En realidad no es necesario capturar una excepción inmediatamente. A lo que me refiero es que cada código que pueda lanzar una
excepción no necesariamente debe de estar rodeado por un try.
Cuando un método no captura l a excepción de esta manera, se dice que la está esquivando (ducking).
12. Java World Capítulo 5
12
Pero hay una regla fundamental, si se produce una excepción, alguien la tiene que capturar, o lo hará la JVM y créeme, no te h
agradará que lo haga (si lo hace, detendrá la ejecución del programa, y mostrará por pantalla l a excepción l anzada, junto con el stack
t
de la misma).
Veamos un ejemplo simple:
t
p
public class exceptionDividoPorCero {
static public int tercerMetodo() { :
return 4/0;; //Ouch!, dividido por 0... /
}
/
static public int segundoMetodo() { g
return exceptionDividoPorCero.tercerMetodo();;
}
u
s
static public int primerMetodo() { t
return exceptionDividoPorCero.segundoMetodo();;
} a
static public void main(String[] args) { v
System.out.println("Valor:" + exceptionDividoPorCero.primerMetodo());;
}
o
} a
Como podemos apreciar, una división por 0 lanza una excepción en tiempo de ejecución. En la s alida por pantalla (producida porque l
Exception in thread "main" java.lang.ArithmeticException: / by zero
b
at exceptionDividoPorCero.tercerMetodo(exceptionDividoPorCero.java:3) e
at exceptionDividoPorCero.segundoMetodo(exceptionDividoPorCero.java:7) r
at exceptionDividoPorCero.primerMetodo(exceptionDividoPorCero.java:11) o
at exceptionDividoPorCero.main(exceptionDividoPorCero.java:14)
l
la excepción llego hasta la JVM, o dicho de otra forma, la excepción fue esquivada por el método main), vemos dos cosas: a
.
una excepción de tipo RuntimeException.
b
El stack (pila) de llamadas, desde donde se lanzo l a excepción, hasta el main. También i nforma l as l íneas de las llamadas
(esto último es muy útil para rastrear los errores). l
Definiendo que es una excepcion o
un
g
Objeto. Con la s alvedad de que todas l as excepciones tienen en su árbol de herencia a l a clase java.lang.Exception. s
p
toda excepción contiene en su árbol de herencia java.lang.Exception. Pero no es necesario que her ede o
directamente, puede ser una subclase, o más niveles de herencia como se desee. Pero siempre, al final del t
camino habrá una clase Exception esperando.
.
c
o
m
13. 13 Java World Capítulo 5
h Jerarquía de excepciones
t
Object
t Jerarquía de
p excepciones
Throwable
:
/
/
v Error Exception
a
l
RuntimeException
o
r
c
Error
Toda clase que herede de Error representa un problema que no es generado por el programa, y generalmente es
r
insalvable. Un ejemplo puede ser el overflow de memoria por parte de la JVM.
e
a
Exception De esta se desprenden dos categorías de excepciones: Excepciones que son posibles de interceptar, y excepciones
t en tiempo de ejecución, que son muy difíciles de detectar, y que pueden derivarse de errores del programa.
i
v Para el examen solo debes de saber que cualquier tipo de excepción derivable de Throwable, Error,
o Exception y RuntimeException puede ser lanzada con un throw, y que todos los tipos derivados de
. estos pueden ser capturados (aunque es muy raro c apturar otra cosa que no sea una Exception).
b
l
o
g
s
p
o
t
.
c
o
m
14. Java World Capítulo 5
14
Atrapando excepciones h
Cuando decimos que se puede atrapar una excepción por su tipo, o por un tipo de una de sus superclases, nos referimos al t
comportamiento habitual de un objeto con respecto a los parámetros de un método. t
Solo hay que tener en cuenta una cuestión, cuando en una sentencia try-‐catch se lanza una excepción, se verifican los catch p
desde arriba hacia abajo, y se ejecuta el que primero califique para la excepción.
:
Veamos un ejemplo: (No se pr eocupen en entender ahora el por qué de las clases que cree, solo s epan que podemos crear nuestras
/
propias excepciones)
/
g
class PadreException extends Exception{
public PadreException(){} u
public PadreException(String s){ super(s);; } s
}
t
class HijoException extends PadreException{ a
public HijoException(){}
public HijoException(String s){ super(s);; }
v
} o
a
class NietoException extends HijoException{
public NietoException(){} l
public NietoException(String s){ super(s);; } b
}
e
public class pruebaExcepciones_1 { r
static public void metodoLanzaException() throws NietoException{
throw new NietoException();;
o
} l
static public void main(String[] args) { a
try {
pruebaExcepciones_1.metodoLanzaException();; .
} catch(PadreException e) { b
System.out.println(e);;
} l
o
try {
pruebaExcepciones_1.metodoLanzaException();;
g
} catch(HijoException e) { s
System.out.println(e);; p
}
o
try { t
pruebaExcepciones_1.metodoLanzaException();;
} catch(NietoException e) { .
System.out.println(e);; c
}
o
try { m
pruebaExcepciones_1.metodoLanzaException();;
} catch(NietoException e){
System.out.println("Nieto");;
} catch(HijoException e){
System.out.println("Hijo");;
} catch(PadreException e){
System.out.println("Padre");;
}
}
}
15. 15 Java World Capítulo 5
h NietoException
t NietoException
t NietoException
Nieto
p
:
/ Como verán, la excepción puede ser captura por el tipo de la clase o de alguna de sus superclases.
También se puede apreciar como en la colección de catchs califica en el primer intento.
/
v Si s e especifican varios catch, y alguno de estos es una s ubclase de otro, la misma debe posicionarse
a siempre por encima de sus clases padres. Si por ejemplo en el código anterior, NietoException se hubiera
especificado l uego de alguna de las otras dos, hubiera generado un error de compilación, dado que esa
l excepción ya s e está capturando.
o
r Declaracion de excepciones e interface pública
c
Como verán en el ejemplo anterior, el método que lanza la excepción tiene en su firma un throws, esto es así porque las
r
excepciones que puede llegar a generar un método o clase son parte de la firma.
e
a Todo método que lance (throw) o esquive (duck) una excepción, a menos que sea una
t RuntimeException o subclase de esta, debe declararla (throws) o capturarla (try-‐catch).
i
v
o
.
b
l
o
g
s
p
o
t
.
c
o
m
16. Java World Capítulo 5
16
Relanzando excepciones h
Si utilizas un try-‐catch, al capturar la excepción puedes relanzarla, o lanzar otro tipo. t
Veamos un ejemplo: t
class MyException extends Exception{ p
public MyException(){} :
public MyException(String s){ super(s);; }
} /
/
public class ejemploRelanzarException{
g
static public void metodoTercero() throws Exception{ u
try{ s
throw new Exception();; //Lanza una excepcion
}catch(Exception ex){ //La atrapa (catch) t
throw ex;; //La vuelve a relanzar y se produce un duck (sale del método) a
}
} v
o
static public void metodoSegundo() throws MyException{
try{ a
ejemploRelanzarException.metodoTercero();; //Llama a un método que puede devolver l
una excepcion de tipo Exception b
}catch(Exception ex){ //Verifica por la excepcion de ese tipo
throw new MyException(ex.toString());; //Relanza una nueva excepcion con el e
informe de la primera como mensaje r
}
} o
l
static public void main(String[] args){
try{ a
ejemploRelanzarException.metodoSegundo();; //Verifica un método que puede devolver .
una excepcion de tipo MyException b
}catch(MyException ex){ //Atrapa la excepcion
l
System.out.println(ex);; //Muestra la información de la excepcion
}
o
}
} g
s
¡Dema
p
Vamos, que no es tan difícil. Primero prestemos atención a las firmas de cada método: o
metodoSegundo dice lanzar una excepción de tipo myException t
metodoTercero dice lanzar una excepción de tipo Excepcion .
En el caso del metodoTercero, este lanza la excepción, la captura, y relanza la misma (cuando hace el segundo throw, no tiene el
c
new).
segundoMetodo captura l a excepción, y en respuesta lanza una nueva excepción de tipo MyException. o
Dado que el método main solo i nteractua con metodoSegundo, cuando se realiza el try, solo buscamos por l a excepción lanzada por m
este (de todas maneras, si hubiéramos especificado como tipo Exception hubiera sido válido, dado que MyException her eda de
esta).
Cuando una excepción es atrapada (try-‐catch), y como consecuencia, se relanza otra excepción, la
información de la anterior se pierde. Salvo que se pase dicha información como descripción a la nueva
excepción.
17. 17 Java World Capítulo 5
h Errores y excepciones comunes
t
t Dado que en la última versi
p
: estas, y saber determinar cuándo serán lanzadas.
/
/ De donde provienen las excepciones
v
Es importante conocer que causa los errores y excepciones, y de donde provienen. Para propósitos del examen, dividimos los
a
orígenes en dos categorías:
l
o Excepciones de la JVM Aquellas que son l anzadas por la JVM.
r Excepciones de programación Aquellas que son l anzadas explícitamente mediante un throw.
c
Veamos una tabla que resume las excepciones que necesitamos conocer para el examen:
r Excepción Descripción Lanzado por
e ArrayIndexOutOfBoundsException Lanzada cuando se intenta acceder a un elemento JVM
a del array con un índice negativo o mayor a la
t cantidad de elementos contenidos (length 1).
i ClassCastException Lanzado cuando se intenta castear una clase que JVM
v falla a l a verificación Is-‐A.
IllegalArgumentException Lanzada cuando un método recibe un a rgumento Programáticamente
o
formateado de forma diferente a la que lo espera.
. IllegalStateException Lanzada cuando el estado del ambiente no coincide Programáticamente
b con la operación s olicitada.
l NullPointerException Lanzado cuando se intenta acceder a un objeto a JVM
o través de una referencia que contiene un valor nulo
g (null).
NumberFormatException Lanzada cuando un método que convierte un Programáticamente
s
String en un número recibe una cadena que no
p puede ser formateada como tal.
o AssertionError Lanzada cuando una sentencia de verificación Programáticamente
t booleana detecta un false.
. ExceptionInInitializerError Lanzado cuando intentas inicializar una variable JVM
c estática o un bloque de inicialización.
o StackOverflowError Lanzada generalmente cuando un método se llama JVM
recursivamente muchas veces (cada invocación se
m
agrega al s tack).
NoClassDefFoundError Lanzada cuando la JVM no puede encontrar una JVM
clase que necesita, debido a un error en la línea de
comandos, un problema con los classpaths, o un
.class que falta.
Afirmaciones
Las afirmaciones (assertions), son una herramienta para poder verificar aquellas partes del código que creemos no fallarán nu nca en
nuestro código, pero que si las tuviéramos que verificar, tendríamos que empezar a generar más excepciones.