Está en la página 1de 62

Mdulo 4

Arreglos, String,
Polimorfismo y
Excepciones en Java

Programacin Orientada a Objetos


De las Heras, Sebastin

4.1- Arreglos y la clase


Vector
4.1.1- Arreglos
El objetivo que perseguiremos en esta seccin ser el aprendizaje de
arreglos en Java. Estudiaremos qu es un arreglo y la sintaxis utilizada
para declarar, crear, inicializar y manipular un arreglo.
Conceptualmente, los arreglos en Java son objetos que pueden
almacenar mltiples variables del mismo tipo de dato. A un arreglo
tambin se lo suele denominar array por su denominacin en ingls. Los
arreglos pueden mantener referencias a tipos de datos primitivos o tipos de
de datos por referencia (objetos), pero el arreglo propiamente dicho es
siempre un objeto.
Los arreglos se clasifican en:
Unidimensionales: almacenan datos indicando un solo ndice
debido a que estn compuestos por una nica dimensin. A estos
tipos de arreglos se los denomina tambin vectores. La siguiente
figura representa un arreglo unidimensional que almacena seis
valores numricos enteros:
ndice
Elementos

0
24

1
12

2
14

3
28

4
9

5
2

Para referenciar al primer elemento de un arreglo, se utiliza el ndice


cero, es decir el conteo del ndice comienza en cero.
Bidimensionales: estn compuestos por dos dimensiones,
razn por la cual para manipularlos se deben indicar dos ndices.
Imaginemos que tenemos un arreglo en el cual los elementos de la
primera dimensin, almacenan a su vez otros arreglos:

Dimensin 1

Dimensin 2

La figura anterior representa un arreglo bidimensional cuya primera


dimensin contiene tres elementos que almacenan nuevos arreglos
de cuatro elementos.

Programacin Orientada a Objetos De las Heras, Sebastin | 2

Filas

Otra representacin ms intuitiva es considerar que los datos de los


arreglos bidimensionales se almacenan en una estructura con forma
de matriz. La siguiente figura representa el mismo arreglo definido
anteriormente pero para su representacin se utiliza una matriz:

0
1
2

0
43
3
6

Columnas
1
2
21
7
67 34
2
56

3
25
67
87

Debido a que la primera dimensin del arreglo contiene tres


elementos, entonces se puede considerar que la matriz que
representa al arreglo contiene tres filas. Tambin se puede
considerar que la matriz contiene cuatro columnas debido a que la
segunda dimensin del arreglo contiene cuatro elementos.
Multidimensionales: tienen ms de dos dimensiones. Para
manipular a este tipo de arreglo se tiene que utilizar un ndice
para cada una de las dimensiones que componen al arreglo. La
siguiente figura representa un ejemplo de un arreglo
multidimensional de tres dimensiones que almacena elementos de
tipo char:
-

La primera dimensin puede almacenar tres elementos. Los


elementos que se almacenan son nuevos arreglos (dimensin
2).

Los arreglos de la segunda dimensin pueden almacenar dos


elementos. Los elementos que se almacenan son nuevos
arreglos (dimensin 3).

Los arreglos de la tercera dimensin pueden almacenar tres


elementos. Se almacenan valores de tipo char.
Dimensin 1

Dimensin 2

Dimensin 3

Debido a que el arreglo representado contiene tres dimensiones,


entonces tambin se lo puede representar mediante la figura de un
cubo como se muestra a continuacin:

Programacin Orientada a Objetos De las Heras, Sebastin | 3

A modo de ejemplo, podemos observar que el elemento que se


encuentra en la posicin [0,1,1] tiene almacenado el valor k. Cuando
indicamos la posicin [0,1,1] hacemos referencia a la primera fila de la
dimensin 1 (ndice 0), la segunda fila de la dimensin 2 (ndice 1) y la
segunda fila de la dimensin 3 (ndice 1). Es importante recordar que el
conteo de los ndices comienza en cero.

Para aprender a utilizar un arreglo, es fundamental conocer los siguientes


conceptos:

Declaracin de un arreglo.

Creacin de un arreglo.

Inicializacin de un arreglo.

Cada uno de estos puntos tiene distintas variantes y estudiaremos las ms


utilizadas.

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.

Programacin Orientada a Objetos De las Heras, Sebastin | 4

Los corchetes se pueden colocar indistintamente a la izquierda o a la


derecha del identificador. En la declaracin del primer arreglo, los
corchetes se colocaron a la izquierda del identificador mientras que para el
segundo arreglo se opt por colocarlos a la derecha del identificador.
Si deseamos declarar un arreglo de ms de una dimensin, entonces se
deben colocar tantos pares de corchetes como nmero de dimensiones
contenga el arreglo. Por ejemplo, declararemos un arreglo de tres
dimensiones que contendr objetos de tipo Persona.
Persona[][][] listadoPersonas;
Tambin se lo podra haber declarado de la siguiente forma:
Persona listadoPersonas[][][];
Por el momento, solamente hemos definido una variable que representa un
arreglo pero no hemos creado ningn objeto. Para crear o construir un
arreglo es necesario invocar al operador new.

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

calificaciones = new int[3];

// Creacin de un
// arreglo unidimensional
// de 3 elementos

Tambin se puede declarar y crear un arreglo en una sola sentencia:


int[] calificaciones = new int[3];
Para crear un arreglo de objetos tambin se procede de la misma manera:
Alumno[] listadoAlumnos = new Alumno[3];
No hay que confundir la utilizacin del operador new. Si nos fijamos en el
ejemplo anterior, cuando construimos el arreglo listadoAlumnos
utilizando el operador new, no estamos invocando al constructor de la
clase Alumno, no estamos creando instancias de tipo Alumno, sino que
estamos construyendo o instanciando un objeto arreglo.

Programacin Orientada a Objetos De las Heras, Sebastin | 5

Tambin es importante tener en cuenta que en la creacin de un arreglo


siempre se debe indicar el tamao del mismo, de lo contrario obtendremos
un error de compilacin. En la siguiente lnea de cdigo, se intenta crear un
arreglo sin especificar su tamao, y por consiguiente obtenemos un error de
compilacin:
Alumno[] listadoAlumnos = new Alumno[]; // No compila
Esto se debe a que la Mquina Virtual Java necesita conocer cunto espacio
de memoria debe reservar para almacenar el arreglo.
Para la construccin de arreglos de ms de una dimensin, se debe seguir la
misma lgica como lo muestra el ejemplo a continuacin:
Persona listadoPersonas[][][]; //
//
//
//

declaracin de un
arreglo de 3
dimensiones de objetos
de tipo Persona

listadoPersonas = new Persona[3][2][2];


En el ejemplo anterior, hemos declarado un arreglo de tipo Persona de tres
dimensiones. Posteriormente hemos construido dicho arreglo e indicamos
que la primera dimensin contendr tres elementos, y la segunda y tercera
dimensiones contendrn dos elementos cada una.

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.

Programacin Orientada a Objetos De las Heras, Sebastin | 6

Supongamos que tenemos definida la clase Persona, y declaramos un


arreglo que contiene elementos de tipo Persona:
Persona[] empleados = new Persona[3];
El objeto empleados puede almacenar elementos que representan
referencias a objetos de tipo Persona, pero hasta el momento solamente
tenemos tres referencias de tipo Persona pero nulas, es decir, no hemos
inicializado cada uno de los elementos de tipo Persona del arreglo. La
siguiente figura es una representacin del arreglo empleados luego de
haber sido declarado y creado:

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.

Programacin Orientada a Objetos De las Heras, Sebastin | 7

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

Programacin Orientada a Objetos De las Heras, Sebastin | 8

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];

Programacin Orientada a Objetos De las Heras, Sebastin | 9

2. for (int a=0 ; a<arregloBytes.length ; a++) {


3.
for (int b=0 ; b<arregloBytes[a].length ; b++) {
4.
for (int c=0 ; c<arregloBytes[a][b].length ; c++) {
5.
arregloBytes[a][b][c] = 2;
6.
}
7.
}
8. }

La lnea de cdigo 2 del ejemplo anterior, recorre los elementos de la


primera dimensin del arreglo, la lnea de cdigo 3 recorre los elementos de
la segunda dimensin y la lnea de cdigo 4 recorre los elementos de la
tercera dimensin.
Tambin se puede declarar, crear e inicializar un arreglo en una nica lnea:
int[] c = {22,8,53,45,2};
La lnea anterior realiza las siguientes acciones:

Declara un arreglo que almacenar valores int cuya variable de


referencia es c.

Construye un arreglo de valores int que podr almacenar cinco


elementos.

Almacena los valores 22, 8, 53, 45 y 2 en el arreglo c.

Es decir, la sentencia de cdigo anterior es equivalente a la siguiente:


int[] c;
c = new int[5];
c[0] = 22;
c[1] = 8;
c[2] = 53;
c[3] = 45;
c[4] = 2;
Ahora veremos otro ejemplo, pero aplicado a un arreglo de objetos:
Persona juan = new Persona(Juan);
Persona[] listadoPersonas = {juan, new
Persona(Lucas), new Persona(Florencia)};

El cdigo anterior realiza las siguientes acciones:

Declara un arreglo que almacenar objetos de tipo Persona cuya


variable de referencia es listadoPersonas.

Construye un arreglo de elementos de tipo Persona de tres


elementos.

Asigna el objeto juan de tipo Persona creado con anterioridad al


primer elemento del arreglo.

Crea dos objetos de tipo Persona y los asigna al segundo y tercer


elementos del arreglo.

Por ltimo, veremos otra alternativa que podemos utilizar para construir e
inicializar un arreglo:

Programacin Orientada a Objetos De las Heras, Sebastin | 10

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;
}
}

Programacin Orientada a Objetos De las Heras, Sebastin | 11

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();

Programacin Orientada a Objetos De las Heras, Sebastin | 12

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

Programacin Orientada a Objetos De las Heras, Sebastin | 13

elementos almacenados. Si hacemos referencia a una posicin inexistente


por
el
momento
entonces
obtendremos
un
error
(ArrayIndexOutOfBoundsException). En el siguiente ejemplo, se intenta
insertar un elemento en la sptima posicin (ndice 6), pero la misma es
inexistente ya que el tamao del vector en el momento que se inserta el
objeto es tres.
import java.util.Vector;
public class EjemplosVector {
public static void main(String[] args) {
Vector numeros = new Vector();
numeros.add(uno);
numeros.add(dos);
numeros.add(tres);
/* Insertamos el objeto siete
* en la sptima posicin(ndice 6) */
numeros.insertElementAt(siete, 6);
}
}
Si ejecutamos el cdigo anterior obtenemos el siguiente error:
Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException: 6 > 3
at java.util.Vector.insertElementAt(Vector.java:551)
at
programacion.EjemplosVector.main(EjemplosVector.java
:15)
Java Result: 1
Si deseamos conocer el tamao de un vector se puede utilizar el mtodo
size() y para conocer su capacidad se puede utilizar el mtodo capacity():
Vector numeros = new Vector(5);
numeros.add(uno);
numeros.add(dos);
numeros.add(tres);
System.out.println(Tamao del vector: +
numeros.size());
System.out.println(Capacidad del vector: +
numeros.capacity());
El cdigo anterior produce la siguiente salida en consola:
Tamao del vector: 3
Capacidad del vector: 5
Esto se debe a que solamente hemos agregado tres elementos al vector y lo
hemos inicializado con una capacidad inicial de cinco.

Programacin Orientada a Objetos De las Heras, Sebastin | 14

Un vector se considera vaco si su tamao es cero, es decir, si no tiene


ningn elemento almacenado. Para saber si un vector est vaco, podemos
obtener su tamao mediante el mtodo size() y verificar si el mismo es igual
a cero; o tambin podemos hacer uso de un mtodo ms directo
denominado isEmpty(). Este mtodo retorna el valor boolean true si el
vector se encuentra vaco, y en caso contrario retorna el valor boolean
false.
Vector numeros = new Vector(5);
/* Por el momento, el vector no contiene
* ningn elemento, entonces est vaco.
* La siguiente sentencia imprime true */
System.out.println(Vector vaco? +
numeros.isEmpty());
numeros.add(uno);
numeros.add(dos);
numeros.add(tres);
/* Se han agregado elementos al vector.
* En consecuencia, la siguiente sentencia
* imprime false */
System.out.println(Vector vacio? +
numeros.isEmpty());
Si deseamos eliminar todos los elementos de un vector podemos utilizar los
mtodos removeAllElements() o clear() en forma indistinta:
Vector numeros = new Vector(5);
numeros.add(uno);
numeros.add(dos);
numeros.add(tres);
System.out.println(Tamao del vector: +
numeros.size()); // Imprime 3
// Se remueven todos los elementos del vector
numeros.removeAllElements();
System.out.println(Tamao del vector: +
numeros.size()); //Imprime 0
Si pretendemos remover algn elemento especfico del vector entonces
podemos utilizar los mtodos removeElement() o remove() enviando
como parmetro el objeto que estamos interesados en remover:
Vector numeros = new Vector(5);
numeros.add(uno);
numeros.add(dos);
numeros.add(tres);
System.out.println(Tamao del vector: +
numeros.size()); // Imprime 3

Programacin Orientada a Objetos De las Heras, Sebastin | 15

/* Se remueve el objeto de tipo String


* con la cadena de caracteres dos */
numeros.removeElement(dos);
System.out.println(Tamao del vector: +
numeros.size()); // Imprime 2
Tambin podemos remover un elemento en particular indicando la posicin
en la que se encuentra el elemento. Para ello se utiliza el mtodo
removeElementAt() y se enva como parmetro el ndice
correspondiente a la posicin en la que se encuentra el objeto que deseamos
remover:
Vector numeros = new Vector(5);
numeros.add(uno);
numeros.add(dos);
numeros.add(tres);
System.out.println(Tamao del vector: +
numeros.size()); // Imprime 3
/* Se remueve el elemento que se encuentra
* en la tercera posicin (ndice 2) */
numeros.removeElementAt(2);
System.out.println(Tamao del vector: +
numeros.size()); // Imprime 2
En el caso que queramos remplazar un elemento del vector por otro,
podemos hacer uso del mtodo setElementAt(). Para utilizarlo, debemos
enviar como parmetros el nuevo objeto que deseamos almacenar y un
ndice que hace referencia a la posicin del objeto que deseamos remplazar.
Vector numeros = new Vector(5);
numeros.add(uno);
numeros.add(dos);
numeros.add(nueve);
numeros.add(cuatro);
/* Remplazamos el objeto que se encuentra
* en la posicin del ndice 2 por el
* objeto String tres */
numeros.setElementAt(tres, 2);
Los mtodos firstElement() y lastElement() devuelven el primer y
ltimo elemento del vector respectivamente:
Vector numeros = new Vector(5);
numeros.add(uno);
numeros.add(dos);
numeros.add(tres);
numeros.add(cuatro);
/* Se imprime el primer elemento del vector,

Programacin Orientada a Objetos De las Heras, Sebastin | 16

* en este caso uno */


System.out.println(numeros.firstElement());
/* Se imprime el ltimo elemento del vector,
* en este caso cuatro */
System.out.println(numeros.lastElement());
Si deseamos conocer el ndice correspondiente a un elemento en particular,
entonces podemos hacer uso del mtodo indexOf(). A este mtodo se le
debe enviar como parmetro el objeto sobre el cual nos interesa conocer su
ndice correspondiente en el vector.
Vector numeros = new Vector(5);
numeros.add(uno);
numeros.add(dos);
numeros.add(tres);
numeros.add(cuatro);
/* Se imprime el ndice correspondiente
* a la posicin en la que se encuentra
* el objeto tres */
System.out.println(numeros.indexOf(tres));
En el ejemplo anterior, si hubiramos enviado como parmetro un objeto
inexistente al mtodo indexOf(), entonces el valor devuelto por el mtodo es
-1.
Para saber si un elemento en particular se encuentra almacenado o no en
un vector, podemos utilizar el mtodo contains(). Este mtodo recibe
como parmetro el objeto del cual se desea conocer su existencia o no
dentro del vector. En caso que el objeto est contenido en el vector,
entonces el mtodo contains() retorna un valor booleano true, y en caso
contrario, retorna un valor booleano false.
Vector numeros = new Vector(5);
numeros.add(uno);
numeros.add(dos);
numeros.add(tres);
numeros.add(cuatro);
/* El objeto tres S existe en el vector,
* en consecuencia se imprime true */
System.out.println(numeros.contains(tres));
/* El objeto ocho NO existe en el vector,
* en consecuencia se imprime false */
System.out.println(numeros.contains(ocho));
Para acceder a los elementos de un vector, se pueden utilizar los mtodos
elementAt() o get() en forma indistinta. Para ello, estos mtodos reciben
como parmetro un ndice que hace referencia a una posicin determinada
del vector y retornan el objeto que se encuentra en dicha posicin.
Vector numeros = new Vector(5);

Programacin Orientada a Objetos De las Heras, Sebastin | 17

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());
}

Programacin Orientada a Objetos De las Heras, Sebastin | 18

En el cdigo anterior, se utiliza la sentencia iterativa while. Mientras se


cumpla la condicin de que haya elementos para recorrer en el vector
numeros entonces se ejecuta el ciclo iterativo, es decir, mientras la
funcin hasMoreElements() retorne el valor true, entonces se ejecutar
un nuevo ciclo del bloque while(). Dentro de este bloque de cdigo, se
utiliza el mtodo nextElement() para obtener una referencia al siguiente
elemento del vector. De esta forma, este mtodo permite avanzar
secuencialmente sobre los elementos de un vector. A medida que
avanzamos, antes de ejecutar un nuevo ciclo, se evala que el vector tenga
ms elementos para recorrer utilizando el mtodo hasMoreElements(). Una
vez que lleguemos al ltimo elemento del vector, el mtodo
hasMoreElements() retornar un valor boolean false debido a que no hay
ms elementos para recorrer, y en consecuencia, la ejecucin del ciclo while
se detendr. Cuando se utilicen estos mtodos hay que tener en cuenta que
el mtodo nextElement() retorna una referencia a un objeto de la clase
Object. Esto quiere decir que en la mayora de los casos ser necesario
aplicar casting a la clase adecuada con la que tengamos que trabajar.

Ventajas
Vectores

desventajas

de

arreglos

Los arreglos y vectores en Java permiten disponer de estructuras de datos


para almacenar elementos que contienen informacin. Dependiendo del
escenario en el que nos encontremos, es conveniente utilizar un arreglo o
una instancia de la clase Vector.
Un arreglo representa una estructura de datos esttica que puede
almacenar un determinado nmero de variables. Estas variables son
almacenadas en una posicin especfica del arreglo. Cuando construimos un
arreglo, se debe especificar la cantidad de variables que se podrn
almacenar.
int[] arreglo = new int[5];
En el ejemplo anterior, se declara un arreglo y en su creacin se reservan
cinco espacios en memoria. Una vez que un arreglo es creado, el tamao del
mismo no puede ser alterado.
A diferencia de un arreglo, un Vector (instancia de la clase Vector) tiene
una estructura de datos dinmica. La capacidad de almacenamiento de un
vector puede cambiar en forma dinmica. Cuando un Vector es
instanciado, el mismo es inicializado con una capacidad inicial, y cuando
esta es superada, la misma es incrementada en forma automtica, e incluso
podemos configurar cmo debe incrementarse la capacidad en caso que sea
necesario. La clase Vector nos ofrece muchos mtodos que nos permiten
manipular un Vector y todos ellos brindan una alternativa ms sencilla para
desarrollar aplicaciones.
Un objeto de la clase Vector utiliza arreglos internamente. La principal
ventaja de un Vector sobre un arreglo es que un Vector puede aumentar su
capacidad en forma automtica; en cambio, un arreglo una vez creado
con un tamao determinado, no se puede modificar, por lo tanto, si en

Programacin Orientada a Objetos De las Heras, Sebastin | 19

el escenario que estamos trabajando, necesitamos una estructura de datos


para almacenar informacin cuyo tamao puede ser cambiante, entonces es
conveniente la utilizacin de la clase Vector.
En el caso que estemos trabajando en un escenario en el que necesitemos
almacenar informacin en una estructura de datos pero la misma tiene un
tamao fijo y no cambiante en el tiempo, entonces es aconsejable utilizar
arreglos. Esto se debe principalmente a que un arreglo tiene mejor
performance que un Vector ya que sus operaciones y el acceso a sus
elementos tienen mejor performance. Los mtodos definidos en la clase
Vector estn basados en operaciones entre objetos y tienen menor eficiencia
en comparacin a los algoritmos utilizados para manipular arreglos. Es
decir, un Vector nos puede ofrecer mayor facilidad para su manipulacin en
comparacin a un arreglo, pero este ltimo tiene mejor performance en
cuantos a sus operaciones. Si la performance del escenario en el que
estamos trabajando es un punto crtico a tener en cuenta, entonces es
recomendable la utilizacin de arreglos en lugar de Vectores.
El siguiente cuadro expone las ventajas y desventajas de Arreglos y
Vectores.
Estructura

Arreglo

Vector

Ventajas

Las operaciones sobre


arreglos tienen mejor
performance que las de un
Vector.

Su estructura es dinmica.
Su tamao puede
incrementarse o reducirse.

Desventajas

Su tamao es fijo y no
puede cambiar.

Define operaciones a nivel


de objetos, por lo tanto son
ms ineficientes que los
algoritmos de los arreglos.

Programacin Orientada a Objetos De las Heras, Sebastin | 20

4.2- Clase String


4.2.1- Utilizacin de la clase String
La manipulacin de texto o cadena de caracteres es una parte fundamental
en la gran mayora de los lenguajes de programacin. En Java, las
cadenas de caracteres son objetos. Para trabajar con estos objetos,
Java provee una clase para tal fin. Dicha clase se llama String y
pertenece al paquete java.lang. Mediante la utilizacin de esta clase
podremos crear instancias que representan cadenas de caracteres.
Al igual que cualquier otro objeto, se puede instanciar un objeto de tipo
String utilizando el operador new como se muestra a continuacin:
String s1 = new String();
La lnea de cdigo anterior crea una instancia de la clase String y se la
asigna a la variable s1. En este caso, la variable s1 representa una cadena
de caracteres vaca. Esto se debe a que en el momento de su inicializacin,
no se envi por parmetro ninguna cadena de caracteres especfica.
Si deseramos inicializar un objeto de tipo String con una cadena de
caracteres en particular, podemos utilizar el constructor de la clase String
que recibe una cadena de texto como parmetro de la siguiente manera:
String s2 = new String(Ejemplo de un objeto String);
La clase String tambin provee otros constructores que permiten crear un
objeto por medio de distintas alternativas. El cdigo de ejemplo siguiente
construye un objeto String utilizando un constructor que recibe un arreglo
de elementos char:
char[] javaArray = {'','J','a','v','a','!'};
String javaString = new String(javaArray);
System.out.println(javaString);
El cdigo anterior imprimir en consola la cadena de caracteres Java!.
La utilizacin de cadena de caracteres es bastante frecuente en la
programacin, y por este motivo, Java nos ofrece una forma ms sencilla de
inicializar un objeto de tipo String.
String s3 = Ejemplo de un objeto String;
La lnea de cdigo anterior tambin crea un objeto de tipo String que
contiene la cadena de caracteres Ejemplo de un objeto String.
Algo importante que debemos conocer acerca de la utilizacin de objetos de
tipo String es que los mismos son inmutables. Esto quiere decir que una
vez que asignamos una cadena de caracteres a un objeto de tipo String,
dicha cadena de caracteres representada por el objeto no podr ser
modificada. Analicemos este concepto mediante un ejemplo:
String s4 = Programacin;

Programacin Orientada a Objetos De las Heras, Sebastin | 21

s4.concat( Orientada a Objetos);


System.out.println(s4 = + s4); //la salida en
//consola es Programacin

En la primera lnea se crea un objeto s4 de tipo String y se le asigna el


valor Programacin. En la siguiente lnea se utiliza el mtodo concat()
con la intencin de concatenar la cadena de caracteres Orientada a
Objetos al objeto s4. En la tercera lnea imprimimos en consola el valor
del objeto s4, pero los resultados muestran que en lugar de imprimir
Programacin Orientada a Objetos, se imprime solamente
Programacin. Esto se debe a la inmutabilidad de los objetos de tipo
String. En el ejemplo anterior, cuando utilizamos el mtodo concat(), este
mtodo devuelve un objeto de tipo String con las cadenas de caracteres
Programacin Orientada a Objetos como resultado de la concatenacin
entre los valores Programacin y Orientada a Objetos pero no hay
ninguna variable que referencie a este nuevo objeto. La variable s4 sigue
referenciando al objeto original con el valor Programacin.
Analicemos este nuevo ejemplo:
String s5 = java;
s5.toUpperCase();
System.out.println(s5 = + s5); // la salida en
// consola es java
El mtodo toUpperCase() devuelve un objeto String cuya cadena de
caracteres se encuentra en mayscula, pero la cadena de caracteres
representada por el objeto s5 permanece inmutable. Este es el motivo por
el cual se imprime la cadena de caracteres java en minscula en lugar de
mayscula cuando imprimimos el valor del objeto s5. Para imprimir la
cadena de caracteres en mayscula, debemos referenciar al objeto String
devuelto por el mtodo toUpperCase() en una variable y luego imprimir
dicha variable:
String s5 = java;
String s6 = s5.toUpperCase();
System.out.println(s5 = + s5); //
//
System.out.println(s6 = + s6) ;//
//

la salida en
consola es java
la salida en
consola es JAVA

Las siguientes figuras describen las sentencias ejecutadas del cdigo


anterior:
String s5 = java;
Objetos en memoria

s5

java

Variable de tipo
String

Programacin Orientada a Objetos De las Heras, Sebastin | 22

String s6 = s5.toUpperCase();
Objetos en memoria

java

s5

toUpperCase()

Variable de tipo
String

JAVA

s6
Variable de tipo
String

Otra consideracin a tener en cuenta de la clase String es que la misma


contiene el modificador final en su declaracin, lo cual implica que no
puede ser derivada.

4.2.2- Mtodos de la clase String


La clase String provee muchos mtodos que pueden ser utilizados para la
manipulacin de cadena de caracteres y son de gran ayuda para los
programadores de aplicaciones. A continuacin analizaremos los mtodos
ms utilizados que provee esta clase.

public char charAt(int index)


Devuelve el carcter que se encuentra en la posicin indicada por la variable
index recibida por parmetro. Los ndices utilizados por la clase String
comienzan en cero.
String java = "Java";
System.out.println(java.charAt(1)); //La salida es a
public String concat(String s)
Devuelve un objeto String compuesto por la unin de la cadena de
caracteres del objeto que invoca el mtodo y la cadena de caracteres del
objeto que se recibe por parmetro.
String lenguaje = "Lenguaje";
System.out.println(lenguaje.concat(" Java"));
Tambin se pueden utilizar los operadores + y += como si se tratara de
un tipo de dato primitivo. La utilizacin de estos operadores sobre un
objeto de tipo String permite tambin concatenar cadenas de caracteres.

Programacin Orientada a Objetos De las Heras, Sebastin | 23

Ejemplo utilizando operador +:


String lenguaje = "Lenguaje";
System.out.println(lenguaje + " Java");
Ejemplo utilizando operador =+:
String lenguaje = "Lenguaje";
lenguaje += " Java";
System.out.println(lenguaje);
public boolean endsWith(String suffix)
Devuelve un valor boolean (true o false) que indica si la cadena de
caracteres del objeto recibido por parmetro (suffix) es sufijo de la cadena
de caracteres del objeto que invoca el mtodo.
String poo = "Programacin Orientada a Objetos";
System.out.println(poo.endsWith("a Objetos")); //true
System.out.println(poo.endsWith("a Objetosss")); //false
public boolean equals(Object anObject)
Devuelve un valor boolean (true o false) que indica si la cadena de
caracteres que representa el objeto que invoca el mtodo es igual a la
cadena de caracteres representada por el objeto recibido por parmetro.
Este mtodo tiene en cuenta la distincin entre minsculas y maysculas.
String JAVA = "JAVA";
String c = "c";
System.out.println(JAVA.equals("JAVA"));
System.out.println(JAVA.equals("java"));
System.out.println(JAVA.equals("jAvA"));
System.out.println(JAVA.equals(c));

//
//
//
//

true
false
false
false

Este mtodo es heredado de la clase java.lang.Object y lo analizaremos con


mayor detalle en el apartado 4.4 de la lectura (Comparacin de Objetos).

public boolean equalsIgnoreCase(String s)


Devuelve un valor boolean (true o false) que indica si la cadena de
caracteres que representa el objeto que invoca el mtodo es igual a la
cadena de caracteres recibida por parmetro. A diferencia del mtodo
equals(), este mtodo no tiene en cuenta la distincin entre minsculas y
maysculas.
String JAVA = "JAVA";
String c = "c";
System.out.println(JAVA.equalsIgnoreCase("JAVA"));
System.out.println(JAVA.equalsIgnoreCase("java"));
System.out.println(JAVA.equalsIgnoreCase("jAvA"));
System.out.println(JAVA.equalsIgnoreCase(c));

//
//
//
//

true
true
true
false

Programacin Orientada a Objetos De las Heras, Sebastin | 24

public int indexOf(int ch)


Devuelve un valor entero que indica la posicin de la primera ocurrencia del
carcter recibido por parmetro. Si no hay ninguna ocurrencia, entonces el
valor devuelto es -1.
String poo = "Programacin Orientada a Objetos";
System.out.println(poo.indexOf('t'));
System.out.println(poo.indexOf('k'));
El cdigo anterior, primero imprime en consola el valor 18, ya que la
primera ocurrencia del carcter t se da en la posicin 18 (la primera
posicin es cero). Luego imprime en consola -1 ya que no hay ninguna
ocurrencia del carcter k en la cadena de caracteres Programacin
Orientada a Objetos.

public int indexOf(String str)


Devuelve un valor entero que indica la posicin de la primera ocurrencia de
la cadena de caracteres recibida por parmetro. Si no hay ninguna
ocurrencia, entonces el valor devuelto es -1.
String poo = "Programacin Orientada a Objetos";
System.out.println(poo.indexOf("Orientada"));
System.out.println(poo.indexOf("No Orientada"));
El cdigo anterior imprime en consola el valor 13, ya que la primera
ocurrencia de la subcadena de caracteres Orientada se da en la posicin
13 (la primera posicin es cero). Luego imprime en consola -1 ya que no
hay ninguna ocurrencia de la subcadena de caracteres No Orientada.

public int length()


Devuelve un entero que indica el largo de la cadena de caracteres, es decir
indica cuntos caracteres contiene la cadena de caracteres del objeto.
String java = "Java";
System.out.println(java.length()); // Imprime el
// valor 4
public String replace(char old, char new)
Este mtodo remplaza todas las ocurrencias del carcter old recibido por
parmetro por el carcter new tambin recibido por parmetro y devuelve
un objeto String como resultado. Este mtodo distingue maysculas y
minsculas.
String JaVa = "JaVa";
System.out.println(JaVa.replace('a', 'A')); //Imprime JAVA

Programacin Orientada a Objetos De las Heras, Sebastin | 25

public boolean startsWith(String prefix)


Devuelve un valor un boolean (true o false) que indica si la cadena de
caracteres del objeto recibido por parmetro (prefix) es prefijo de la cadena
de caracteres del objeto que invoca el mtodo. Este mtodo distingue
maysculas y minsculas.
String poo = "Programacin Orientada a Objetos";
System.out.println(poo.startsWith("Programacin"));
System.out.println(poo.startsWith("Programacin No
Orientada"));

// true
// false

public String substring(int begin)


Este mtodo es utilizado para devolver una subcadena de caracteres que
representa una parte de la cadena de caracteres del objeto sobre el que se
invoca el mtodo. El parmetro recibido indica a la posicin inicial en la
que inicia la subcadena de caracteres a devolver. El ndice comienza en
cero.
String poo = "Programacin Orientada a Objetos";
System.out.println(poo.substring(13));
El cdigo anterior imprime en consola la cadena de caracteres Orientada a
Objetos.

public String substring(int begin, int end)


Este mtodo es utilizado para devolver una cadena de caracteres que
representa una parte de la cadena de caracteres del objeto sobre el que se
invoca el mtodo. A diferencia del mtodo anterior, este ltimo recibe dos
parmetros. El primer parmetro recibido (begin) indica la posicin inicial
en la que inicia la subcadena de caracteres a devolver y el segundo
parmetro recibido (end) indica la posicin final en la que debe terminar la
subcadena de caracteres a devolver. Hay que tener en cuenta que en la
determinacin de la posicin inicial de la subcadena de caracteres, se
considera que la primera posicin comienza en cero, mientras que para la
determinacin de la posicin final de la subcadena de caracteres se
considera que la primera posicin comienza en 1.
String poo = "Programacin Orientada a Objetos";
System.out.println(poo.substring(13,22));
El cdigo anterior imprime en consola la subcadena de caracteres
Orientada.
public String toLowerCase()
Devuelve un objeto String constituido por la cadena de caracteres del objeto
que invoc al mtodo pero con todos sus caracteres en minscula.
String JAVA = "JAVA";
System.out.println(JAVA.toLowerCase()); //Imprime java

Programacin Orientada a Objetos De las Heras, Sebastin | 26

public String toString()


Devuelve un objeto String con la cadena de caracteres que representa el
objeto.
String Java = "Java";
System.out.println(Java.toString()); //Imprime Java
public String toUpperCase()
Devuelve un objeto String constituido por la cadena de caracteres del objeto
que invoc al mtodo pero con todos sus caracteres en mayscula.
String Java = "Java";
System.out.println(JAVA.toUpperCase()); //Imprime JAVA

public String trim()


Devuelve un objeto String compuesto por la cadena de caracteres del objeto
que invoc al mtodo, pero si dicha cadena de caracteres tiene espacios en
blancos tanto al comienzo como al final, entonces los mismos son
removidos.
String lenguajeJava = "
Lenguaje
System.out.println(lenguajeJava.trim());

Java

";

El mtodo anterior imprime en consola la cadena de caracteres


Lenguaje
Java en lugar de
Lenguaje
Java , ya que el mtodo
trim() elimina los espacios en blanco que se encuentran al comienzo y al
final de la cadena de caracteres.

Programacin Orientada a Objetos De las Heras, Sebastin | 27

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;
}

Mtodo toString() para la clase Triangulo:


public String toString() {
String s = super.toString() + "Tipo de tringulo: " +
tipoTriangulo;
return s;
}

Programacin Orientada a Objetos De las Heras, Sebastin | 28

En la siguiente clase definiremos un mtodo main() en el que


declararemos dos variables con referencias polifrmicas e invocaremos al
mtodo toString() para ambas variables.
package programacion;
public class Polimorfismo {
public static void main(String args[]) {
Figura rectangulo = new Rectangulo("Rectngulo", 4, 4,
true);
System.out.println("Datos de la variable rectangulo");
System.out.println(rectangulo.toString());
System.out.println("\n");
Figura triangulo = new Triangulo("Tringulo", 4, 6,
"Escaleno");
System.out.println("Datos de la variable triangulo");
System.out.println(triangulo.toString());
}
}

Si ejecutamos el mtodo main(), obtendremos los siguientes resultados


en consola:
Datos de la variable rectangulo
Nombre: Rectngulo
Alto: 4
Ancho: 4
Es Cuadrado?: true
Datos de la variable triangulo
Nombre: Tringulo
Alto: 4
Ancho: 6
Tipo de tringulo: Escaleno
Como podemos ver, en el caso de la variable rectangulo, cuando hemos
invocado al mtodo toString(), el mtodo ejecutado es el que se encuentra
en la clase Rectangulo porque efectivamente el objeto creado y al que se
hace referencia es una instancia de esta clase. La misma lgica se aplica
para la variable triangulo. Esta variable es de tipo Figura pero hace
referencia a una instancia de la clase Triangulo, en consecuencia, el mtodo
toString() a ejecutar ser el de la clase Triangulo.
Vamos a mencionar otro ejemplo pero esta vez usando el mtodo
calcularArea(). Como bien sabemos, el mtodo calcularArea() es un
mtodo abstracto en la clase Figura, pero tanto en la clase Rectangulo
como en la clase Triangulo, el mtodo ha sido redefinido con su propia
implementacin particular para cada clase.

Programacin Orientada a Objetos De las Heras, Sebastin | 29

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());
}
}
}

En este caso, hemos definido un arreglo de referencias a objetos de tipo


Figura. Nuestro inters en este caso es agregar en este arreglo todo tipo de
figuras sin importar su tipo especfico (rectngulos o tringulos) para luego
recorrer este arreglo y mostrar en pantalla el clculo del rea de las figuras
almacenadas. Para ello, cuando recorremos el arreglo, sabemos que
obtendremos cualquier objeto de tipo Figura, ya sea un Rectangulo o un
Triangulo, pero no nos importa el tipo especfico al que pertenece el objeto
al que se refiere la variable, slo nos interesa saber que estas referencias ya
sean de tipo Rectangulo o Triangulo tienen implementado el mtodo
calcularArea(). Cualquier objeto que obtengamos del arreglo figuras,
ser una instancia de la clase Figura y podremos invocar al mtodo
calcularArea(). La Mquina Virtual de Java determinar en tiempo de
ejecucin la implementacin correspondiente que debe invocar de acuerdo
a la clase a la que pertenece la referencia polifrmica.
En la primera iteracin del ciclo for, estamos trabajando con una variable
que en tiempo de ejecucin hace referencia a una instancia de la clase
Rectangulo, por ende el mtodo calcularArea() que se ejecuta es el que se
corresponde al de la clase Rectangulo.
En la segunda iteracin del ciclo for, estamos trabajando con una variable
que en tiempo de ejecucin hace referencia a una instancia de la clase
Triangulo, en consecuencia, el mtodo calcularArea() que se ejecuta es el
que se corresponde al de la clase Triangulo.
En todos estos casos entra en juego el concepto de Polimorfismo. Se trata
de una propiedad que permite obtener distintas respuestas ante un
mismo mensaje dependiendo de quin reciba el mensaje. En el ejemplo
anterior, el mensaje calcularArea() es siempre el mismo, pero la
respuesta ser distinta si quien recibe el mensaje es una instancia de la
clase Rectangulo o una instancia de la clase Triangulo.
Cuando utilizamos variables con referencias polifrmicas, solamente
podemos invocar aquellos mtodos definidos en la clase base a la que
pertenece la variable. Es decir, si declaramos una variable de la siguiente
forma
Figura figura = new Triangulo();

