PDF de programación - Clase 16. Prácticas: colecciones de la API de Java

Imágen de pdf Clase 16. Prácticas: colecciones de la API de Java

Clase 16. Prácticas: colecciones de la API de Javagráfica de visualizaciones

Publicado el 6 de Septiembre del 2017
882 visualizaciones desde el 6 de Septiembre del 2017
199,0 KB
11 paginas
Creado hace 20a (12/12/2003)
Clase 16. Prácticas: colecciones de la API de Java

No se puede ser un programador de Java competente sin entender las partes esenciales de la
biblioteca Java. Los tipos básicos están todos en java.lang, y son parte del lenguaje propiamente
dicho. El paquete java.util ofrece colecciones -conjuntos, listas y mapas- y es necesario
conocerlo muy bien. El paquete java.io también es importante y no basta con tener de él un
conocimiento básico, hace falta profundizar.

En esta clase analizaremos el diseño del paquete java.util, que suele recibir el nombre de ‘API de
colecciones’. Merece la pena estudiarlo no sólo porque las clases de colecciones resulten
extremadamente útiles, sino también porque la API es un ejemplo óptimo de código bien
diseñado. La API es bastante fácil de comprender y existe mucha documentación al respecto. Fue
diseñada y escrita por Joshua Bloch, autor del libro Effective Java que hemos recomendado al
inicio del curso.

Al mismo tiempo, en la API aparecen casi todas las complejidades de la programación orientada
a objetos, por lo que si la estudia con detenimiento obtendrá una amplia comprensión de asuntos
de programación que, probablemente, no había tenido en cuenta en su propio código. De hecho,
no sería exagerado decir que si llega a comprender enteramente tan sólo una de las clases,
ArrayList por ejemplo, dominará todos los conceptos de Java. Hoy no tendremos tiempo de
analizar todos los códigos pero sí que nos ocuparemos de muchos de ellos. Algunos, como la
serialización y la sincronización, quedan fuera del alcance de este curso.

16.1 Jerarquía de tipos

Vista de un modo general, la API presenta tres tipos de colecciones: conjuntos, listas y mapas.
Un conjunto es una colección de elementos que no mantiene un orden en el recuento de los
elementos: cada elemento o está en el conjunto o no lo está. Una lista es una secuencia de
elementos y, por tanto, mantiene el orden y el recuento. Un mapa es una asociación entre llaves y
valores: mantiene un conjunto de llaves y asigna cada llave a un único valor.

La API organiza sus clases mediante una jerarquía de interfaces –las especificaciones de los
diversos tipos– y una jerarquía separada de clases de implementación. El siguiente diagrama
muestra algunas clases de interfaces seleccionadas para ilustrar la organización jerárquica. La
interfaz Collection captura las propiedades comunes de listas y conjuntos, pero no de los mapas,
aunque de todas formas utilizaremos el término informal “colecciones” para referirnos también a
los mapas. SortedMap y SortedSet son interfaces utilizadas por los mapas y los conjuntos que
facilitan operaciones adicionales para recuperar los elementos en un orden.





Las implementaciones concretas de clases, como LinkedList, están construidas en la parte
superior del esqueleto de las implementaciones (por ejemplo AbstractList, de la cual LinkedList
desciende). Esta estructura paralela de interfaces es un idioma importante que merece la pena
estudiar. Muchos programadores inexpertos están tentados a utilizar clases abstractas cuando les
sería más conveniente utilizar interfaces; pero, por regla general, es mejor para usted elegir las
interfaces en vez de las clases abstractas. No es fácil aplicar un retrofit a una clase existente para
extender una clase abstracta (porque una clase puede tener como máximo una superclase), pero
no suele resultar difícil hacer que la clase implemente una nueva interfaz.

Bloch demuestra (en el capítulo 16 de su libro: ‘Prefer interfaces to abstract classes’) cómo
combinar las ventajas de ambas, utilizando una implementación de clases organizada en forma de
esqueleto de jerarquías, como hace aquí en la API de colecciones. De esta forma se obtienen las
ventajas de las interfaces para lograr el desacoplamiento basado en especificaciones y las ventajas
de las clases abstractas para fabricar código compartido entre implementaciones relacionadas.


List p = new LinkedList ();


es un estilo mejor que


LinkedList p = new LinkedList ();


Si su código compila con la primera versión del ejemplo anterior, podrá migrar fácilmente a una
lista diferente en una implementación posterior:


List p = new ArrayList ();

Cada interfaz de Java viene con una especificación informal en la documentación de API Java, lo
que resulta bastante útil, ya que informa sobre el comportamiento de la interfaz al usuario de una
clase que implementa ésta. Si se implementa una clase y se quiere que ésta satisfaga la
especificación List, por ejemplo, se deberá garantizar que cumple también con la especificación
informal, pues de lo contrario no se comportará con arreglo a lo previsto por los programadores.

