Sie sind auf Seite 1von 59

Capítulo 6

Colecciones de Objetos
y Fachadas en Java

Tema 3 - Material exclusivo prog.III - 1


INET
Casting e instanceof

Casting en tipos primitivos


¾ Consideremos las siguientes declaraciones:
int x = 5;
double y = 3.45;
¾ Consideremos además las siguientes asignaciones:
y = x;
x = y;
• La primer asignación es válida, puesto que x es un int. Como todo
entero es también un real, se lo puede asignar a y que es un double.
• La segunda asignación no es válida, porque y vale 3.45 y no es un
entero.
¾ Hay ocasiones en las cuales se desea asignar a una variable un valor cuyo
tipo no es compatible con el de la variable. Esto puede lograrse haciendo un
casting al momento de realizar la asignación.
x = (int) y;
Tema 3 - Material exclusivo prog.III - 2
INET
Casting e instanceof

Casting en Objetos
¾ Hay circunstancias en las cuales se tiene una referencia correspondiente a
una cierta clase base, pero se sabe que en realidad está referenciando a un
objeto de una clase derivada.
Vehiculo ve = new Auto (“Corsa”,“AAA 403”,15000,“Nafta”,5);
¾ En el contexto anterior, podríamos querer invocar a un método específico de
la clase derivada. Para el ejemplo anterior haríamos así:
String tipoMotor = ve.getTipoMotor();
¾ La asignación anterior es incorrecta pues desde el punto de vista del
compilador ve es un Vehiculo, no un Auto. Por lo tanto no posee un
método getTipoMotor(), el cual es específico de la Clase Auto. Este
problema puede resolverse mediante un casting:
String tipoMotor = ((Auto) ve).getTipoMotor();
// Le indico al compilador que en tiempo de ejecución,
// ve es en realidad un Auto.
Tema 3 - Material exclusivo prog.III - 3
INET
Casting e instanceof

Casting en Objetos (continuación)


¾ En el ejemplo anterior era claro que el objeto referenciado pertenecía a una
Clase derivada. Sin embargo, esto no siempre es evidente en el código, y
puede provocar errores en tiempo de ejecución.
¾ Para evitar confundir el tipo de los Objetos en tiempo de ejecución, Java
posee un operador especial llamado instanceof que permite verificar el
tipo de un Objeto en forma previa a realizarle un casting.
Ejemplo:
Vehiculo ve = new Auto (“Corsa”,“AAA 403”,15000,“Nafta”,5);
if (ve instanceof Vehiculo)
{ String tipoMotor = ((Auto) ve).getTipoMotor();
...
}
Observación: Usamos casting e instanceof solamente cuando queremos
acceder específicamente a miembros que no están definidos en la Clase base.
Tema 3 - Material exclusivo prog.III - 4
INET
Arreglos en Java

¾ Son Colecciones que permiten almacenar (en forma secuencial) un conjunto


acotado de elementos. Sus celdas pueden contener tanto valores de tipos
primitivos como Objetos.

¾ Siempre son dinámicos, en el sentido de que su tamaño es definido en


tiempo de ejecución y, una vez determinado, no puede modificarse.

¾ A su vez, los arreglos en Java son objetos en sí mismos, sin importar que
sus celdas contengan otros objetos o valores de tipos primitivos. Al ser
objetos, cuando los declaramos no hacemos más que declarar una
referencia , para la cual luego se asignará memoria en forma dinámica.

¾ Tanto la sintaxis de los arreglos como la manera de manipularlos son muy


similares a C++ .

Tema 3 - Material exclusivo prog.III - 5


INET
Arreglos en Java

Creación y manipulación
¾ Los arreglos en Java se declaran de la siguiente manera:
tipoCelda nombreArreglo [];
¾ nombreArreglo es simplemente una referencia. El tamaño del arreglo
aún no ha sido determinado. Ello puede hacerse de dos formas:
• mediante el uso de la palabra reservada new.
• mediante el uso de llaves en la propia declaración
Ejemplo:
int tam = (int) (Math.random() * 10);
double miArreglo [] = new double [tam];
int otroArreglo [] = {9, 17, 5, 10, 0};
¾ Los arreglos en Java se indizan desde 0 hasta (tamaño - 1) y una vez
creados se accede a sus celdas usando la misma sintaxis que en C++. Si
no son inicializados explícitamente, sus celdas se cargan con valores nulos.
Tema 3 - Material exclusivo prog.III - 6
INET
Arreglos en Java

Creación y manipulación (continuación)


¾ Al igual que cualquier objeto, un arreglo puede ser un atributo de una Clase:
Ejemplo:
public class ArregloReales
{ private double arre [];
public ArregloReales (int tam)
{ arre = new double [tam] ; }
...
public void desplegar ()
{ for (int i=0 ; i < arre.length ; i++)
System.out.println (arre[i]) ;
}
}
Observación: Todo arreglo en Java posee un atributo length que
contiene su tamaño Si se accede a una celda más allá del mismo, ocurre un
error en tiempo de ejecución.
Tema 3 - Material exclusivo prog.III - 7
INET
Arreglos en Java