Programacin Orientada a Objetos De las Heras, Sebastin | 30

La variable figura solamente podr invocar a los mtodos definidos en la


clase Figura. Aunque la variable figura est referenciando a una instancia
de la clase Triangulo, no podr invocar los mtodos definidos en esta
ltima clase. Cualquier intento de invocar un mtodo definido en la
subclase ocasionar un error de compilacin:
Figura figura = new Triangulo();
figura.getTipoTriangulo(); // Error de compilacin!
En tiempo de compilacin, se debe invocar a los mtodos definidos en la
clase base de la variable. Esto se debe a que una variable de tipo Figura
puede referenciar a instancias de las subclases Rectangulo o Triangulo y
hay mtodos que estn definidos en la clase Rectangulo pero no en la clase
Triangulo y viceversa.
Sin embargo, hay una forma de invocar a los mtodos definidos en la clase a
la que la instancia hace referencia. En estos casos se debe realizar un
casting a la clase polifrmica.
Triangulo t = (Triangulo) figura;
t.getTipoTriangulo();
Mediante el empleo de casting, le estamos diciendo al compilador que la
variable figura en realidad se trata de una instancia de la clase Triangulo.
Si la variable figura no hiciera referencia a una instancia de la clase
Triangulo, obtendramos un error en tiempo de ejecucin
(ClassCastException). Una forma de saber la clase a la que pertenece la
instancia referida por una variable es mediante el operador instanceof.
Figura figura = new Triangulo();
if (figura instanceof Triangulo) {
System.out.println("La variable figura hace
referencia a una instancia de
la clase Triangulo");
}
Lo importante a tener en cuenta con respecto al Polimorfismo es que una
variable de cierta clase puede referirse a una subclase. Cuando se invocan
los mtodos sobre dicha variable, solamente pueden invocarse los mtodos
definidos en la clase base. Pero en tiempo de ejecucin, el mtodo invocado
ser el que est definido en la subclase a la que hace referencia.

Programacin Orientada a Objetos De las Heras, Sebastin | 31

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;

Suponiendo las variables anteriores declaradas son locales, cada una de


ellas es almacenada en el Stack. La declaracin de la variable d indica que
se asigne como valor de la misma el valor de la variable a pero esto no
quiere decir que ambas variables compartan el mismo espacio de memoria.
Se crea una copia del valor de la variable a, en este caso 10 y se lo asigna
a la variable d.

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;

Programacin Orientada a Objetos De las Heras, Sebastin | 32

En el ejemplo anterior, se declara nicamente una variable de tipo Auto,


pero por el momento esta variable no referencia a ningn objeto, solamente
contamos con la variable que apunta a una referencia nula. Para que esta
variable referencie a un objeto, se debe primero construir un objeto y luego
asignar este objeto a la variable a1. Para ello, se utiliza el operador new y
el operador de asignacin (=).
a1 = new Auto(Ford Fiesta, LAR123);
En la lnea de cdigo anterior, primero se crea un objeto de tipo Auto
utilizando el operador new y luego dicho objeto es asignado a la variable de
referencia a1, es decir, la variable a1 referencia al objeto creado de tipo
Auto. Una variable de referencia se almacena en el Stack pero el objeto al
que referencia se almacena en un sector de la memoria denominado Heap.
En el ejemplo anterior, una vez creado el objeto, el mismo es almacenado en
el Heap. Este sector de memoria es ms lento en comparacin al sector
de memoria Stack, por lo tanto, por el momento contamos con una variable
de referencia y un objeto referenciado por dicha variable. Una variable de
referencia es una variable que indica mediante una direccin de memoria la
ubicacin donde se encuentra el objeto que referencia.
Auto
Auto
Auto
Auto

a1;
a2;
a3;
a4;

En las lneas de cdigo anteriores, se declaran cuatro variables de referencia


de tipo Auto. Supongamos que la clase Auto tiene definidos los atributos
modelo y patente y su constructor recibe dos variables de tipo String
para inicializar dichos atributos.
1.
2.
3.
4.

a1
a2
a3
a4

=
=
=
=

new Auto("Ford Fiesta", "LAR123");


new Auto("Volkswagen Gol", "HIJ583");
new Auto("Ford Fiesta", "KUS392");
a1;

La lnea de cdigo 1 crea un objeto de tipo Auto y se asigna a la variable


a1. La lnea de cdigo 2 crea un objeto de tipo Auto y se asigna a la
variable a2. La lnea de cdigo 3 crea un objeto de tipo Auto y se asigna a
la variable a3. La lnea de cdigo 4, indica que la referencia indicada por
la variable a1 sea asignada a la variable a4, es decir, se indica que la
variable a4 referencie al mismo objeto referenciado por la variable a1.
La siguiente figura ilustra una representacin de las variables declaradas y
sus respectivas referencias.

Programacin Orientada a Objetos De las Heras, Sebastin | 33

Heap
Instancia de Auto

Ford Fiesta
LAR123
Instancia de Auto

Ford Fiesta
KUS392
Instancia de Auto

Vokswagen Gol
HIJ583

Como se puede ver en la figura, un objeto puede ser referenciado por ms


de una variable.
Luego de comprender los conceptos relacionados a la asignacin y creacin
de objetos en memoria, y siguiendo con el ejemplo anterior, nos podemos
plantear la siguiente pregunta:

Son las variables a1 y a2 iguales?

Son las variables a1 y a3 iguales?

Son las variables a1 y a4 iguales?

Para responder a estas preguntas, en primer lugar debemos tener en cuenta


el criterio que se aplica para definir cundo dos variables son iguales o no.
Un criterio podra considerar que dos variables de referencia son iguales si
ambas referencian al mismo objeto. Si seguimos este criterio, entonces
las nicas variables que son iguales entre s seran las variables a1 y a4,
ya que ambas hacen referencia al mismo objeto y el resto de las variables
referencian a objetos distintos.
El operador == permite aplicar este tipo de comparacin entre dos objetos.
Este operador devuelve como resultado el valor lgico true si ambas
variables referencian al mismo objeto y devuelve el valor lgico false si
ambas variables referencian a objetos distintos. A continuacin se muestra
un ejemplo en el que se hace uso de este operador:
Auto
Auto
Auto
Auto

a1
a2
a3
a4

=
=
=
=

new Auto("Ford Fiesta", "LAR123");


new Auto("Volkswagen Gol", "HIJ583");
new Auto("Ford Fiesta", "KUS392");
a1;

Programacin Orientada a Objetos De las Heras, Sebastin | 34

// 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).

Programacin Orientada a Objetos De las Heras, Sebastin | 35

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;
}
}

El mtodo equals() recibe un objeto como parmetro. Luego se aplica el


operador instanceof para comprobar que el objeto recibido sea una
instancia de la clase Auto para verificar que se comparan objetos del mismo
tipo. A continuacin se compara el modelo del objeto recibido por
parmetro y el modelo del objeto actual y en caso que sean iguales, se
retorna el valor lgico true y en caso contrario se retorna el valor lgico
false.
En el siguiente cdigo, se utiliza el mtodo equals() para comparar las
variables de referencia a1, a2, a3 y a4.
Auto
Auto
Auto
Auto

a1
a2
a3
a4

=
=
=
=

new Auto("Ford Fiesta", "LAR123");


new Auto("Volkswagen Gol", "HIJ583");
new Auto("Ford Fiesta", "KUS392");
a1;

// 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");

Programacin Orientada a Objetos De las Heras, Sebastin | 36

} 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()).

Programacin Orientada a Objetos De las Heras, Sebastin | 37

4.5- Sobrecarga de mtodos


La sobrecarga de un mtodo hace referencia a la definicin de distintas
versiones del mismo mtodo en una clase. Para sobrecargar un mtodo,
debe mantenerse el mismo nombre pero debe modificarse la lista de
parmetros del mismo. No se toma como sobrecarga la diferenciacin
solamente en el tipo de salida del mtodo.
Ejemplos de mtodos sobrecargados:
void ejemplo(int a, String b)
{
.
.
}
int ejemplo(int a)
{
.
.
}
int ejemplo(int a, int b)
{
.
.
}
int ejemplo()
{
.
.
}
Se trata de mtodos distintos pero todos ellos tienen el mismo
nombre. La diferencia que existe entre ellos radica en que tienen distinto
nmero y/o tipo de argumentos en su declaracin.
Algo a tener en cuenta es que los mtodos sobrecargados pueden cambiar el
tipo de retorno y se pueden definir tambin en subclases.
En el momento en el que se invoca a un mtodo sobrecargado, el
compilador busca el mtodo que tenga la definicin que se corresponde con
el nmero y/o tipo de parmetros en la invocacin del mtodo. Si el
compilador no encuentra ningn mtodo que se corresponda con la
invocacin, entonces obtendremos un error de compilacin.
Otro claro ejemplo del uso de mtodos sobrecargados es cuando definimos
distintos constructores para una misma clase.

Programacin Orientada a Objetos De las Heras, Sebastin | 38

4.6- La palabra clave this