Estas especificaciones, al igual que ocurre con muchas otras , han quedado incompletas de forma
intencionada. Las clases concretas también poseen especificaciones que completan los detalles de
las especificaciones de la interfaz. La interfaz List, por ejemplo, no especifica si los elementos
nulos pueden ser almacenados, pero las clases ArrayList y LinkedList informan explícitamente
que los elementos nulos están permitidos. La clase HashMap admite tanto valores nulos como
llaves nulas, al contrario que Hashtable, que no permite ni éstas ni aquellos.

Cuando escriba código que utiliza clase de API de colecciones, deberá referirse a un objeto
mediante la interfaz o la clase más genérica posible. Por ejemplo,



ya que todo el código subsiguiente se basaba en el hecho de que p era del tipo List. Pero si utiliza
la segunda versión del ejemplo anterior, seguramente descubrirá que puede hacer la alteración,
porque algunas partes de su programa realizan operaciones sobre x que sólo la clase LinkedList
ofrece: una operación que, de hecho, podría no ser necesaria. Esto está explicado más
detalladamente en la sección 34 del libro de Bloch ('Refer to objects by their interfaces').

Veremos un ejemplo más complejo de este tipo de ocurrencia en el caso práctico Tagger en la
próxima clase, donde parte del código requiere acceso a las llaves de HashMap. En lugar de
pasar todo el mapa, sólo pasaremos una visión del tipo Set:


Set keys = map.keySet ();


Ahora el código que utiliza keys ni siquiera sabe que este conjunto es un conjunto de llaves de un
mapa.

16.2 Métodos opcionales

La API de colecciones permite que una clase implemente una interfaz de colecciones sin
implementar todos sus métodos. Por ejemplo, todos los métodos de tipo modificadores de la

interfaz List están especificados como opcionales, (optional). Esto significa que usted puede
implementar una clase que satisfaga la especificación de List, pero que arroja una excepción
UnsupportedOperationException cada vez que desea llamar a un método de tipo modificador
(mutator) como, por ejemplo, el método add.

Esta debilidad intencional de la especificación de la interfaz List es problemática, porque
significa que cuando usted está escribiendo un código que recibe una lista, no puede saber, en
ausencia de información adicional sobre la lista, si será compatible con el método add.

Pero sin esta noción de operaciones opcionales, tendría que declarar una interfaz separada
denominada ImmutableList. Estas interfaces proliferarían. A veces nos interesan algunos métodos
modificadores y otros no. Por ejemplo, el método keySet de la clase HashMap devuelve un
conjunto (un objeto Set) que contiene las llaves del mapa. El conjunto es una visión: al eliminar
una llave del conjunto, una llave y su valor asociado desaparecen del mapa. Por lo tanto, es
posible utilizar el método remove, aunque no el método add, ya que no se puede añadir una llave
a un mapa sin un valor asociado a ella.

Por consiguiente, la utilización de operaciones opcionales es un buen cálculo de ingeniería.
Implica menos comprobaciones en tiempo de compilación, aunque reduce el número de
interfaces.

16.3 Polimorfismo

Todos estos contenedores –conjuntos, listas y mapas– reciben elementos de tipo Object. Se les
considera polimórficos, lo que significa 'muchas formas', porque permiten construir muchas
clases diferentes de contenedores: listas de enteros, listas de URL, listas de listas, etc.

Este tipo de polimorfismo se denomina polimorfismo de subtipo, ya que se basa en la jerarquía
de tipos. Una forma diferente de polimorfismo, denominada polimorfismo paramétrico, permite
definir contenedores a través de parámetros que indican el tipo, de manera que un cliente pueda
indicar qué tipo de elemento contendrá un contenedor específico:

List[URL] bookmarks; // ilegal en Java

Java no admite este tipo de polimorfismo, aunque han existido muchas propuestas para
incorporarlo. El polimorfismo paramétrico tiene la gran ventaja de que el programador puede
decir al compilador cuáles son los tipos de los elementos. Así, el compilador es capaz de
interceptar errores en los que se inserta un elemento del tipo equivocado, o cuando un elemento
que se extrae se trata como un tipo diferente.

A través del polimorfismo de subtipo, usted deberá moldear explícitamente los elementos durante
la recuperación, a través de la operación de cast. Considere el código:


List bookmarks = new LinkedList ();
URL u = …;
bookmarks.add (u);


URL x = bookmarks.get (0); // el compilador rechazará esta sentencia


La sentencia que añade u es correcta, pues el método add espera un objeto, y URL es una
subclase de Object. La sentencia que recupera x, no obstante, es errónea; ya que el tipo devuelto
por la sentencia del lado derecho del operador = devuelve un Object, y no se puede atribuir un
Object a una variable del tipo URL, ya que no podría basarse en aquella variable como si fuera
una URL. Por tanto, es precisa una operación de downcast, para lo que hay que escribir el
siguiente código:


URL x = (URL) bookmarks.get (0);


El efecto de la operación de downcast es realizar una verificación en tie
  • Links de descarga
http://lwp-l.com/pdf6812

Comentarios de: Clase 16. Prácticas: colecciones de la API de Java (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad