Beruflich Dokumente
Kultur Dokumente
Arreglos, String,
Polimorfismo y
Excepciones en Java
0
24
1
12
2
14
3
28
4
9
5
2
Dimensin 1
Dimensin 2
Filas
0
1
2
0
43
3
6
Columnas
1
2
21
7
67 34
2
56
3
25
67
87
Dimensin 2
Dimensin 3
Declaracin de un arreglo.
Creacin de un arreglo.
Inicializacin de un arreglo.
Declaracin de un arreglo
Un arreglo se declara indicando el tipo de dato de los elementos que el
arreglo almacenar, pudiendo ser tipos de datos primitivos o tipos de datos
por referencia (objeto), seguido de un par de corchetes que se pueden
ubicar a la izquierda o a la derecha del identificador del arreglo. A
continuacin se declaran dos arreglos para ejemplificar:
int []numeros;
String palabras[];
El primer arreglo es un objeto cuyo identificador es numeros y almacena
valores numricos enteros (int). El segundo arreglo es un objeto cuyo
identificador es palabras y almacena cadenas de caracteres de tipo
String.
Creacin de un arreglo
La creacin de un arreglo significa invocar a su constructor para que est
disponible en memoria junto a todos los objetos creados por la Mquina
Virtual Java. Para la creacin de un arreglo, Java debe conocer cunto
espacio de memoria debe reservar, motivo por el cual se debe
especificar el tamao del arreglo durante la creacin del mismo. El tamao
del arreglo hace referencia a la cantidad de elementos que el arreglo podr
almacenar.
Hay diferentes alternativas para construir un arreglo. La formas ms
estandarizada es utilizando la palabra reservada new, seguida del tipo de
dato del arreglo con un par de corchetes que indican la cantidad de
elementos del arreglo. Veamos el siguiente ejemplo:
int[] calificaciones;
// declaracin de un arreglo
// que contendr nmeros enteros
// Creacin de un
// arreglo unidimensional
// de 3 elementos
declaracin de un
arreglo de 3
dimensiones de objetos
de tipo Persona
Inicializacin de un arreglo
Hasta el momento, hemos podido declarar y crear un arreglo, pero no
hemos indicado el almacenamiento de algn elemento en el mismo. Los
elementos que se pueden almacenar pueden ser valores primitivos u
objetos mediante variables de referencia.
Los elementos de un arreglo pueden ser accedidos mediante un ndice
que indica una posicin exacta en el arreglo. Este ndice es un nmero
que comienza en cero. Si por ejemplo, tenemos un arreglo de seis
elementos, los ndices del arreglo comenzarn en cero y llegarn hasta el
valor cinco.
Si observamos cada uno de los elementos del arreglo, todos ellos pueden
almacenar objetos de tipo Persona, pero por el momento tienen referencias
nulas. El prximo paso entonces, es crear objetos de tipo Persona y asignar
estos objetos a las posiciones del arreglo empleados. Esto lo podemos
realizar de la siguiente manera:
empleados[0] = new Persona(Juan);
empleados[1] = new Persona(Lucas);
empleados[2] = new Persona(Florencia);
De esta forma, para cada posicin del arreglo empleados, hemos
inicializado un objeto de tipo Persona.
Persona
Juan
Persona
Lucas
Persona
Florencia
Hay que tener en cuenta que si intentamos acceder a una posicin del
arreglo inexistente entonces obtendremos un error en tiempo de ejecucin
(ArrayIndexOutOfBoundsException). Por ejemplo, si en el caso anterior
intentamos inicializar la posicin del ndice 3 del arreglo, obtendremos un
error en tiempo de ejecucin.
empleados[3] = new Persona(Pedro);
El ndice 3 se encuentra fuera de rango, no existe, ya que el tamao del
arreglo es tres y por consiguiente los posibles valores de los ndices son 0, 1
y 2.
Para inicializar un arreglo de ms de una dimensin hay que aplicar la
misma lgica; se debe referenciar a alguna posicin especfica del arreglo y
asignar un objeto o valor en dicha posicin. El siguiente cdigo es un
ejemplo de inicializacin de un arreglo bidimensional que almacena valores
boolean.
boolean[][] a = new boolean[2][2];
a[0][0] = true;
a[0][1] = false;
a[1][0] = false;
a[1][1] = true;
Algo importante a tener en cuenta, es que si declaramos y construimos un
arreglo de tipo primitivo, entonces sus elementos quedan inicializados
con los valores por defecto correspondientes al tipo de dato del arreglo.
int[] a = new int[4];
boolean[][] b = new boolean[2][3];
En el ejemplo anterior, los elementos del arreglo a estn inicializados con
el valor cero ya que este es el valor por defecto o predeterminado para el
tipo de dato int. Los elementos del arreglo b estn inicializados con el
valor false ya que este es el valor por defecto del tipo de dato boolean.
Un arreglo tambin puede ser inicializado utilizando sentencias
iterativas, otorgando de esta forma una alternativa ms sencilla para
inicializar un arreglo cuando su tamao es grande. Supongamos que
tenemos un arreglo de String de cien elementos y deseamos inicializar cada
uno de ellos con una cadena de caracteres vaca . De acuerdo a lo que
acabamos de analizar anteriormente, una de las formas de hacerlo es la
siguiente:
String[] s = new String[100];
s[0] = new String();
s[1] = new String();
s[2] = new String();
.
.
.
s[98] = new String();
s[99] = new String();
Pero como podemos ver, esta forma de inicializar un arreglo resulta
bastante tediosa si el nmero de elementos que contiene el arreglo es alto.
Para facilitar esta tarea podemos hacer uso de las sentencias iterativas. Los
arreglos tienen un atributo denominado length que representa el
nmero de elementos que puede almacenar un arreglo, es decir, su tamao.
Entonces por ejemplo, en el arreglo anterior, el valor de s.length es igual a
100. Si hacemos uso de este atributo y de las sentencias iterativas entonces
podemos inicializar el arreglo. Una de las formas ms utilizadas es
mediante la sentencia for:
String[] s = new String[100];
for (int i=0; i<s.length; i++) {
s[i] = new String();
}
En cada iteracin, el valor de i es aumentado en una unidad comenzando
desde cero, entonces se utiliza esta variable para hacer referencia a las
posiciones de los elementos del arreglo. Cuando la variable i vale 100, no se
cumple la condicin i < s.length y por consiguiente el ciclo for deja de ser
ejecutado. Utilizar un ciclo for para inicializar un arreglo es una de las
formas ms utilizadas pero tambin se pueden utilizar otras sentencias
iterativas, como por ejemplo la sentencia while:
String[] s = new String[100];
int i=0;
while (i<100) {
s[i] = new String("");
i++;
}
Si deseamos utilizar sentencias iterativas para inicializar un arreglo de ms
de una dimensin entonces se debe iterar sobre todos los elementos para
cada una de las dimensiones que componen el arreglo. Veamos el siguiente
ejemplo:
1. byte[][][] arregloBytes = new byte[3][2][2];
Por ltimo, veremos otra alternativa que podemos utilizar para construir e
inicializar un arreglo:
char[] d;
d = new char[]{'p','o','o'};
Esta forma de crear e inicializar arreglos se denomina creacin annima
de arreglos. Esta alternativa es poco utilizada, pero no deja de ser una
posibilidad con la que nos encontremos alguna vez.
Una vez que tenemos un arreglo declarado, creado e inicializado, para
utilizarlo simplemente se deben referenciar a sus elementos utilizando el
ndice correspondiente a la posicin del elemento con el que se desea
trabajar.
A continuacin se muestra un ejemplo de una aplicacin que genera
instancias de la clase Usuario, las asigna a un arreglo de cinco elementos y
por ltimo realiza una iteracin sobre el arreglo para imprimir en consola
los objetos almacenados.
// Clase GeneracionDeUsuarios
package programacion;
public class GeneracionDeUsuarios {
public static void main(String[] args) {
Usuario[] listadoUsuarios = new Usuario[5];
for (int i=0; i<listadoUsuarios.length; i++) {
int idGenerado = (int)(Math.random() * 1000);
listadoUsuarios[i] = new Usuario(idGenerado);
}
for (int i=0; i<listadoUsuarios.length; i++) {
System.out.println(listadoUsuarios[i]);
}
}
}
// Clase Usuario
package programacion;
public class Usuario {
private int id;
public Usuario(int idUsuario) {
id = idUsuario;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String toString() {
String s = "Usuario - id: " + id;
return s;
}
}
4.1.2- Vector
En la seccin anterior estudiamos los conceptos asociados a los arreglos en
Java y vimos que los mismos son tiles para almacenar varios elementos de
un mismo tipo de dato. Para ello debemos conocer de antemano la cantidad
de elementos que se podrn almacenar en el arreglo. Sin embargo, hay
algunos escenarios en los cuales no sabemos con precisin la cantidad de
elementos que sern almacenados en el arreglo. Una posible solucin a este
problema es crear un arreglo que pueda almacenar un nmero de
elementos mucho mayor a la cantidad de elementos que estimamos que
podemos llegar a guardar. El inconveniente de esta solucin, es que cada
posicin del arreglo ocupa un lugar en memoria, y de esta forma estaremos
ocupando espacio adicional en memoria en forma innecesaria.
Java provee la clase Vector que permite representar arreglos que pueden
aumentar o disminuir la cantidad de elementos posibles a almacenar en
forma dinmica. La clase Vector se encuentra en el paquete java.util y
cada vez que queramos hacer uso de esta clase ser necesario importar
dicho paquete.
Vector nombres = new Vector(5);
La lnea de cdigo anterior crea un objeto de tipo Vector con una capacidad
inicial de cinco elementos. En el caso que hayamos agregado cinco
elementos al vector y agreguemos un elemento adicional, entonces su
capacidad ser duplicada en forma automtica, es decir se incrementar a
diez elementos. Si en un futuro esta capacidad es superada, entonces
nuevamente su capacidad ser duplicada automticamente, en este caso a
veinte elementos. En otras palabras, si utilizamos este constructor su
capacidad inicial ser aquella indicada por medio del parmetro que se
enva en su constructor, y por cada vez que su capacidad sea superada,
entonces la misma ser duplicada en forma automtica. Hay que tener
precaucin en la utilizacin de este constructor especialmente cuando se
debe almacenar una gran cantidad de elementos, ya que en el punto en el
que superemos la capacidad, la misma ser duplicada y por consiguiente se
requerir mayor cantidad de memoria disponible.
Si deseamos tener un mayor control sobre cmo se incrementa la capacidad
del vector cada vez que la misma es superada entonces podemos utilizar el
siguiente constructor:
Vector nombres = new Vector(5, 5);
El constructor anterior recibe dos parmetros: el primero de ellos indica la
capacidad inicial del vector, y el segundo indica cunto debe aumentar la
capacidad por cada vez que se la supere. En el ejemplo anterior, la
capacidad inicial del vector es cinco y por cada vez que la misma sea
superada, entonces ser incrementada de a cinco unidades (5, 10, 15, 20,
25).
Tambin se puede utilizar un tercer constructor que no recibe ningn
parmetro:
Vector nombres = new Vector();
En este caso, la capacidad inicial del vector es diez y ser duplicada por cada
vez que la misma sea superada.
No se deben confundir los conceptos de capacidad y tamao. La
capacidad tiene una relacin con la cantidad de espacio en memoria
reservado por un vector, mientras que el tamao de un vector hace
referencia a la cantidad de elementos almacenados en un momento
determinado.
Sus mtodos
A continuacin, analizaremos los mtodos que provee la clase Vector que
nos permiten manipular objetos de este tipo.
Si deseamos aadir un elemento a un vector podemos utilizar los mtodos
addElement(Object o) o add(Object o):
Vector nombres = new Vector(5, 5);
nombres.add(Juan);
nombres.add(Mara);
nombres.add(Rodrigo);
nombres.addElement(Florencia);
Se pueden utilizar los mtodos addElement() y add() en forma indistinta ya
que proveen la misma funcionalidad. Estos mtodos agregan un elemento
al final del vector.
Si deseamos insertar un elemento en una determinada posicin entonces
podemos hacer uso del mtodo insertElementAt():
nombres.insertElementAt(Daro, 2);
Si utilizamos el mtodo insertElementAt(), entonces debemos enviar un
primer parmetro que representa el objeto que deseamos insertar y un
segundo parmetro que indica la posicin en la cual deseamos insertar el
objeto dentro del vector. A la posicin la debemos indicar mediante un
ndice y el conteo del mismo comienza en cero. En el ejemplo anterior,
agregamos un objeto de tipo String con la cadena de caracteres Daro en
la tercera posicin (ndice 2).
Tambin se puede utilizar en forma indistinta el mtodo add(int index,
Object element):
nombres.add(4, Paula);
A diferencia del mtodo insertElementAt(), este mtodo recibe como
primer parmetro un ndice que hace referencia a la posicin en la que se
desea insertar el objeto, y recibe como segundo parmetro el objeto que se
desea insertar. En el ejemplo anterior, agregamos un objeto de tipo String
con la cadena de caracteres Paula en la quinta posicin (ndice 4).
Cuando se utiliza un ndice para referenciar una posicin especfica para
insertar un elemento en un vector, el mismo debe ser igual o mayor a cero
(el conteo comienza en cero) y menor o igual al tamao del vector.
Recordemos que el tamao de un vector hace referencia a la cantidad de
numeros.add(uno");
numeros.add(dos);
numeros.add(tres);
numeros.add(cuatro);
System.out.println(numeros.elementAt(0));
System.out.println(numeros.elementAt(1));
System.out.println(numeros.get(2));
System.out.println(numeros.get(3));
Las ltimas cuatro sentencias del cdigo anterior imprimen en consola los
elementos del vector correspondientes a los ndices 0, 1, 2 y 3. Si en algn
momento intentamos acceder a un elemento que se encuentra fuera de
rango, obtendremos un error en tiempo de ejecucin. En el ejemplo
anterior, el ltimo ndice vlido es 3; si intentamos utilizar un ndice
superior a este ltimo entonces obtendremos una excepcin de tipo
ArrayIndexOutOfBoundsException.
Al igual que los arreglos, tambin es posible utilizar sentencias iterativas
para manipular los elementos de un objeto de tipo Vector.
Vector numeros = new Vector(5);
numeros.add(uno);
numeros.add(dos);
numeros.add(tres);
numeros.add(cuatro);
for (int i = 0; i<numeros.size(); i++) {
System.out.println(numeros.elementAt(i));
}
Otra forma de acceder a los elementos de un vector es mediante la interface
Enumeration. Para ello, se utilizan las funciones hasMoreElements() y
nextElement() de esta interface. Si invocamos al mtodo elements(), este
ltimo retorna un objeto que implementa la interface Enumeration y en
consecuencia, tiene implementadas las funciones hasMoreElements() y
nextElement(). Estos mtodos permiten recorrer secuencialmente los
elementos de un vector. El mtodo hasMoreElements() retorna un valor
boolean true o false que indica si el vector tiene ms elementos para
recorrer o no. Cuando se llega al ltimo elemento del vector, este mtodo
devuelve un valor boolean false, indicando que no hay ms elementos
para recorrer. El mtodo nextElement() retorna una referencia al prximo
elemento del vector. Para entender mejor estos conceptos, a continuacin
se presenta un cdigo que recorre secuencialmente un vector utilizando
estos mtodos:
Vector numeros = new Vector(5);
numeros.add(uno);
numeros.add(dos);
numeros.add(tres);
numeros.add(cuatro);
Enumeration elementos = numeros.elements();
while (elementos.hasMoreElements()) {
System.out.println(elementos.nextElement());
}
Ventajas
Vectores
desventajas
de
arreglos
Arreglo
Vector
Ventajas
Su estructura es dinmica.
Su tamao puede
incrementarse o reducirse.
Desventajas
Su tamao es fijo y no
puede cambiar.
la salida en
consola es java
la salida en
consola es JAVA
s5
java
Variable de tipo
String
String s6 = s5.toUpperCase();
Objetos en memoria
java
s5
toUpperCase()
Variable de tipo
String
JAVA
s6
Variable de tipo
String
//
//
//
//
true
false
false
false
//
//
//
//
true
true
true
false
// true
// false
Java
";
4.3- Polimorfismo
Cuando declaramos una variable de referencia de un tipo de clase que se
corresponde a una clase base de una jerarqua, dicha variable puede hacer
referencia a cualquier subclase de dicha jerarqua. Esta propiedad se
denomina Polimorfismo.
Si definimos una variable Figura f, dicha variable puede hacer referencia
a objetos de la clase Figura o tambin puede hacer referencia a objetos de la
clase Rectangulo o de la clase Triangulo:
Figura figura = new Figura();
// Suponiendo que la
// clase Figura no
// fuera abstracta
Figura rectangulo = new Rectangulo();
Figura triangulo = new Triangulo();
En todos los casos hemos declarado variables de tipo Figura, pero en el
caso de las variables rectangulo y triangulo, ambas hacen referencia a
una instancia de la clase Rectangulo y una instancia de la clase Triangulo
respectivamente.
En el momento que se declara una variable de un cierto tipo de clase,
cuando se crea efectivamente el objeto usando el operador new, la variable
puede apuntar a cualquier instancia de una subclase de la clase definida en
la variable. Esta propiedad se conoce como Polimorfismo. Tenemos una
variable que apunta a un objeto distinto al que se esperara por el tipo de
dato de la variable.
Cuando se invoca un mtodo desde una variable con una referencia
polifrmica, el mtodo invocado ser aquel que se encuentra definido en la
clase de la referencia polifrmica.
Veamos un ejemplo que explique estos conceptos:
En este ejemplo vamos a usar el mtodo toString(), razn por la cual lo
vamos a redefinir en la clase Rectangulo y Triangulo de la misma forma
que lo hicimos en su momento para la clase Figura.
Mtodo toString() para la clase Rectangulo:
public String toString() {
String s = super.toString() + "Es Cuadrado?: " +
isCuadrado;
return s;
}
package programacion;
public class Polimorfismo {
public static void main(String args[]) {
Figura[] figuras = new Figura[2];
figuras[0] = new Rectangulo("Rectngulo", 4, 4, true);
figuras[1] = new Triangulo("Tringulo", 4, 6,
"Escaleno");
for (int i=0 ; i<figuras.length ; i++) {
Figura figura = figuras[i];
System.out.println("El clculo del rea para la figura "
+ figura.getNombre() + " es igual a "
+ figura.calcularArea());
}
}
}
4.4- Comparacin de
objetos
Para comprender la comparacin de objetos en Java primero debemos
entender algunos conceptos relacionados a la forma en que Java almacena
una variable en memoria. Una variable en Java puede ser primitiva o por
referencia. Ambas nos sirven para manipular informacin, pero difieren en
su complejidad y el manejo que hace la Mquina Virtual de Java para
almacenarlas en memoria.
Cuando declaramos una variable local de tipo primitiva en Java, la misma
es almacenada en un sector de la memoria denominado Stack. Una de las
caractersticas de este sector de la memoria es su rpido acceso. Cada
variable local primitiva declarada, cuenta con su espacio de memoria
reservado en el Stack.
int
int
int
int
a
b
c
d
=
=
=
=
10;
6;
2;
a;
Stack
d
c
b
a
Cuando se trata de objetos, su creacin difiere en cuanto a la forma en la
que se crean variables primitivas, ya que para crear un objeto se debe
primero declarar una variable y luego se debe indicar la construccin de un
objeto que ser referenciado por la variable creada:
Auto a1;
a1;
a2;
a3;
a4;
a1
a2
a3
a4
=
=
=
=
Heap
Instancia de Auto
Ford Fiesta
LAR123
Instancia de Auto
Ford Fiesta
KUS392
Instancia de Auto
Vokswagen Gol
HIJ583
a1
a2
a3
a4
=
=
=
=
// Comparacin 1
if (a1 == a2) {
System.out.println("Las variables a1 y a2 hacen
referencia al mismo objeto");
} else {
System.out.println("Las variables a1 y a2 hacen
referencia a objetos distintos");
}
// Comparacin 2
if (a1 == a3) {
System.out.println("Las variables a1 y a3 hacen
referencia al mismo objeto");
} else {
System.out.println("Las variables a1 y a3 hacen
referencia a objetos distintos");
}
// Comparacin 3
if (a1 == a4) {
System.out.println("Las variables a1 y a4 hacen
referencia al mismo objeto");
} else {
System.out.println("Las variables a1 y a4 hacen
referencia a objetos distintos");
}
En Comparacin 1, se comparan las referencias de las variables a1 y
a2. El resultado de dicha comparacin es false ya que ambas variables
apuntan a distintos objetos. La misma lgica se aplica en Comparacin 2
pero aplicado a las variables a1 y a3. Estas ltimas hacen referencia a
objetos distintos y en consecuencia el resultado de la comparacin es
false. En Comparacin 3 se comparan las referencias de las variables
a1 y a4 y ambas variables referencian al mismo objeto, y por
consiguiente el resultado de la comparacin es true.
Por el momento, el criterio de igualdad que aplicamos es el de considerar
que dos variables de referencia son iguales si ambas referencian al mismo
objeto. Para aplicar este criterio de comparacin se utiliza el operador ==. A
su vez, el operador != es utilizado en sentido inverso, es decir, para
determinar si dos variables de referencia no son iguales. En el caso que las
variables de referencia no sean iguales entonces el operador != retorna
true y en caso que sean iguales retorna false.
Otro criterio de comparacin podra considerar que dos variables de
referencia son iguales, si los objetos a los que referencian son
conceptualmente iguales. Siguiendo con el ejemplo anterior, los
atributos que contiene una instancia de la clase Auto son modelo y
patente. Podramos considerar que dos objetos de tipo Auto son iguales
conceptualmente si son del mismo modelo y tienen la misma patente, pero
a modo de ejemplo, vamos a considerar que dos objetos de tipo Auto son
conceptualmente iguales si ambos tienen definido el mismo modelo.
Siguiendo este criterio, entonces las variables a1 y a3 son las nicas
variables conceptualmente iguales ya que los objetos referenciados por
ambas variables tienen el mismo modelo definido (Ford Fiesta).
Para definir este criterio de igualdad conceptual entre objetos de tipo Auto
debemos redefinir un mtodo especial que tienen todos los objetos
denominado equals(). Este mtodo se encuentra definido en la clase
java.lang.Object, por lo tanto todos los objetos heredan este mtodo, pero
para definir nuestro propio criterio conceptual de igualdad es necesario
redefinir este mtodo con una implementacin acorde a nuestro criterio de
igualdad. A continuacin se redefine el mtodo equals() de la clase Auto:
public boolean equals(Object o) {
if ((o instanceof Auto) &&
(((Auto)o).getModelo().equalsIgnoreCase(this.modelo))
{
return true;
} else {
return false;
}
}
a1
a2
a3
a4
=
=
=
=
// Comparacin 4
if (a1.equals(a2)) {
System.out.println("Las variables a1 y a2 son iguales
conceptualmente");
} else {
System.out.println("Las variables a1 y a2 no son
iguales conceptualmente");
}
// Comparacin 5
if (a1.equals(a3)) {
System.out.println("Las variables a1 y a3 son iguales
conceptualmente");
} else {
System.out.println("Las variables a1 y a3 no son
iguales conceptualmente");
}
// Comparacin 6
if (a1.equals(a4)) {
System.out.println("Las variables a1 y a4 son iguales
conceptualmente");
} else {
System.out.println("Las variables a1 y a4 no son
iguales conceptualmente");
}
En Comparacin 4, se comparan conceptualmente las referencias de las
variables a1 y a2. El resultado de dicha comparacin es false ya que
los objetos referenciados por ambas variables tienen modelos distintos de
autos. En Comparacin 5, se comparan conceptualmente las referencias
de las variables a1 y a3. Ambas variables referencian objetos distintos,
pero tienen el mismo modelo de auto, por lo tanto conceptualmente son
iguales y en consecuencia el valor devuelto por el mtodo equals() es
true. En Comparacin 6, se comparan conceptualmente las referencias
de las variables a1 y a4, pero ambas variables referencian al mismo
objeto y en consecuencia se est comparando conceptualmente al mismo
objeto y en consecuencia el resultado de la comparacin es true.
De acuerdo a lo analizado anteriormente, siempre que queramos verificar la
igualdad entre dos objetos, debemos tener en cuenta si lo que queremos
verificar es si las variables de referencia hacen referencia al mismo objeto
(operador ==), o si los objetos referenciados por ambas variables son
conceptualmente iguales (mtodos equals()).
En este caso, el constructor define dos parmetros del mismo nombre que
las variables de instancia (a y b) Cul es el valor de las variables de
instancia a y b luego de llamar al constructor?
La respuesta es a = 0, y b = 0, porque el compilador est asignando la
variable a que viene por parmetro a la misma variable a que viene por
parmetro, y lo mismo se aplica para la variable b, es decir, en el
constructor nunca hacemos referencia a las variables de instancia, sino que
siempre nos estamos refiriendo a las variables locales.
Este problema de ambigedad se soluciona agregando la palabra clave
"this" antes de las variables a y b, como se muestra a continuacin:
public class Ejemplo {
public int a = 0;//variable de instancia
public int b = 0;//variable de instancia
//constructor con 2 parmetros
public Ejemplo(int a, int b) {
this.a = a;
this.b = b;
}
}
Supongamos que invocamos al constructor de la clase Ejemplo y como
parmetros enviamos los valores 1 y 2. Como resultado de la ejecucin
del constructor, los valores de las variables de instancia son a = 1 y b = 2.
Hay que tener en cuenta que la palabra clave this no puede ser utilizada
desde un mtodo esttico debido a que estos mtodos no se refieren a
ninguna instancia en particular y al usar la palabra clave this
pretenderamos obtener la instancia actual, lo cual es contradictorio.
public class Ejemplo {
int a;
public static void main(String args[]) {
System.ou.println(this.a);//Error de compilacin
}
}
La utilizacin de la palabra clave this se considera una buena prctica de
programacin para evitar ambigedades.
8
Ingrese un divisor entero
4
El resultado de la divisin es: 2
Veamos qu sucede si ingresamos como divisor el valor cero:
Divisin entre dos nmeros enteros
Ingrese un dividendo entero
2
Ingrese un divisor entero
0
Exception in thread "main"
java.lang.ArithmeticException: / by zero
at Division.main(Division.java:18)
Java Result: 1
En consola podemos ver que ha ocurrido una excepcin y la aplicacin ha
terminado abruptamente:
Exception in thread "main"
java.lang.ArithmeticException: / by zero
at Division.main(Division.java:18)
Esta informacin se la conoce como stack trace o rastreo de la pila de
la excepcin. Esta informacin incluye el nombre de la excepcin que ha
ocurrido (java.lang.ArithmeticException) junto a algn mensaje
descriptivo de la misma y la cadena de llamadas a mtodos al momento en
que ocurri la excepcin. En este caso, se intent hacer una divisin por
cero en la siguiente lnea de cdigo y la misma arroj una excepcin:
int cociente = dividendo/divisor;
El
nombre
de
la
excepcin
que
se
obtuvo
es
java.lang.ArithmeticException y se informa que se intent hacer una
divisin por cero (/ by zero). La divisin por cero en el conjunto de los
nmeros enteros es una operacin no permitida, siendo ste el motivo por
el cual obtuvimos la excepcin.
En el cdigo de ejemplo que vimos, el flujo normal de la aplicacin sera
esperar que el usuario siempre ingrese valores enteros vlidos, pero como
vimos, se puede dar la ocasin en la que el usuario ingrese valores no
esperados, dando a producir situaciones anmalas conocidas como
excepciones.
Una aplicacin puede arrojar varios tipos de excepciones. Intentemos
ejecutar la aplicacin e ingresar alguna letra en lugar de un nmero. El
resultado obtenido es el siguiente:
Divisin entre dos nmeros enteros
Ingrese un dividendo entero
a
Exception in thread "main"
java.lang.NumberFormatException: For input string: "a"
at
java.lang.NumberFormatException.forInputString(NumberFo
rmatException.java:48)
at java.lang.Integer.parseInt(Integer.java:449)
at java.lang.Integer.parseInt(Integer.java:499)
at Division.main(Division.java:13)
Java Result: 1
Como podemos ver, la consola nos informa que se ha lanzado una excepcin
de tipo java.lang.NumberFormatException y la aplicacin finaliza
abruptamente. Esto se debe a que la aplicacin espera que siempre se
ingresen nmeros enteros, pero darse la situacin en la que un usuario se
equivoque e ingrese una letra en lugar de un nmero. En dicho caso la
siguiente lnea de cdigo arrojar una excepcin:
int dividendo = Integer.parseInt(br.readLine());
Esto se debe a que la funcin Integer.parseInt() intenta obtener el
nmero entero que representa la cadena de caracteres ingresada, pero si
ingresamos como cadena de caracteres alguna letra, esta funcin no podr
convertir dicha letra en un nmero entero y arroja una excepcin.
controle esta situacin ser ejecutado. Pero para que este modelo funcione,
necesitamos indicarle de alguna forma a la Mquina Virtual Java qu
cdigo se debe ejecutar cuando alguna excepcin en particular ocurre. Para
hacer esta indicacin, se utilizan las palabras claves try y catch.
La palabra clave try se utiliza para definir un bloque de cdigo en donde
alguna excepcin puede ocurrir.
La palabra clave catch se utiliza para capturar alguna excepcin en
particular o grupo de excepciones para luego ejecutar algn bloque de
cdigo.
Analicemos la utilizacin de las palabras claves try y catch siguiendo el
escenario del ejemplo anterior:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Division {
public static void main(String args[]) throws
IOException {
boolean reprocesarCiclo = true;
do {
try {
System.out.println("Divisin entre dos nmeros
enteros");
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
System.out.println("Ingrese un dividendo
entero");
int dividendo = Integer.parseInt(br.readLine());
System.out.println("Ingrese un divisor entero");
int divisor = Integer.parseInt(br.readLine());
int cociente = dividendo/divisor;
System.out.println("El resultado de la divisin
es: " + cociente);
reprocesarCiclo = false;
} catch (ArithmeticException e) {
System.out.println("No se puede dividir por
cero!");
} catch (NumberFormatException e) {
System.out.println("El valor ingresado no es un
nmero entero!");
}
} while (reprocesarCiclo);
30.
31.
32.
33.
System.out.println("Fin de la aplicacin");
34.
}
36. }
import java.io.FileWriter;
import java.io.IOException;
public class EscribirArchivo {
private static FileWriter file;
public static void main(String args[]) {
leerArchivo();
escribirArchivo();
}
public static void leerArchivo() {
try {
file = new FileWriter("test.txt");
} catch (IOException ex) {
System.out.println("Una excepcin ha ocurrido: " +
ex.toString());
}
}
public static void escribirArchivo() {
try {
file.write("Programacin Orientada a Objetos");
file.close();
} catch (IOException ex) {
System.out.println("Una excepcin ha ocurrido: " +
ex.toString());
}
}
}
escribirArchivo()
main()
En este caso, como la lnea de cdigo 22 no forma parte de un bloque de
cdigo try y catch entonces se dice que la excepcin es lanzada hacia
el mtodo previo de la pila de llamadas, en este caso el mtodo main(), y
este ltimo es ahora responsable de manipular la excepcin, que
efectivamente lo hace mediante un bloque de cdigo try y catch. La
misma lgica se aplica para el mtodo leerArchivo(). Si una excepcin de
tipo IOException ocurre durante la ejecucin de este mtodo, entonces
dicha excepcin ser lanzada hacia el mtodo main().
Es importante tener en cuenta el uso de la sentencia throws en la
declaracin de un mtodo para indicar que el mismo puede lanzar
excepciones. De esta forma, si un mtodo a() invoca a otro mtodo b()
cuya declaracin incluye la sentencia throws, entonces el mtodo a()
conoce que puede recibir excepciones desde el mtodo b() y deber estar
preparado para manipularlas.
Para indicar que un mtodo puede lanzar ms de una excepcin, se indican
los distintos tipos de excepciones que se pueden lanzar separados por
coma:
public static void escribirArchivo() throws
FileNotFoundException, InterruptedIOException,
RemoteException {
La declaracin de este mtodo indica que puede arrojar excepciones de tipo
FileNotFoundException, InterruptedIOException y RemoteException.
Antes de que una excepcin pueda ser capturada en algn punto, debe
existir algn cdigo que inicie y lance dicha excepcin. Este lanzamiento
de la excepcin puede estar indicado en nuestro cdigo o en el cdigo de
alguna librera que utilicemos o en las clases que componen los paquetes de
Java. Sin importar quin lanza especficamente la excepcin, lo importante
es saber que para que se inicie el flujo de una excepcin, la misma debe ser
lanzada o arrojada utilizando la sentencia throw (no confundir con la
sentencia throws).
En los ejemplos anteriores, las excepciones eran creadas y lanzadas por
clases de Java. Por ejemplo, cuando evalubamos la siguiente expresin:
Integer.parseInt(br.readLine());
Si la sentencia anterior recibe como parmetro una cadena de caracteres
que no representa un nmero entero, entonces la implementacin del
mtodo parseInt() crea y lanza una excepcin de tipo
NumberFormatException, es decir, la implementacin del mtodo
parseInt() contiene lneas de cdigo que evalan si el parmetro que
recibe se corresponde al de un nmero entero, y en caso contrario crea un
objeto de tipo NumberFormatException que representa la excepcin
producida y la misma es arrojada utilizando la sentencia throw.
A continuacin mostraremos un ejemplo, en donde verifiquemos una
condicin, y en el caso que dicha condicin no se cumpla entonces
lanzaremos una excepcin. Supongamos que a nuestra clase Division que
Object
Throwable
Error
(unchecked)
Exception
RuntimeException
(unchecked)
IOException
(checked)
Excepciones del
programador
(checked)
ClassNotFoundException
IllegalAccessException
InterruptedException
IOException
NamingException
SQLException
TimeoutException
ArithmeticException
ClassCastException
ConcurrentModificationException
IllegalArgumentException
IndexOutOfBoundsException
MissingResourceException
NegativeArraySizeException
NoSuchElementException
NullPointerException
Una vez que tenemos un objeto que representa una excepcin, hay dos
formas de obtener informacin acerca de la misma. Una opcin es por
medio del tipo de excepcin, es decir, por medio de la clase de la cual el
objeto es instancia. Por otro lado, la clase Throwable provee algunos
mtodos que pueden ser tiles para obtener informacin acerca de la
excepcin ocurrida. Como estos mtodos se encuentran definidos en la clase
Throwable, entonces los mismos son heredados por el resto de las clases
del rbol de excepciones. Uno de los mtodos tiles es el mtodo
printStackTrace(), el cual imprime en consola la pila de llamadas de
mtodos al punto en el que se ejecut la excepcin. El mtodo
getMessage() retorna un objeto de tipo String con informacin sobre el
error que dio origen a la excepcin.
}
public String getMensaje() {
return mensaje;
}
}
// Clase CargaSalarios
package salarios;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class CargaSalarios {
private int[] salarios;
BufferedReader br;
private static int LIMITE_CANTIDAD_SALARIOS = 10;
public CargaSalarios() {
br = new BufferedReader(new
InputStreamReader(System.in));
}
public void cargarCantidadDeSalarios() throws IOException {
boolean pedirCargaDeDatos = true;
while (pedirCargaDeDatos) {
System.out.println("\nIngrese la cantidad de salarios
con la que desea operar (entre 1 y 10): ");
try {
int cantidadDeSalarios =
Integer.parseInt(br.readLine());
if (cantidadDeSalarios < 0 || cantidadDeSalarios >
LIMITE_CANTIDAD_SALARIOS) {
ValorIngresadoException ex = new
ValorIngresadoException("La cantidad de
salarios ingresada no es correcta. Debe
ser entre 1 y 10");
throw ex;
}
salarios = new int[cantidadDeSalarios];
pedirCargaDeDatos = false;
} catch (NumberFormatException ex) {
System.out.println("El valor ingresado no es un
nmero entero! Intente ingresar un
nmero entero.");
} catch (ValorIngresadoException ex) {
System.out.println("ValorIngresadoException: " +
ex.getMensaje());
}
}
}
// Clase ValorIngresadoException
package salarios;
public class ValorIngresadoException extends Exception {
private String mensaje = "El valor ingresado no es un valor
esperado!";
public ValorIngresadoException() {
}
public ValorIngresadoException(String mensaje) {
this.mensaje = mensaje;
}
public String getMensaje() {
return mensaje;
}
public void setMensaje(String mensaje) {
this.mensaje = mensaje;
}
}
Bibliografa Lectura 5
Sierra Kathy, Bates Bert, (2008), SCJP Sun Certified Programmer for Java 6
Study Guide (Exam 310-065), EE.UU, Editorial McGraw-Hill.
Bruce Eckel, (2006), Thinking in Java (4a ed.), EE.UU, Editorial Prentice Hall.