La palabra clave this hace referencia a la instancia u objeto actual.
Por medio de ella podemos referirnos a cualquier miembro del objeto
actual.
Veamos a continuacin un ejemplo que permita clarificar este concepto:
En la clase Ejemplo, tenemos un constructor con dos parmetros (int c,
int d) que son asignados a las variables de instancia a y b.
public class Ejemplo {
public int a = 0;
public int b = 0;
//constructor con 2 parmetros
public Ejemplo(int c, int d) {
a = c;
b = d;
}
}
A continuacin vamos a escribir la misma clase Ejemplo pero haciendo
uso de la palabra clave "this":
public class Ejemplo {
public int a = 0;
public int b = 0;
//constructor con 2 parmetros
public Ejemplo(int c, int d) {
this.a = c;
this.b = d;
}
}
Podemos ver que lo nico que cambi en el constructor fue el agregado de
la palabra "this". sta se puede utilizar para evitar ambigedades en el
cdigo.
Veamos el siguiente ejemplo:
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) {
a = a; // variable local
b = b; // variable local
}
}

Programacin Orientada a Objetos De las Heras, Sebastin | 39

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.

Programacin Orientada a Objetos De las Heras, Sebastin | 40

4.7- La palabra clave super


La palabra clave super se utiliza cuando se quiere acceder a los
miembros de la clase padre, desde la clase hija.
Si se redefine un mtodo de la clase padre, en la clase hija, y se quiere
acceder al mtodo de la clase padre, la forma de hacerlo es con la palabra
clave super.
public class EjemploPadre {
public void escribir() {
System.out.println("Estoy en la clase padre");
}
}
public class EjemploHija extends EjemploPadre {
public void escribir() {
System.out.println("Estoy en la clase hija");
}
public static void main(String[] args) {
EjemploHija ejemploHija = new EjemploHija();
ejemploHija.escribir();
}
}
Cuando ejecutamos el mtodo main() de la clase hija, vemos por la
consola el siguiente mensaje:
Estoy en la clase hija
Vemos este mensaje en la consola, porque el mtodo escribir() de la clase
padre, fue sobrescrito en la clase hija.
Para poder ejecutar desde la clase hija el mtodo escribir() de la clase
padre, agregamos la palabra clave super como vemos a continuacin:
public class EjemploHija extends EjemploPadre {
public void escribir() {
super.escribir();//Se utiliza super SIN parntesis.
System.out.println("Estoy en la clase hija");
}
public static void main(String[] args) {
EjemploHija ejemploHija = new EjemploHija();
ejemploHija.escribir();
}
}

Programacin Orientada a Objetos De las Heras, Sebastin | 41

Cuando ejecutamos el mtodo main() de la clase hija, vemos por la


consola el siguiente mensaje:
Estoy en la clase padre
Estoy en la clase hija
Si tenemos en la clase hija una variable de instancia int a=8, y queremos
acceder a una variable de instancia int a=6 que se encuentra en la clase
padre, lo podemos hacer de la siguiente manera:
public class EjemploPadre {
public int a = 6;//variable de instancia
}
public class EjemploHija extends EjemploPadre {
public int a = 8;//variable de instancia
public void escribir() {
System.out.println("El valor de a en la clase padre
es: " + super.a);
System.out.println("El valor de a en la clase hija
es: " + a);
}
public static void main(String[] args) {
EjemploHija ejemploHija = new EjemploHija();
ejemploHija.escribir();
}
}
Luego de ejecutar el mtodo main() de la clase hija, vemos por la consola
el siguiente mensaje:
El valor de a en la clase padre es: 6
El valor de a en la clase hija es: 8

Programacin Orientada a Objetos De las Heras, Sebastin | 42

4.8- Manejo de excepciones


4.8.1- Concepto de excepcin
En los lenguajes de programacin, escribir cdigo que verifique y haga un
correcto manejo de las situaciones anmalas que podra tener una
aplicacin puede resultar tedioso. Sin embargo, la deteccin de posibles
errores y la determinacin de cmo debera reaccionar la aplicacin
ante esos errores es un aspecto fundamental que definir cun robusta y
confiable es la aplicacin. Para ello, Java provee los mecanismos
necesarios para el manejo de eventos anormales.
Definiremos entonces a una excepcin como un evento anormal o
inesperado que ocurre durante la ejecucin de un programa y altera
su flujo normal.
El objetivo del manejo o gestin de excepciones es el de proveer un
contexto acorde para que la aplicacin pueda resolver las situaciones
anmalas de la forma en que nosotros creamos ms conveniente. Para
entender mejor estos conceptos, analicemos el siguiente cdigo de ejemplo:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Division {
public static void main(String args[]) throws IOException {
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);
}
}

El cdigo anterior solicita al usuario el ingreso de dos nmeros enteros para


realizar el clculo de su cociente. Si ejecutamos la aplicacin podemos ver
los siguientes mensajes en la consola:
Divisin entre dos nmeros enteros
Ingrese un dividendo entero

Programacin Orientada a Objetos De las Heras, Sebastin | 43

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"

Programacin Orientada a Objetos De las Heras, Sebastin | 44

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.

Mediante el manejo de excepciones, los desarrolladores pueden


detectar posibles eventos anormales sin tener que escribir demasiados
cdigos e indicar cmo se debe comportar la aplicacin ante estos
eventos. Una excepcin es representada por un objeto que la Mquina
Virtual de Java instancia en tiempo de ejecucin si algn evento
anmalo ha sucedido, permitiendo al programador que intervenga en
dicha situacin si as lo deseare para recuperarse del estado anormal y
evitar que la aplicacin finalice en forma abrupta.

4.8.2- Captura de excepciones


Como bien se mencion anteriormente, el trmino excepcin hace
referencia a un evento anormal que puede alterar el flujo normal de una
aplicacin. Muchas pueden ser las causas que pueden originar una
excepcin: fallas en el hardware, no disponibilidad de recursos, situaciones
no contempladas, errores matemticos, invocacin de un mtodo sobre un
puntero nulo, ndices fuera de rango, entre otros.
Cuando una excepcin ocurre, se dice que la misma ha sido arrojada y el
cdigo responsable de hacer algo con dicha excepcin se denomina gestor
de la excepcin. Se dice que dicho cdigo captura la excepcin
arrojada. De esta forma, la ejecucin del programa se transfiere al
manejador de la excepcin apropiado.
Entonces, por ejemplo, si llamamos a un mtodo que intenta abrir un
archivo pero por algn motivo, ste no puede ser abierto, la ejecucin de
dicho mtodo se detendr y el cdigo que hayamos definido para que

Programacin Orientada a Objetos De las Heras, Sebastin | 45

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. }

Programacin Orientada a Objetos De las Heras, Sebastin | 46

En el ejemplo, el cdigo que se encuentra entre las lneas 11 y 25


constituye una regin de cdigo en donde alguna excepcin puede ocurrir
ya que dicho cdigo se encuentra en un bloque try. Es nuestra forma de
decirle al compilador que en dicho bloque de cdigo puede producirse
alguna excepcin.
El cdigo que se encuentra entre las lneas 26 y 27 se corresponde con
un bloque catch y le indica a la aplicacin qu acciones debe realizar en el
caso que el bloque de cdigo try indicado con anterioridad arroje una
excepcin de tipo ArithmeticException.
El cdigo que se encuentra entre las lneas 28 y 29 se corresponde con
un bloque catch y le indica a la aplicacin qu acciones debe realizar en el
caso que el bloque de cdigo try indicado con anterioridad arroje una
excepcin de tipo NumberFormatException.
Como pudimos ver, cada bloque catch debe especificar entre parntesis
un parmetro que indica el tipo de excepcin que manipular dicho bloque
de cdigo catch. Esto permite trabajar con el objeto que representa la
excepcin que ha ocurrido para obtener mayor informacin de la misma si
as se desea. Cuando ocurre una excepcin en un bloque de cdigo try
entonces inmediatamente se ejecutar el bloque de cdigo catch
correspondiente a la excepcin que ocurri.
Se debe tener en cuenta que los bloques de cdigo catch se deben colocar
inmediatamente despus del bloque de cdigo try. A su vez, si hay varios
bloques de cdigo catch, los mismos deben colocarse consecutivamente,
es decir, no se puede colocar alguna sentencia intermedia entre los bloques
catch.
La ejecucin del cdigo protegido por el bloque try comienza en la lnea
11. Si la aplicacin logra ejecutarse hasta llegar a la lnea 25 sin arrojar
ninguna excepcin, es decir si ningn evento anormal sucede, entonces la
ejecucin de la aplicacin continuar en la lnea 32 hacia abajo. Pero si en
algn momento durante la ejecucin del cdigo que se encuentra entre las
lneas 11 y 25 ocurre alguna excepcin de tipo ArithmeticException,
entonces la ejecucin se transferir directamente a la lnea 26 y en
consecuencia se ejecutar el bloque de cdigo catch correspondiente a la
lnea 27. Una vez que el bloque de cdigo catch finaliza, la ejecucin del
programa contina en la lnea 32.
Algo importante a tener en cuenta tambin es que si por ejemplo, una
excepcin se produce en la lnea 16, entonces el resto de las lneas
sucesivas que se encuentran en el bloque de cdigo try no sern
ejecutadas, es decir, una vez que el control de un programa se encuentra en
un bloque de cdigo catch entonces el control nunca regresar al bloque
de cdigo try para completar su ejecucin.
Uno de los beneficios de este modelo de manejo de excepciones es que el
cdigo necesario para manejar alguna excepcin en particular que pueda
ser arrojada en cualquier seccin de un bloque de cdigo try debe ser
escrita una nica vez. En el ejemplo anterior, una excepcin de tipo
NumberFormatException puede ocurrir tanto en la lnea 16 y 19, pero
sin importar en qu lnea se arroje la excepcin, el mismo bloque de cdigo
catch capturar la excepcin.

Programacin Orientada a Objetos De las Heras, Sebastin | 47

4.8.3- Lanzamiento de excepciones