Arreglos de Objetos
¾ Se declaran y se crean de igual forma que los arreglos de tipos primitivos.
Sin embargo, la creación de un arreglo de Objetos no construye los objetos
a almacenar en el mismo. Sólo asigna en sus celdas referencias a null.
Ejemplo: String miArreglo [] = new String[3];
0 1 2
miArreglo

¾ Luego cada celda deberá ser instanciada por separado.


Ejemplo: miArreglo

miArreglo[0] = new String(“Hola”); 0 1 2


miArreglo[1] = new String(“Chau”);
miArreglo[2] = new String(“Mundo”);
“Hola” “Mundo”
“Chau”

Tema 3 - Material exclusivo prog.III - 8


INET
Arreglos en Java

Arreglos polimórficos
¾ Son arreglos cuyas celdas contienen referencias correspondientes a una
determinada clase base. Al instanciar cada celda, se la puede crear como un
objeto de la clase base (si la misma es instanciable) o como un objeto de
cualquier clase derivada. Luego se puede recorrer el arreglo e invocar algún
método polimórfico sobre los Objetos almacenados en el mismo.
Ejemplo:
Vehiculo arre [] = new Vehiculo[3] ;
arre[0] = new Auto (“Corsa”,“AAA 403”,15000,“Nafta”,5);
arre[1] = new Camion (“Scania”,“SAP 3047”,25000,550,320.5);
arre[2] = new ConRemolque (“Scania”,“HQ 312”,35000,550,
320.5,750) ;
int max = arre[0].cantidadRuedas();
for (int i=1; i<arre.length; i++)
if (arre[i].cantidadRuedas() > max)
max = arre[i].cantidadRuedas();
Tema 3 - Material exclusivo prog.III - 9
INET
Arreglos en Java

Ejemplo de colección usando arreglos


¾ Suponga que se tiene la
siguiente especificación
en UML para un diccionario
(acotado) de vehículos, el
cual se va a representar
en forma privada mediante
un arreglo con tope.

Tema 3 - Material exclusivo prog.III - 10


INET
Arreglos en Java

Ejemplo de colección usando arreglos (continuación)


public class Vehiculos
{ private Vehiculo [] arreglo;
int tope;
public Vehiculos (int tam)
{ arre = new double [tam] ;
tope = 0;
}
public boolean member (String mat)
{ int i=0; boolean existe = false;
while (i < tope && !existe)
{ if (arreglo[i].getMatricula().equals(mat))
existe = true;
i++;
}
return existe;
}
...
Tema 3 - Material exclusivo prog.III - 11
INET
Arreglos en Java

Ejemplo de colección usando arreglos (continuación)


public void insert (Vehiculo v)
{ arre[tope] = v ;
tope++;
}
public Vehiculo find (String mat)
{ int i=0;
while (!arreglo[i].getMatricula().equals(mat))
i++;
return arreglo[i];
}
public void delete (String mat)
{ arreglo[tope] = v; int i=0;
while (!arreglo[i].getMatricula().equals(mat))
i++;
arreglo[i] = arreglo[tope-1]; tope--;
} Tema 3 - Material exclusivo prog.III - 12
INET
Arreglos en Java

Ejemplo de colección usando arreglos (continuación)


public double promedioPrecios ()
{
double suma = 0.0;
for (int i=0; i < tope; i++)
suma = suma + arreglo[i].getPrecio();
if (tope == 0)
return 0;
else
return (suma/tope);
}
}

Tema 3 - Material exclusivo prog.III - 13


INET
Excepciones

¾ Una excepción es cualquier condición anormal que interrumpe el flujo


normal de ejecución de un programa.
¾ Los errores ocurridos en tiempo de ejecución de un programa constituyen
claros ejemplos de excepciones (más adelante veremos otros ejemplos de
excepciones)
Ejemplos: Consideremos los siguientes errores en tiempo de ejecución:
• El programa pretende hacer una división entre cero.
• Se quiere invocar un método sobre un objeto que está referenciando
a null.
• Se accede a una celda que está más allá del tamaño de un arreglo.

¾ En todos los ejemplos anteriores, el problema no es detectado en la


compilación, sino durante la ejecución. Esto ocasiona que el programa
termine de ejecutarse abruptamente, en forma prematura.

Tema 3 - Material exclusivo prog.III - 14


INET
Excepciones

¾ Excepciones como las anteriores constituyen un tipo especial de Excepción


conocido como Runtime Exception. Las excepciones de este tipo son todos
aquellos errores en tiempo de ejecución que podrían evitarse si se programa
cuidadosamente.

¾ Java provee un mecanismo conocido como Exception Handling (manejo de


excepciones) que permite detectar una excepción, y si es posible, corregir el
problema y permitir que el programa continúe ejecutándose normalmente.

¾ Por ahora vamos a dedicarnos solamente al estudio de las Runtime


Exceptions. Más adelante veremos que la forma de manejar todas las
excepciones en Java es idéntica a la forma de manejar éstas.

Tema 3 - Material exclusivo prog.III - 15


INET
Excepciones

Runtime Exceptions
¾ Consideremos el siguiente ejemplo:
public class PruebaExcepciones
{
public static void main (String [] args)
{
String arre[] = {“Uno”, “Dos”, “Tres”};
for (int i=0; i<20; i++)
System.out.println(arre[i]);
}
}

™ ¿ Hay errores de Compilación en este programa ?


™ ¿ El programa se comportará correctamente ?

Tema 3 - Material exclusivo prog.III - 16


INET
Excepciones

Runtime Exceptions (continuación)


¾ La salida a pantalla desplegada por el programa anterior será:
Uno
Dos
Tres
java.lang.ArrayIndexOutOfBoundsException
at PruebaExcepciones.main (PruebaExcepciones.java:7)
Exception in thread “main” Process exit...

¾ Cuando ocurre un error de ejecución como el anterior, se dice que el


programa lanzó una Runtime Exception. Existen muchas Runtime
Exceptions predefinidas por Java. Por ejemplo, las siguientes:
• ArithmeticException
• NullPointerException
• ArrayIndexOutOfBoundsException
• StringIndexOutOfBoundsException
Tema 3 - Material exclusivo prog.III - 17
INET
Excepciones

Runtime Exceptions (continuación)


¾ Generalmente, no es posible predecir si nuestro programa lanzará una
Runtime Exception o no. En general, si uno programa cuidadosamente,
tales excepciones nunca son lanzadas.
¾ De todas maneras, estudiaremos cómo podemos hacer para detectar estas
excepciones y (si es posible) corregir los problemas asociados con ellas.
Para ello, analizaremos el mecanismo de Exception Handling.
La instrucción try – catch
¾ Es una instrucción especial de Java que permite manejar excepciones (esto
es, detectarlas y tratar de corregir el error asociado). Su sintaxis básica es:
try
{ ... // código “peligroso” }
catch (TipoExcepcion nombre)
{ ... // tratamiento del error }
Tema 3 - Material exclusivo prog.III - 18
INET
Excepciones

La instrucción try – catch (continuación)


¾ Para manejar una Excepción en particular se debe encerrar el código
“peligroso” (el que puede lanzar la excepción) dentro de un bloque try. El
mismo debe contener a la instrucción “sospechosa”, pero también puede
contener otras instrucciones.

¾ A continuación, se debe incluir un bloque catch donde:


• Entre paréntesis se especifica el tipo de excepción a tratar.
• Entre llaves se escribe el código a ejecutarse que permita corregir el
error, o en su defecto, terminar el programa en forma “elegante” .

¾ Modifiquemos la clase PruebaExcepciones presentada antes a efectos de


incorporarle una instrucción try – catch.

Tema 3 - Material exclusivo prog.III - 19


INET
Excepciones

La instrucción try – catch (continuación)


Ejemplo:
public class PruebaExcepciones
{
public static void main (String [] args)
{
String arre[] = {“Uno”, “Dos”, “Tres”};
for (int i=0; i<20; i++)
{ try
{ System.out.println(arre[i]); }
catch (ArrayIndexOutOfBoundsException e)
{ i = 20; }
}
}
}
Tema 3 - Material exclusivo prog.III - 20
INET
Excepciones

La instrucción try – catch (continuación)

¿ Cómo funciona la instrucción try – catch ?


1º) Comienza a ejecutarse el código que está dentro del bloque try.

2º) Si la excepción especificada en los paréntesis del catch es lanzada:


a) Se detiene la ejecución de las instrucciones del bloque try.
b) Luego se ejecutan las instrucciones del bloque catch.
3º) Si dicha excepción no es lanzada, el código del try termina de ejecutarse
normalmente y no se ejecutan las instrucciones del catch.
Observación:
Una instrucción try – catch maneja solamente la excepción indicada
entre los paréntesis del catch. Si otra excepción es lanzada durante la
ejecución del bloque try, la misma no será atrapada.

Tema 3 - Material exclusivo prog.III - 21


INET
Excepciones

La instrucción try – catch (continuación)


¾ En el ejemplo presentado, la excepción especificada fue lanzada, pero
enseguida fue atrapada y procesada dentro del bloque catch. Ahora la
salida desplegada por el programa será simplemente la siguiente:
Uno
Dos
Tres
¾ Incluir una instrucción try – catch en un programa no significa que
necesariamente la excepción va a ser lanzada. Quiere decir que, en caso
de lanzarse, el programa estará preparado para manejarla.
¾ Si en el ejemplo anterior mantenemos el bloque try – catch, pero
modificamos el encabezado del for para no excedernos del rango, la
excepción especificada no será lanzada.
for (int i=0; i<arre.length; i++)

Tema 3 - Material exclusivo prog.III - 22


INET
Excepciones

La instrucción try – catch (continuación)


¾ Para tratar más de una excepción en una instrucción try – catch, podemos
incluir más de un bloque catch, uno por cada excepción que queramos tratar
Ejemplo:
try
{ ...
// código “peligroso”
}
catch (ArrayIndexOutOfBoundsException e)
{ ...
// trato esta excepción, en caso de lanzarse
}
catch (NullPointerException e)
{ ...
// trato esta otra excepción, en caso de lanzarse
}
Tema 3 - Material exclusivo prog.III - 23
INET
Excepciones

La instrucción try – catch (continuación)


¾ En ocasiones, no tenemos interés en preocuparnos por ninguna excepción
en particular. Simplemente queremos que, ante cualquier excepción, el
programa tome una acción genérica.
Ejemplo:
try
{ ...
// código “peligroso”
}
catch (Exception e)
{ ...
// trato esta excepción, sin importar cual sea
}

™ ¿ Porqué creen que este bloque catch atrapa cualquier Excepción ?

Tema 3 - Material exclusivo prog.III - 24


INET
Excepciones

Runtime Exceptions (Moraleja)


¾ Hemos visto que para manejar Excepciones en Java contamos con la
instrucción try – catch. En los ejemplos presentados las hemos usado
solamente para manejar Runtime Exceptions, pero la misma sirve para
manejar cualquier tipo de Excepción (enseguida veremos otras).

¾ De todas maneras, el compilador de Java NO nos obliga a manejar las


Runtime Exceptions, dado que las mismas son en general impredecibles,
pero en caso de que queramos hacerlo, contamos con la instrucción try –
catch.

¾ Si programamos con cuidado y depuramos apropiadamente nuestro código,


tales excepciones no ocurrirán, y no perjudicaremos la claridad del código al
incluir muchos bloques try – catch.

Tema 3 - Material exclusivo prog.III - 25


INET
Excepciones

Throws versus try – catch


¾ A veces no deseamos manejar una Excepción dentro del mismo método en
el cual es lanzada (quizás porque queremos centralizar el manejo de errores
de todo el programa en otra capa).

¾ Por lo tanto, Java nos permite “redireccionar” una Excepción hacia el método
superior. Es decir, el que invoca al método dentro del cual la Excepción es
lanzada.

¾ Esto puede hacerse usando la palabra reservada throws en lugar de atrapar


la Excepción con una instrucción try – catch. Si optamos por esta
alternativa, será el método superior quien deberá hacerse cargo de la
Excepción.

¾ No hay una regla general acerca de dónde conviene manejar las


excepciones. Eso debe definirse concretamente para cada diseño.

Tema 3 - Material exclusivo prog.III - 26


INET
Excepciones

Throws versus try – catch (continuación)


Ejemplo: Mostramos dos alternativas para un mismo método
public void miMetodo(...)
{ ...
try
{ instrucción X;
instrucción Y;
}
catch (TipoException nombre)
{ ... }
}

public void miMetodo(...) throws TipoException


{ ...
instrucción X;
instrucción Y;
}
Tema 3 - Material exclusivo prog.III - 27
INET
Excepciones

Manejando otras Excepciones


¾ Hemos visto que las Runtime Exceptions son todos aquellos errores en
tiempo de ejecución que podrían evitarse si se programa cuidadosamente.
¾ No obstante, existen otras situaciones que podrían provocar la finalización
prematura de un programa y que no dependen del programador, sino de
factores externos al programa en tiempo de ejecución.
Ejemplos:
• El programa pretende abrir un archivo que no existe en el disco.
• El programa pretende enviar información hacia otra máquina en un
momento en el cual la red está caída.
• El programa pretende imprimir un texto en una impresora, pero la misma
no está configurada.

Tema 3 - Material exclusivo prog.III - 28


INET
Excepciones

Manejando otras Excepciones (continuación)


¾ Los ejemplos anteriores también son considerados excepciones, dado que
constituyen situaciones anormales que pueden provocar la finalización
abrupta de la ejecución del programa.

¾ Sin embargo, en Java se considera que tales excepciones son predecibles


y por lo tanto el compilador nos obliga a manejarlas, lo cual hacemos con
la instrucción try – catch tal y como la conocemos.

¾ En resumen, podemos decir que existen dos grandes tipos de Excepciones:


• Las Runtime Exceptions
• Todas las demás
¾ En Java, las Excepciones también son Objetos. Las clases que las
definen están organizadas en una enorme jerarquía de herencia, como
podemos ver en la próxima diapositiva.

Tema 3 - Material exclusivo prog.III - 29


INET
Excepciones

Manejando otras Excepciones (continuación)


¾ Mostramos parte de la jerarquía de Excepciones existentes en Java

Exception


RuntimeException SQLException AWTException IOException

… …
ArithmeticException NullPointerException FileNotFoundException

Referencia: API - java.lang.Exception


Tema 3 - Material exclusivo prog.III - 30
INET
Excepciones

Definiendo nuestras propias Excepciones


¾ En nuestros programas podemos definirnos nuestras propias excepciones
con el fin de manejar situaciones que (en el contexto de nuestros programas)
constituyan errores que deban ser tratados.
¾ Al hacerlo, muchas veces podemos eliminar precondiciones o chequeos
previos que impliquen trabajo adicional para una operación. La idea básica
es: “Trato de resolverlo y si no puedo, lanzo una excepción”
Ejemplo: Supóngase un programa para el manejo de cuentas bancarias
public class MontoInvalidoException extends Exception
{ private String mensaje;
public MontoInvalidoException (String mensaje)
{ this.mensaje = mensaje; }
public String darMensaje()
{ return mensaje; }
}
Tema 3 - Material exclusivo prog.III - 31
INET
Excepciones

Definiendo nuestras propias Excepciones (continuación)


public class CuentaBancaria
{ private double saldo;
...
public void depositar (double monto)
throws MontoInvalidoException
{ if (monto < 0)
{ String msg = “El monto debe ser positivo”;
throw new MontoInvalidoException(msg);
// creo y lanzo una nueva Excepción
}
saldo = saldo + monto;
}
}
Observación: Cualquiera que invoque al método depositar, deberá
manejar nuestra MontoInvalidoException
Tema 3 - Material exclusivo prog.III - 32
INET
Colecciones de Objetos

¾ Hasta el momento, la única estructura que conocemos en Java para


implementar una colección de objetos es el arreglo (estructura acotada)

¾ Para implementar colecciones no acotadas, Java provee un paquete


predefinido llamado java.util, el cual contiene clases predefinidas que
implementan colecciones no acotadas de objetos.

¾ Esto significa que no tenemos que programar nuestras propias


estructuras cuando queramos implementar colecciones no acotadas. En
lugar de eso utilizaremos las colecciones predefinidas por Java.
¾ Las colecciones del paquete java.util siempre son polimórficas, dado
que permiten almacenar cualquier tipo de Objeto. Desde la versión 1.5 de
java, al declararlas es posible indicar el tipo concreto de los objetos a
guardar en ellas mediante < >.

Tema 3 - Material exclusivo prog.III - 33


INET
Colecciones de Objetos

Algunas clases predefinidas del paquete java.util


¾ Clase ArrayList <TipoElem>
• Esta clase implementa una colección que internamente utiliza una
estructura de Arreglo Dinámico Redimensionable para almacenar los
elementos.

• Las operaciones de acceso a elementos se realizan en O(1) peor caso


(son muy eficientes, dado que acceden directamente a la posición dada).

• Sin embargo, las operaciones de inserción y borrado potencialmente


son ineficientes (se realizan en O(n) peor caso) dado que en ocasiones
requieren redimensionar el arreglo.

Observación: Al usar ArrayList NO usamos la sintaxis usual de arreglos


porque los mismos son usados internamente por la clase. Nos manejamos
simplemente con los métodos provistos por la clase (nada de corchetes [ ]).
Tema 3 - Material exclusivo prog.III - 34
INET
Colecciones de Objetos

Algunas clases predefinidas del paquete java.util (cont.)


¾ Clase LinkedList <TipoElem>
• Esta clase internamente utiliza una estructura de Lista Doblemente
Encadenada con Puntero al Principio y al Final para almacenar los
elementos.

• Las operaciones principales (búsqueda, inserción, borrado) se


realizan en O(n) peor caso (son medianamente eficientes, dado que
requieren recorrer nodo a nodo los elementos hasta llegar a la posición
deseada). En una lista no existe el concepto de redimensionamiento.

Observación: Al utilizar LinkedList NO usamos ninguna sintaxis para


listas encadenadas porque las mismas son usadas internamente por la clase.
Nos manejamos simplemente con los métodos provistos por la clase. De hecho,
NO existe en Java una notación para listas similar a la de C++ (nada de flechas
ni de asteriscos) dado que no existe notación de punteros en Java.
Tema 3 - Material exclusivo prog.III - 35
INET
Colecciones de Objetos

Algunas clases predefinidas del paquete java.util (cont.)


¾ Clase Hashtable <TipoKey,TipoElem>
• Esta clase implementa una colección que internamente utiliza una
estructura de Hash para almacenar los elementos.

• Las operaciones principales (búsqueda, inserción, borrado) se


realizan en O(1) caso promedio (son muy eficientes).

• Las claves utilizadas deben ser objetos que implementen los métodos
hashCode() y equals() apropiadamente. Estos métodos están
originalmente definidos en la clase Object y existen clases predefinidas
que los sobre-escriben (Por ejemplo, la clase String).

Observación: Al utilizar Hashtable debemos manejarnos simplemente con los


métodos provistos por la clase, de igual modo que en toda colección
predefinida. La función de dispersión ya viene predefinida.
Tema 3 - Material exclusivo prog.III - 36
INET
Colecciones de Objetos

Algunas clases predefinidas del paquete java.util (cont.)


¾ Clase TreeMap <TipoKey,TipoElem>
• Esta clase implementa una colección que internamente utiliza un Arbol
binario de Búsqueda Balanceado como estructura para almacenar los
elementos según el orden de sus claves.

• Las operaciones principales (búsqueda, inserción, borrado) se


realizan en O( log(n) ) caso promedio (son bastante eficientes).

• Las claves utilizadas deben ser objetos que implementen el método


compareTo() apropiadamente. Dicho método está originalmente
definido en la interface Comparable de Java y existen clases
predefinidas que lo implementan (Por ejemplo, la clase String). De
este modo, las claves utilizadas poseen una relación de orden.

Tema 3 - Material exclusivo prog.III - 37


INET
Colecciones de Objetos

Algunos métodos de LinkedList y ArrayList