En la seccin anterior vimos de qu forma se poda escribir un bloque de
cdigo catch para capturar alguna excepcin en particular y determinar
cmo queremos que se comporte el programa ante dicha excepcin. En
algunos casos es apropiado capturar una excepcin en el mismo mtodo en
donde ocurre dicha excepcin mediante los bloques de cdigo try y
catch, pero tambin hay otros casos en los cuales puede resultar ms
conveniente que la excepcin sea capturada por algn mtodo superior o
previo en pila de llamadas (stack trace). Para ello se dice que se debe
lanzar la excepcin hacia los mtodos previos de la pila de llamadas. Para
entender este concepto debemos primero comprender el funcionamiento de
la pila de llamadas de un mtodo.
La pila de llamadas de un mtodo es la cadena de mtodos que el
programa ejecuta para obtener el mtodo actual que est siendo
ejecutado.

Si nuestro programa inicia con el mtodo main(), y dentro de este mtodo


se invoca al mtodo a(), y ste invoca al mtodo b(), y ste ltimo invoca
al mtodo c(), la pila de llamadas es la siguiente:
c()
b()
a()
main()

En la pila de llamadas de mtodos, el ltimo mtodo invocado es el que se


encuentra en lo ms alto del listado, mientras que el primer mtodo
invocado es el que encuentra en lo ms bajo del listado. En este caso, c()
es el mtodo que se estaba ejecutando actualmente, y a medida que
descendemos hacia abajo en el listado observamos los mtodos
previamente invocados. En algunos casos se representa la pila de llamadas
con el orden invertido al expuesto en el ejemplo.
Supongamos ahora que existe la posibilidad de que durante la ejecucin del
mtodo c() ocurra una excepcin. Una de las opciones que tenemos es la
de capturar dicha excepcin mediante los bloques de cdigo try y catch
dentro del mismo mtodo c(). Otra opcin que tenemos es la de lanzar la
excepcin hacia el mtodo que previamente fue invocado, en este caso el
mtodo b() y que sea ste quien tenga la responsabilidad de manipular la
excepcin. Pero para ello, debemos indicarle a la Mquina Virtual Java que
existe la posibilidad de que el mtodo c() pueda arrojar una excepcin.
Esto lo indicamos en la declaracin del mtodo utilizando la palabra clave
throws.
A continuacin, analizaremos un cdigo de ejemplo para que podamos
comprender mejor estos conceptos:

Programacin Orientada a Objetos De las Heras, Sebastin | 48

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());
}
}
}

El cdigo anterior escribe la cadena de caracteres Programacin


Orientada a Objetos en un archivo de texto plano denominado test.txt. Si
dicho archivo no existe, entonces el archivo es creado. Cuando se ejecuta el
mtodo leerArchivo(), la pila de llamadas es la siguiente:
leerArchivo()
main()
Esto indica que primero se ejecut el mtodo main() y luego dentro de
este mtodo se invoca al mtodo leerArchivo(). Una vez que finaliza el
mtodo leerArchivo(), el control vuelve al mtodo main() y este ltimo
invoca ahora al mtodo escribirArchivo(). Cuando se ejecuta el mtodo
escribirArchivo() la pila de llamadas es la siguiente:
escribirArchivo()
main()
Esto indica que el primer mtodo en ser ejecutado fue el mtodo main() y
en algn momento este ltimo invoca al mtodo escribirArchivo().

Programacin Orientada a Objetos De las Heras, Sebastin | 49

Si observamos los mtodos leerArchivo() y escribirArchivo(), ambos


mtodos contienen bloques de cdigo try y catch debido a que las
sentencias utilizadas pueden arrojar excepciones de tipo IOException.
Este tipo de excepcin representa errores relacionados con operaciones de
entrada y salida de datos, como puede ser por ejemplo algn error en el
intento de creacin del archivo test.txt o algn problema mientras se
intenta guardar una cadena de caracteres en el archivo.
En este caso, hemos definido bloques de cdigo try y catch que se
encargan de manipular las excepciones dentro del mtodo donde ha
sucedido la excepcin. A continuacin modificaremos el cdigo para que
veamos de qu forma se puede lanzar la excepcin que ha ocurrido a un
mtodo previo en la pila de llamadas:
import java.io.FileWriter;
import java.io.IOException;
public class EscribirArchivo {
private static FileWriter file;
public static void main(String args[]) {
try {
leerArchivo();
escribirArchivo();
} catch (IOException ex) {
System.out.println("Una excepcin ha ocurrido: " +
ex.toString());
}
}
public static void leerArchivo() throws IOException {
file = new FileWriter("test.txt");
}
public static void escribirArchivo() throws IOException {
file.write("Programacin Orientada a Objetos");//lnea 22
file.close();
}
}

Como bien dijimos con anterioridad, para lanzar una excepcin a un


mtodo previo de la pila de llamadas se debe indicar la posibilidad de que
el mtodo actual puede arrojar una excepcin. Si observamos los mtodos
leerArchivo() y escribirArchivo(), ambos mtodos tienen en su
declaracin la siguiente sentencia:
throws IOException
Esto quiere decir que el conjunto de sentencias de este mtodo tiene la
posibilidad de arrojar una excepcin de tipo IOException.
Entonces si por ejemplo, ocurre una excepcin en la lnea de cdigo 22
mientras se intenta escribir la cadena de caracteres Programacin
Orientada a Objetos en el archivo, la pila de llamadas de la excepcin ser
la siguiente:

Programacin Orientada a Objetos De las Heras, Sebastin | 50

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

Programacin Orientada a Objetos De las Heras, Sebastin | 51

hemos definido en un ejemplo anterior que se encarga de realizar la


divisin entre dos nmeros enteros deseamos incluir como restriccin que
nicamente se puedan dividir nmeros enteros positivos. En otras palabras,
si al momento de ingresar el dividendo y el divisor, se ingresan nmeros
negativos entonces se debe informar que no se podr realizar la divisin
porque el nmero ingresado es un nmero entero negativo. El cdigo
modificado para cumplir con esta restriccin sera el siguiente:
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());
if (dividendo < 0) {
Exception e = new Exception("Dividendo ingresado
negativo!");
throw e;
}
System.out.println("Ingrese un divisor entero");
int divisor = Integer.parseInt(br.readLine());
if (divisor < 0) {
Exception e = new Exception("Divisor ingresado
negativo!");
throw e;
}
int resultado = dividir(dividendo, divisor);
System.out.println("El resultado de la divisin es: "
+ resultado);
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!");
} catch (Exception e) {
System.out.println("Una excepcin ha ocurrido! " +
e);
}
} while (reprocesarCiclo);
System.out.println("Fin de la aplicacin");
}
public static int dividir(int dividendo, int divisor) {

Programacin Orientada a Objetos De las Heras, Sebastin | 52

int cociente = dividendo/divisor;


return cociente;
}
}

En el cdigo anterior, en las lneas 17 y 24 hemos agregado la condicin


de que el dividendo y el divisor ingresados no pueden ser nmeros enteros
negativos. Si se cumple la condicin de que los valores ingresados son
nmeros enteros negativos entonces se crea una instancia de la clase
Exception y luego se lanza la excepcin utilizando la palabra clave throw.
Exception e = new Exception("Dividendo ingresado
negativo!");
throw e;
Si se lanza la excepcin, entonces el bloque de cdigo catch de la lnea
38 captura dicha excepcin y la procesa. En el constructor de la clase
Exception hemos pasado como parmetro una cadena de caracteres con
informacin sobre el error producido. Si ejecutamos el programa e
introducimos un nmero entero negativo, entonces en la consola se nos
informa que una excepcin ha ocurrido y se nos muestra el mensaje de
error que hemos definido en el cdigo:
Divisin entre dos nmeros enteros
Ingrese un dividendo entero
8
Ingrese un divisor entero
-4
Una excepcin ha ocurrido! java.lang.Exception:
Divisor ingresado negativo!
La plataforma de Java dispone de muchas clases para representar
excepciones. Todas estas clases son descendientes de la clase
java.lang.Throwable. Cuando se lanza una excepcin utilizando la
sentencia throw, el nico requerimiento de esta sentencia es que el objeto
que se ha de lanzar debe ser una instancia de la clase Throwable. En el
ejemplo anterior hemos creado una instancia de la clase Exception
(subclase de Throwable) y dicho objeto ha sido lanzado utilizando la
sentencia throw.
No hay que confundir la utilizacin de las palabras claves throws y
throw. La palabra clave throws es utilizada en la declaracin de un
mtodo para indicar las excepciones que pueden ser arrojadas por dicho
mtodo; mientras que la palabra clave throw es utilizada para lanzar en
forma explcita una excepcin.

Programacin Orientada a Objetos De las Heras, Sebastin | 53

4.8.4- Jerarqua de excepciones


Todas las clases que representan excepciones en la plataforma Java son
subclases de la clase java.lang.Exception. A su vez, esta ltima deriva
de la clase java.lang.Throwable y sta de la clase
java.lang.Object.

Object

Throwable

Error
(unchecked)

Exception

RuntimeException
(unchecked)

IOException
(checked)

Excepciones del
programador

(checked)

En la figura anterior se representa la jerarqua de excepciones de la


plataforma Java con sus clases ms representativas. La clase Throwable
tiene dos subclases:
Error: las clases que derivan de Error representan situaciones
anmalas que no son causadas por errores de programacin y
pueden estar asociadas a errores graves de hardware o del
sistema en los cuales el programador nada puede hacer al respecto
ms que ser notificado sobre el error. Un ejemplo de este tipo de
error se genera cuando la Mquina Virtual Java no cuenta con la
memoria suficiente para almacenar algn objeto en memoria y en
consecuencia se produce un error de tipo OutOfMemoryError
(subclase de Error). En general, cuando sucede alguno de estos
tipos de errores (instancias de la clase Error), la aplicacin no estar
en condiciones de manipular el error y recuperarse de la situacin,
motivo por el cual muchas veces no tiene sentido intentar manipular
estos tipos de errores. Tcnicamente, las instancias de la clase Error
no se las considera excepciones porque no derivan de la clase
Exception.

Programacin Orientada a Objetos De las Heras, Sebastin | 54

Exception: una instancia de la clase Exception representa una


situacin anmala excepcional que puede ocurrir y puede ser
manipulada de forma tal que la aplicacin se puede recuperar de
dicho estado anormal. La mayora de los programas lanzan y
capturan objetos que derivan de la clase Exception. Una excepcin
indica que un problema ha ocurrido pero no es tan grave como un
error del sistema.
La plataforma Java define muchas clases descendientes de la clase
Exception. Cada una de estas clases representa algn tipo de tipo de
excepcin en particular que puede requerir por parte del programador la
obligacin de definir algn cdigo que manipule dicha excepcin ya que
de lo contrario la aplicacin no compilara. De acuerdo a la obligacin o
no de definir cdigo que manipule una excepcin, las mismas se
pueden clasificar en verificadas en compilacin (o chequeadas) y no
verificadas en compilacin (o no chequeadas).
Para las excepciones que son verificadas en compilacin es obligatorio
definir un cdigo que haga un tratamiento de la posible excepcin que se
puede producir aunque la misma no llegue nunca a ejecutarse, ya que de lo
contrario el cdigo no compilar. Todas las clases que extienden de
Exception salvo la clase RutimeException son verificadas o chequeadas
(checked).
Como ejemplo, podemos citar las excepciones que son instancias de la clase
IOException. Esta clase deriva de Exception y representa a las excepciones
relacionadas con operaciones de entrada y salida de datos desde diversos
tipos de dispositivos. Si en algn momento utilizamos un mtodo que puede
arrojar este tipo de excepcin, entonces al ser una excepcin verificada,
tenemos la obligacin de definir algn cdigo que haga un tratamiento de la
excepcin, de lo contrario obtendremos un error de compilacin. Por
ejemplo, los mtodos write() y close() de la clase FileWriter pueden
arrojar excepciones de tipo IOException, por lo tanto si no indicamos
ningn tratamiento ante la posibilidad de recibir una excepcin cuando
utilizamos estos mtodos, obtendremos un error de compilacin:
public static void escribirArchivo() {
//file es una instancia de FileWriter
file.write("Programacin Orientada a Objetos");
file.close();
}
En el cdigo anterior, hacemos uso de los mtodos write() y close(),
pero no indicamos ningn tratamiento para la posible excepcin de tipo
IOException que se podra recibir desde estos mtodos, por lo tanto el error
de compilacin que obtenemos es el siguiente:
Exception in thread "main" java.lang.RuntimeException:
Uncompilable source code - unreported exception
java.io.IOException; must be caught or declared to be thrown
at
EscribirArchivo.escribirArchivo(EscribirArchivo.java:22)
at EscribirArchivo.main(EscribirArchivo.java:11)
Java Result: 1

Programacin Orientada a Objetos De las Heras, Sebastin | 55

El error de compilacin informa que se debe indicar algn cdigo que


permita darle un tratamiento a la posible excepcin de tipo IOException
que se puede arrojar. Para definir un tratamiento a la posible excepcin, se
puede definir cdigo que capture la excepcin mediante bloques try y
catch o se puede seguir lanzando la excepcin a un mtodo superior
(sentencia throws en la declaracin del mtodo). Como ejemplo, vamos a
dejar que la excepcin sea manipulada por algn mtodo previo y para ello
vamos a utilizar la sentencia throws en la declaracin del mtodo.
public static void escribirArchivo() throws IOException {

//file es una instancia de FileWriter


file.write("Programacin Orientada a Objetos");
file.close();
}

Debido a que hemos definido un tratamiento para la excepcin verificada o


chequeada de tipo IOException, entonces ahora el mtodo
escribirArchivo() compila en forma satisfactoria.
Por el otro lado, para las excepciones no verificadas o no chequeadas
(unchecked) el compilador no obliga a establecer algn cdigo que defina
un tratamiento a las posibles excepciones que se pueden ejecutar, pero el
programador lo puede hacer si as lo deseare. Las clases que derivan de
RuntimeException y Error representan excepciones no verificadas.
En el siguiente ejemplo, hacemos uso del mtodo parseInt() de la clase
Integer:
Integer.parseInt("a");
Este mtodo puede lanzar una excepcin de tipo NumberFormatException
y se trata de una clase que extiende de RuntimeException, por lo tanto es
una excepcin no verificada. Debido a esto, no es necesario definir un
cdigo que trate a la posible excepcin que se puede llegar a lanzar, pero
podemos hacerlo si deseamos ejecutar alguna accin en particular ante la
ocurrencia de dicha excepcin:
try {
Integer.parseInt("a");
} catch (NumberFormatException e) {
System.out.println("El valor ingresado no es un
nmero entero!");
}
Algunas de las clases ms conocidas que extienden de Exception son:
-

ClassNotFoundException
IllegalAccessException
InterruptedException
IOException
NamingException
SQLException
TimeoutException

Programacin Orientada a Objetos De las Heras, Sebastin | 56

Algunas de las clases ms conocidas que extienden de RuntimeException


son:
-

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.

4.8.5- Excepciones definidas por el


programador
Cuando una excepcin ocurre, un objeto de la clase Exception o de alguna
de sus subclases es instanciada y lanzada. Cuando estamos escribiendo
cdigo y deseamos lanzar una excepcin, podemos crear una instancia de
una clase ya existente como pueden ser aquellas que pertenecen a la
plataforma Java, o podemos definir nuestra propia clase que represente
alguna excepcin. Para ello, lo nico que debemos realizar es definir una
nueva clase y que la misma extienda de la clase Exception.
Para ejemplificar este concepto, supongamos que en la aplicacin anterior
en la cual se intenta realizar la divisin entre dos nmeros enteros no
negativos definimos la siguiente clase que representa una excepcin:
public class NumeroNegativoException extends Exception {
private String mensaje = "Se produjo un error debido a
que el nmero ingresado es un
nmero negativo";
public NumeroNegativoException() {
}
public NumeroNegativoException(String mensaje) {
this.mensaje = mensaje;

Programacin Orientada a Objetos De las Heras, Sebastin | 57

}
public String getMensaje() {
return mensaje;
}
}

Esta excepcin puede ser utilizada para representar un error cuando se


ingresa un nmero con valor negativo. De esta forma, en lugar de lanzar
una excepcin de tipo Exception como lo hacamos anteriormente cuando
se ingresa un valor negativo, podemos modificar el cdigo de la aplicacin
para crear una excepcin de tipo NumeroNegativoException y lanzarla.
int dividendo = Integer.parseInt(br.readLine());
if (dividendo < 0) {
NumeroNegativoException e = new
NumeroNegativoException("Dividendo
ingresado negativo!");
throw e;
}
System.out.println("Ingrese un divisor entero");
int divisor = Integer.parseInt(br.readLine());
if (divisor < 0) {
NumeroNegativoException e = new
NumeroNegativoException("Divisor
ingresado negativo!");
throw e;
}
De esta forma, podemos crear una clase que represente alguna
excepcin con la estructura que a nosotros nos parezca ms conveniente.

Programacin Orientada a Objetos De las Heras, Sebastin | 58

4.9- Aplicaciones en Java


Aplicacin: Carga de salarios
La siguiente aplicacin tiene por objetivo realizar la carga por teclado de
una determinada cantidad de salarios para luego mostrar los valores
ingresados y el promedio de los mismos. En la aplicacin se hace uso de
arreglos y manejo de excepciones.

// 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());
}
}
}

Programacin Orientada a Objetos De las Heras, Sebastin | 59

public void cargarSalarios() throws IOException {


for (int i=0 ; i<salarios.length ; i++) {
boolean pedirCargaDeDatos = true;
while (pedirCargaDeDatos) {
try {
System.out.print("Ingrese el valor del salario " +
(i+1) + ": ");
int salarioIngresado =
Integer.parseInt(br.readLine());
if (salarioIngresado < 0) {
ValorIngresadoException ex = new
ValorIngresadoException("El salario
ingresado no puede ser negativo!");
throw ex;
}
salarios[i] = salarioIngresado;
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());
}
}
}
}
public void mostrarSalarios() {
System.out.println("\nValores ingresados:");
for (int i=0 ; i<salarios.length ; i++) {
System.out.println("Valor salario " + (i+1) + ": " +
salarios[i]);
}
}
public void mostrarSalarioPromedio() {
int sumaSalarios = 0;
for (int i=0 ; i<salarios.length ; i++) {
sumaSalarios += salarios[i];
}
int salarioPromedio = sumaSalarios / salarios.length;
System.out.println("\nSalario promedio: " +
salarioPromedio);
}
public static void main(String[] args) {
CargaSalarios cs = new CargaSalarios();
try {
System.out.println("CARGA DE SALARIOS");
cs.cargarCantidadDeSalarios();
cs.cargarSalarios();
cs.mostrarSalarios();
cs.mostrarSalarioPromedio();
} catch (IOException e) {
System.out.println("Se produjo un error de tipo
IOException: " + e);
}
}
}

Programacin Orientada a Objetos De las Heras, Sebastin | 60

// 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;
}
}

Programacin Orientada a Objetos De las Heras, Sebastin | 61

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.

Frittelli Valerio, (2007), Manual Programador Java (2a ed.),


Argentina.
The Java Tutorials (Oracle), (2011), Learning the Java Language,
Recuperado el 24/01/2013 de
http://download.oracle.com/javase/tutorial/java/TOC.html

Programacin Orientada a Objetos De las Heras, Sebastin | 62