¾ boolean add (TipoElem o)
// inserta el objeto recibido al final de la colección. Siempre retorna true.

¾ TipoElem get (int index)


// retorna el objeto almacenado en la posición dada por el índice. Si no
// existe dicha posición en la colección, el método lanza una excepción.

¾ TipoElem remove (int index)


// elimina el objeto almacenado en la posición dada por el índice y baja un
// lugar a todos los objetos posteriores en la colección. Si no existe dicha
// posición en la secuencia, el método lanza una excepción.

¾ int size()
// retorna la cantidad de objetos almacenados en la colección (las
// posiciones dentro de la secuencia se numeran a partir de cero).

Tema 3 - Material exclusivo prog.III - 38


INET
Colecciones de Objetos

Algunos métodos de Hashtable y TreeMap


¾ TipoElem put (TipoKey key, TipoElem value)
// inserta en la colección al objeto value asignándole la clave key. Si ya
// había otro objeto con esa clave, el mismo es retornado y suplantado.

¾ TipoElem get (TipoKey key)


// retorna el objeto identificado por la clave recibida. Si no había ninguno en
// la colección, o el que había era nulo, el método retorna null.

¾ boolean containsKey (TipoKey key)


// determina si hay algún objeto en la colección identificado por la clave
// recibida.

¾ TipoElem remove (TipoKey key)


// elimina de la colección al objeto identificado por la clave recibida y además
// lo devuelve. Si no había un objeto con esa clave, el método no hace nada.

Tema 3 - Material exclusivo prog.III - 39


INET
Colecciones de Objetos

Iteradores
¾ Para recorrer todos los elementos de una Secuencia, podemos hacerlo
fácilmente utilizando for, dado que los elementos se ubican linealmente.
¾ De hecho, desde java 1.5 se introdujo una variante al for tradicional que
permite iterar con facilidad los elementos de un array o de cualquier
secuencia.
Ejemplo:
Vehiculo arre[] = new Vehiculo[3];
arre[0] = new Auto (...);
arre[1] = new Camion (...);
arre[2] = new ConRemolque (...);
for (Vehiculo elem: arre)
// equivalente a for (int i=0; i<arre.length; i++)
System.out.println (elem.getMatricula());
// equivalente a arre[i].getMatricula();
Tema 3 - Material exclusivo prog.III - 40
INET
Colecciones de Objetos

Iteradores (continuación)
¾ Sin embargo, para recorrer los elementos de una colección que guarda los
elementos en una estructura no lineal (un árbol o un hash) lo anterior no es
posible (al menos no en forma directa), dado que el almacenamiento no es
secuencial.
¾ Por esta razón es que las colecciones del paquete java.util poseen
iteradores asociados. Los iteradores son objetos que proveen métodos para
poder recorrer todos los elementos de la colección sin necesidad de conocer
la estructura interna en la cual se almacenan. Los métodos son:
™ public boolean hasNext()
// determina si quedan elementos por visitar en la colección.
™ public Object next()
// retorna el próximo elemento a visitar en la colección.

Tema 3 - Material exclusivo prog.III - 41


INET
Arreglos en Java

Ejemplo de colección usando una estructura no acotada


¾ Suponga que se tiene la
siguiente especificación
en UML para un diccionario
(acotado) de vehículos, el
cual se va a representar
en forma privada mediante
una estructura de hash.

Tema 3 - Material exclusivo prog.III - 42


INET
Colecciones de Objetos

Ejemplo de colección usando una estructura no acotada (cont.)


public Vehiculos ()
{ tabla = new Hashtable <String,Vehiculo> (); }
public boolean member (String mat)
{ return tabla.containsKey(mat); }
public Vehiculo find (String mat)
{ return tabla.get(mat); }
public void insert (Vehiculo v)
{ String mat = v.getMatricula();
tabla.put(mat,v);
}
public void delete (String mat)
{ tabla.remove(v); }

Tema 3 - Material exclusivo prog.III - 43


INET
Colecciones de Objetos

Ejemplo de colección usando una estructura no acotada (cont.)


public double promedioPrecios()
{ // obtengo el iterador de la estructura de hash
Iterator <Vehiculo> iter = tabla.values().iterator();
double suma = 0.0;
// recorro los Vehículos a través del iterador
while (iter.hasNext())
{ Vehiculo ve = iter.next();
suma = suma + ve.getPrecio();
}
// calculo el promedio
if (tabla.size() > 0)
return (suma / tabla.size());
else
return 0.0;
}
Tema 3 - Material exclusivo prog.III - 44
INET
Colecciones de Objetos

Ejemplo de colección usando una estructura no acotada


¾ Observación: Nótese que en Java, las colecciones de tipo Hashtable,
Treemap, ArrayList y LinkedList ya traen implementadas sus propias
operaciones básicas. Por esta razón es que la implementación se simplifica
enormemente.
En el ejemplo anterior, obsérvese que para manipular la estructura de hash
(hashtable) en ningún momento fue necesario manipular directamente las
cubetas del hash ni trabajar directamente con la función de dispersión. Todo
eso fue realizado en forma interna a la clase Hashtable.
En resumen, en Java no tenemos que programar desde cero las estructuras
de datos para nuestras colecciones de objetos no acotadas. Las mismas ya
vienen predefinidas con el lenguaje y con sus operaciones básicas ya
implementadas para que las podamos usar.

Tema 3 - Material exclusivo prog.III - 45


INET
Static

¾ Hay ocasiones en las cuales se desea que un determinado atributo o


método de una clase sea compartido por todas las instancias de esa clase.
Ejemplo:
Para una cierta clase podríamos querer tener un contador de la
cantidad de instancias que han sido creadas para la clase.
¾ Lo anterior puede lograrse etiquetando al miembro (atributo o método) en
cuestión mediante la palabra reservada static.
¾ Un miembro etiquetado como static no está asociado a ninguna instancia de
la clase en particular, sino que es accesible desde todas las instancias de la
clase. Comúnmente se dice que los miembros estáticos pertenecen a la
clase en lugar de a los objetos.
¾ Solamente podemos declarar como static a los atributos y a los métodos de
una clase. No podemos declarar parámetros ni variables locales a métodos
como static.

Tema 3 - Material exclusivo prog.III - 46


INET
Static

Atributos Static
Ejemplo: Presentamos una clase con un contador de la cantidad de
instancias que han sido creadas para la clase.
public class Producto
{
private long codigo;
private double precio;
private static int contador;
public Producto (long codigo, double precio)
{
this.codigo = codigo;
this.precio = precio;
contador++;
}
...
}
Tema 3 - Material exclusivo prog.III - 47
INET
Static

Atributos Static (continuación)


¾ Creamos ahora dos instancias de la clase Producto presentada en el
ejemplo anterior:
Producto prod1 = new Producto(1573, 220.50);
// el contador de la clase queda con el valor 1
Producto prod2 = new Producto(8832, 562.75);
// el contador de la clase queda con el valor 2
¾ Cada instancia de la clase Producto posee sus propios atributos código y
precio, pero el atributo contador no pertenece a ninguno de ellos, sino
que pertenece a la clase.

codigo codigo
contador prod2
prod1 1573 8832
2
220.50 562.75
precio precio
Tema 3 - Material exclusivo prog.III - 48
INET
Static

Métodos Static
Ejemplo: Le agregamos un método estático a la clase Producto
public class Producto
{
private long codigo;
private double precio; ¿ Puedo acceder a un
private static int contador; atributo static desde
... un método común ?

public long getCodigo() ¿ Puedo acceder a un


{ return codigo; } atributo común desde
un método static ?
public double getPrecio()
{ return precio; }
public static int cantInstancias()
{ return contador; }
}
Tema 3 - Material exclusivo prog.III - 49
INET
Static

Métodos Static (continuación)


¾ A diferencia de los métodos comunes, que se invocan a través del nombre
de un objeto, los métodos estáticos se invocan a través del nombre de la
clase. Veamos un ejemplo:
// invocamos métodos comunes
long cod1 = prod1.getCodigo(); // retorna 1573
long cod2 = prod2.getCodigo(); // retorna 8832
double pre1 = prod1.getPrecio(); // retorna 220.50
double pre2 = prod2.getPrecio(); // retorna 562.75
// invocamos el método estático
int count = Producto.cantInstancias(); // retorna 2

¾ No es la primera vez que vemos invocaciones de este tipo. Por ejemplo,


Math.random() o System.out.println() son invocaciones a métodos
estáticos.

Tema 3 - Material exclusivo prog.III - 50


INET
Singleton

¾ Hay ciertas ocasiones en Orientación a Objetos en las cuales se desea tener


una única instancia de una determinada clase y que la misma sea accedida
fácilmente desde cualquier punto dentro de la aplicación. Por ejemplo:
™ Queremos tener una única instancia de la clase que se conecta con una
base de datos.
™ Queremos tener una única instancia de la clase que se comunica con el
programa servidor de nuestra aplicación.
¾ Lo anterior es fácilmente realizable en Java mediante la utilización de un
mecanismo popularmente conocido como Singleton. Dicho mecanismo no
es más que una forma ingeniosa de programar nuestra clase para
garantizar la existencia de una única instancia de ella.

Nota: Formalmente hablando, Singleton es en realidad un Patrón de Diseño. Los


patrones de diseño son descripciones de soluciones pre-establecidas a problemas que se
repiten una y otra vez en Orientación a Objetos. A lo largo de la evolución de la P.O.O
muchos desarrolladores han ido inventando y documentando Patrones en libros o tutoriales
para que otros desarrolladores puedan aprenderlos y utilizarlos en sus propios diseños.

Tema 3 - Material exclusivo prog.III - 51


INET
Singleton

Ejemplo: Presentamos una clase implementada de forma tal que aplica el


mecanismo Singleton.
public class MiClase
{
private static MiClase instancia;
// otros atributos, pueden ser comunes o estáticos
private MiClase()
{ ... }
public static MiClase getInstancia()
{
if (instancia == null)
instancia = new MiClase();
return instancia;
}
...
// otros métodos, pueden ser comunes o estáticos
} Tema 3 - Material exclusivo prog.III - 52
INET
Singleton

¾ Veamos una descripción del ejemplo anterior:


• Método constructor: Dado que no queremos que se puedan crear múltiples
instancias de la clase, etiquetamos el método constructor como privado. De
este modo no podrá ser invocado desde fuera de la clase y por lo tanto no
se podrán crear múltiples instancias de la misma.

• Atributo instancia: Necesitamos tener alguna referencia a la única


instancia que existirá de la clase. La declaramos privada a efectos de evitar
un manejo descuidado de la misma desde fuera de la clase.

• Método getInstancia(): Debemos tener algún método que permita


retornar la única instancia de la clase a quien la solicite. Lo declaramos
static para que sea fácilmente invocable (a través del nombre de la clase)
desde cualquier lugar de nuestra aplicación. La primera vez que sea
invocado, creará la instancia y la retornará. En sucesivas invocaciones,
solamente la retornará, garantizando así su unicidad.

Tema 3 - Material exclusivo prog.III - 53


INET
Fachadas

¾ Ya sabemos que una Fachada es una clase que encapsula el acceso a la


capa lógica. Dentro de una fachada, usualmente colocamos las distintas
colecciones de objetos como atributos. Los métodos de las fachadas son
aquellos que permiten resolver los casos de uso del sistema.
¾ Por ejemplo, imaginemos que contamos con la siguiente fachada para un
sistema de manejo de vehículos como los vistos en ejemplos anteriores:

Tema 3 - Material exclusivo prog.III - 54


INET
Fachadas

¾ En esta fachada, el único atributo que tenemos es un diccionario que


almacena a todos los vehículos. Hemos colocado solamente a esa colección
como atributo porque en el sistema de este ejemplo solamente estamos
trabajando con vehículos. Si además trabajásemos con otros objetos, quizás
tendríamos que tener alguna otra colección más como atributo.
¾ Los métodos que colocamos en esta fachada son los necesarios para
resolver los siguientes casos de uso:
• Poner un nuevo vehículo a la venta.
• Quitar un vehículo de la venta.
• Obtener el promedio de precios de todos los vehículos del sistema.
¾ Recordar que los casos de uso se definen durante el análisis, a partir del
documento de requerimientos. Los métodos de la fachada se definen
durante el diseño, luego de haber realizado el desglose de los
requerimientos. Para este ejemplo estamos asumiendo que dichas
actividades ya fueron realizadas y dieron como resultado los métodos que se
muestran en la fachada.
Tema 3 - Material exclusivo prog.III - 55
INET
Fachadas

¾ Obsérvese que los métodos ponerVehiculoVenta y quitarVehiculoVenta


podrían producir un error. Hasta ahora, la forma de representar eso era
devolver un error en forma de parámetro por referencia.
¾ Sin embargo, ahora contamos con las excepciones como el mecanismo
adecuado en Java para indicar que se ha producido un error durante la
ejecución. Por lo tanto, a la hora de implementar en Java, en vez de devolver
un error en forma de parámetro por referencia, lo que haremos será lanzar
una excepción.
¾ Ejemplo: En lugar de escribir el siguiente cabezal…
void ponerVehiculoVenta (Vehiculo v, Error & e)
En Java vamos a escribir el siguiente cabezal equivalente…
void ponerVehiculoVenta (Vehiculo v) throws MiException

Tema 3 - Material exclusivo prog.III - 56


INET
Fachadas

¾ Lo único que nos falta ahora para poder completar la implementación de la


Fachada es asegurarnos de que la misma representa un punto único de
acceso desde la capa gráfica.
¾ Para asegurarnos de que sea realmente única, lo que podemos hacer es
aplicar el patrón de diseño Singleton a la clase Fachada, tal como se
describió anteriormente.
¾ Para ello, tendremos que:
• Etiquetar al constructor de la clase Fachada como privado (observar
que hasta ahora es público)
• Agregar el atributo estático instancia y el método estático getInstancia
del modo visto.
• Mantener los demás atributos y cabezales de la fachada tal y como
habían sido propuestos en el diagrama de clases de implementación en
UML.

Tema 3 - Material exclusivo prog.III - 57


INET
Fachadas

¾ Finalizamos este capítulo mostrando el esqueleto en Java correspondiente a


la clase Fachada, de acuerdo con todas las consideraciones anteriores:
public class Fachada
{
private static Fachada instancia;
private Vehiculos diccio;
private Fachada()
{
diccio = new Vehículos();
}
public static Fachada getInstancia()
{
if (instancia == null)
instancia = new Fachada();
return instancia;
}
Tema 3 - Material exclusivo prog.III - 58
INET
Fachadas
public void ponerVehiculoVenta (Vehiculo v)
throws MiException
{ String clave = v.getMatricula();
if (diccio.member(clave))
throw new MiException(“Ya existe vehiculo”);
else
diccio.insert(v);
}
public void quitarVehiculoVenta (Vehiculo v)
throws MiException...
public double promedioPrecios()...
} // fin de la clase Fachada

Tema 3 - Material exclusivo prog.III - 59


INET

Das könnte Ihnen auch gefallen