POO Java
POO Java
P
r
r
o
o
g
g
r
r
a
a
m
m
a
a
c
c
i
i
n
n
o
o
r
r
i
i
e
e
n
n
t
t
a
a
d
d
a
a
a
a
o
o
b
b
j
j
e
e
t
t
o
o
s
s
e
e
n
n
J
J
a
a
v
v
a
a
1
1
e
e
d
d
i
i
c
c
i
i
n
n
^( 1vo 1.vn Ti:v Iv.iv ^( 1vo 1.vn Ti:v Iv.iv ^( 1vo 1.vn Ti:v Iv.iv ^( 1vo 1.vn Ti:v Iv.iv
Guadalajara, Jal., Mxico
Enero 2004
CONTENIDO
1 Introduccin al paradigma orientado a objetos
1.1 Introduccin a los objetos : atributos, acciones
1.2 Programacin Estructurada vs. Programacin Orientada a Objetos
1.3 Caracterstica de los Lenguajes Orientados a Objetos
1.3.1 Abstraccin
1.3.2 Encapsulamiento
1.3.3 Modularidad
1.3.4 Jerarqua
1.3.5 Polimorfismo
1.4 Caractersticas de un objeto
1.4.1 Identidad
1.4.2 Estado
1.4.3 Comportamiento
1.4.4 Relacin entre estado y comportamiento
2 Modelando objetos con UML
2.1 Breve historia de UML
2.2 Representacin grfica de las clases
2.3 Visibilidad de atributos / mtodos
2.4 Asociacin
2.5 Agregacin
2.6 Relacin muchos a muchos con Asociacin/Agregacin
2.7 Herencia
2.8 Ejemplos
3 Fundamentos de Java
3.1 Origen de Java
3.2 Caractersticas de Java
3.2.1 Simple
3.2.2 Orientado a objetos
3.2.3 Distribuido
3.2.4 Robusto
3.2.5 Arquitectura neutral
3.2.6 Multiplataforma
3.3 Programacin bsica
II PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
3.3.1 Comentarios
3.3.2 Identificadores
3.3.3 Tipos de datos y literales
3.3.3.1 Enteros
3.3.3.2 Reales
3.3.3.3 Lgicos
3.3.3.4 Caracter
3.3.3.5 Cadenas de caracteres
3.3.4 Operadores
3.3.4.1 Aritmticos
3.3.4.2 Relacionales
3.3.4.3 Condicionales (lgicos)
3.3.4.4 A nivel de bits
3.3.4.5 De asignacin
3.3.5 Separadores
3.4 Impresin en pantalla
3.5 Control de flujo
3.5.1 Sentencias de salto
3.5.1.1 Sentencia if
3.5.1.2 Sentencia switch
3.5.2 Sentencias de bucle
3.5.2.1 Ciclo for
3.5.2.2 Ciclo while
3.5.2.3 Ciclo do / while
3.6 Conversin de tipos
4 Estructura de un programa
4.1 Encabezado
4.2 Definicin de la clase
4.3 Declaracin de atributos
4.4 Declaracin de mtodos
4.4.1 Invocacin de mtodos y sentencia return
4.4.2 Constructores
4.4.3 Mtodo main
4.5 mbito de una variable
4.6 Traduccin de una clase en notacin UML a una clase en cdigo Java
5 Objetos
5.1 Creacin
5.2 Uso de atribut os y mtodos de clase
5.3 Alcance de un objeto
5.4 Pase por valor / referencia
6 Modificadores
6.1 Para atributos
6.2 Para mtodos
6.3 Para clases
6.3.1 Clases no derivables / no instanciables
6.4 Representacin de modificadores utilizando notacin UML
CONTENIDO III
7 Almacenamiento de datos
7.1 Arreglos
7.1.1 Declaracin
7.1.2 Instanciacin
7.1.3 Manipulacin
7.1.4 Ejemplo
7.1.5 Declaracin / instanciacin / rellenado
7.1.6 Igualacin
7.2 Vectores
7.2.1 Declaracin / creacin
7.2.2 Adicin de elementos
7.2.3 Navegacin
7.2.4 Eliminacin de elementos
7.2.5 Ejemplo
7.3 Tablas hash
7.3.1 Declaracin y creacin
7.3.2 Adicin de elementos
7.3.3 Obtencin de elementos
7.3.4 Eliminacin de elementos
7.3.5 Ejemplo
7.4 Implementacin de la asociacin de clases
7.5 Implementacin de la agregacin de clases
7.6 Ejemplo final
8 Herencia y polimorfismo
8.1 Introduccin
8.2 Especializacin
8.2.1 Clase base
8.2.2 Objetos de la clase base
8.2.3 Clase derivada
8.2.4 Objetos de la clase derivada
8.3 Generalizacin
8.3.1 Clase abstracta
8.3.2 Clases derivadas
8.3.3 Objetos de una clase derivada
8.3.4 Enlace dinmico
8.3.5 Polimorfismo en accin
8.4 Herencia mltiple
8.4.1 Interfaces
8.4.2 Clase implementadora
8.4.3 Herencia mltiple en accin
8.4.4 Polimorfismo en accin
8.4.5 Modelado de interfaces usando notacin UML
9 Excepciones
9.1 Excepciones comunes
9.2 Capturando excepciones
9.2.1 Capturando varias excepciones
9.3 Creando excepciones propias
IV PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
9.3.1 Mtodos que lanzan excepciones
9.3.2 Captura de las excepciones propias
9.4 Ciclo de vida de una excepcin
10 Hilos
10.1 Flujos de un programa
10.2 Creacin de un hilo
10.3 Estados de un hilo
10.3.1 Nuevo
10.3.2 En ejecucin
10.3.3 Suspendido
10.3.4 Muerto
10.4 Comunicacin entre hilos
11 Interfaz grfica de usuario
11.1 AWT
11.2 Swing
11.3 Creacin y configuracin de los componentes visuales bsicos de Swing
11.3.1 JLabel
11.3.2 JTextField
11.3.3 JButton
11.3.4 JList
11.3.5 JScrollPane
11.3.6 JComboBox
11.3.7 Cuadros de dilogo
11.4 Adicin de los componentes visuales bsicos de Swing en una aplicacin
11.4.1 JFrame
11.4.2 JPanel
11.4.3 Disposicin de componentes Swing en un Jpanel
11.4.3.1 FlowLayout
11.4.3.2 GridLayout
11.4.3.3 BorderLayout
11.5 Manejo de eventos con componentes Swing
11.5.1 JButton
11.5.2 JList
CAPTULO 1
INTRODUCCIN AL PARADIGMA ORIENTADO A OBJETOS
Adonde quiera que volteemos podemos observar que el mundo real est compuesto por objetos:
personas, animales, plantas, edificios, vehculos, etc., lo que ocasiona que el ser humano piense en
trminos de objetos. Por esta razn, la orientacin a objetos es una forma ms natural de pensar y, por
tanto, la codificacin de programas utilizando el paradigma orientado a objetos se convierte en un
proceso ms natural que el paradigma estructurado tradicional.
El objetivo de la programacin orientada a objetos es reducir la distancia entre el razonamiento
humano y el lenguaje de los ordenadores, como se puede observar en la Figura 1.
Figura 1 Evolucin de la programacin
1.1 Introduccin a los objetos: atributos, acciones
Podemos dividir a los objetos en 2 categoras: animados e inanimados. Los objetos animados estn
vivos en algn sentido ya que pueden realizar acciones (desplazarse, emitir ruidos, comer) bajo su
propia iniciativa. Los objetos inanimados solamente estn ah, esperando a que un objeto animado
interacte con l. Sin embargo, todos los objetos tienen algo en comn: cuentan con un conjunto de
atributos forma, color, tamao, peso, edad, posicin y un conjunto de acciones que pueden realizar y
que definen su comportamiento una pelota rueda (como respuesta a otra accin), rebota, se infla, se
desinfla, un carro avanza, frena, un beb llora, duerme, gatea. Ntese que, aunque una pelota no tenga
vida propia, tambin puede realizar acciones que, por lo general, suceden como consecuencia de la
interaccin con otros objetos.
Objetos
Tipos de datos
abstractos
Funciones
Mnemnicos
Cdigo binario
Programacin ms abstracta
Simplificacin
Programacin ms difcil
2 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
El ser humano aprende sobre los objetos estudiando sus atributos y observando sus comportamientos.
Gracias a su capacidad de abstraccin, puede notar que varios objetos diferentes pueden exhibir
atributos y comportamientos similares, y es capaz de clasificarlos en categoras (clases).
1.2 Programacin Estructurada vs. Programacin Orientada a Objetos
La programacin orientada a objetos nos proporciona una forma ms natural e intuitiva de ver el
proceso de programacin, ya que simula objetos del mundo real utilizando equivalentes de software.
En C, Pascal, Cobol y otros lenguajes de programacin estructurada, la programacin tiende a estar
orientada a la accin, mientras que la programacin en Java, Eiffel, SmallTalk y C++, entre otros, estn
orientada al objeto. En C, la unidad de programacin es la funcin. En Java, la unidad de programacin
es la clase, a partir de la cual los objetos son creados en algn momento. Los programadores de C se
concentran en escribir funciones, las cuales se agrupan para formar programas. Los datos son
importantes pero solamente como apoyo de las acciones efectuadas por las funciones. Los
programadores de Java se concentran en definir sus propios tipos de datos, llamados clases. Los verbos
de la especificacin de un sistema ayudan al programador en C a determinar el conjunto de funciones
con el que se implementar tal sistema. Los sustantivos de la especificacin de un sistema son la base
para que el programador de Java determine el conjunto de clases que componen su sistema.
1.3 Caracterstica de los lenguajes orientados a objetos (LOO)
Para que un lenguaje de programacin sea considerado orientado a objetos debe cumplir con las
caractersticas definidas a continuacin.
1.3.1 Abstraccin
La abstraccin consiste en separar las propiedades ms importantes de las que no lo son. Gracias a la
abstraccin podemos definir las caractersticas esenciales de los objetos reales a travs de atributos y
comportamientos, y clasificarlos en categoras llamadas clases. Una clase es una descripcin genrica
de un grupo de objetos que comparten propiedades comunes. Todo LOO deber permitir la
implementacin de clases a partir de los cuales podemos crear muchos objetos con atributos y
comportamientos afines.
cuchillo, cuchara, tenedor : Cubierto
Hugo, Paco, Luis : Pato
15, x, 3.5, PI : Nmero
a, e, i : Vocal
Pointer, Ibiza, Corsa : Automvil
1.3.2 Encapsulamiento
En el concepto de la POO lo que realmente nos importa es el comportamiento de los objetos, no cmo
est implementado tal comportamiento; esto es, para invocar alguna accin desempeada por un objeto
es necesario conocer nicamente sus parmetros de entrada y de salida, no tanto la forma en que tal
objeto resuelve la accin. De esta manera, si la implementacin cambia pero su interfaz permanece
igual, es decir, la forma como ese objeto se relaciona con el mundo exterior, los objetos que interactan
CAPTULO 1: INTRODUCCIN AL PARADIGMA ORIENTADO A OBJETOS 3
con l no se vern afectados por esos cambios. Los objetos tienen la propiedad de ocultamiento de
informacin: aunque un objeto tenga la capacidad de comunicarse con los dems objetos, no conoce la
manera en que implementan esos objetos. En resumen, el encapsulamiento consiste en ocultar los
detalles de la implementacin de un objeto, a la vez que se proporciona una interfaz pblica por medio
de sus mtodos permitidos. Ejemplo: es posible manejar un automvil sin saber como funcionan
internamente el motor, la transmisin y el sistema de escape.
1.3.3 Modularidad
Una vez representada una situacin del mundo real en un programa, tenemos como resultado un
conjunto de objetos de software que constituyen la aplicacin. La modularidad nos permite poder
modificar las caractersticas de la clase que definen a un objeto, de forma independiente de las dems
clases en la aplicacin. En otras palabras, si nuestra aplicacin puede dividirse en mdulos separados
(normalmente clases) y estos mdulos pueden compilarse y modificarse sin afectar a los dems,
entonces dicha aplicacin ha sido implementada en un lenguaje de programacin que soporta la
modularidad.
Calculadora Geometra Tringulo
Crculo
Trigonometra Seno
Coseno
Aritmtica Suma
Resta
Figura 2 Estructura de clases de una aplicacin
Supongamos que el sistema representado en la figura 2 fue desarrollado en un LOO que soporta
modularidad y que la clase Seno solamente calcula el seno de valores dados en radianes; entonces
nosotros podemos modificar la clase Seno de tal manera que acepte valores en grados y radianes sin
tener que modificar y/o volver a compilar el resto de la aplicacin.
1.3.4 Jerarqua
Existen dos tipos de jerarquas de clases en la programacin orientada a objetos:
1. es un tipo de : herencia
2. es parte de : agregacin
La herencia nos permite definir una clase a partir de otra ya existente; la nueva clase clase derivada o
subclase heredar las caractersticas y el comportamiento de la clase existente clase base o
superclase pero adems podr tener atributos y acciones particulares. Por esta razn se dice que la
clase derivada extiende a la clase base.
Existen 2 tipos de herencia: simple y mltiple. La herencia simple nos permite crear una clase a partir
de otra ya existente. La herencia mltiple nos permite definir una clase a partir de 2 o ms clases
preexistentes. No todos los LOO permiten la herencia mltiple. Java suele implementar la herencia
mltiple a travs del uso de interfaces y polimorfismo [vase Seccin 8.4]. La Figura 3 despliega una
estructura de rbol que representa un caso tpico en el que se aplica la herencia: las literales [vase
Seccin 3.3.3]. Cabe mencionar que tal estructura no sigue alguna notacin en particular. Una variable
en cualquier lenguaje de programacin debe tener asignada una literal que indique la manera en que se
4 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
puede utilizar dicha variable. Normalmente encontramos 3 tipos de literales: numricos, lgicos y
alfanumricos. Una variable con literal numrica asignada podr participar en operaciones
matemticas. Una literal numrica tiene 2 representaciones: real y entero. En Java, existen 2 tipos de
datos para las literales reales: float y real; la diferencia entre estos 2 tipos de datos estriba en el tamao.
En resumen, float tiene las caractersticas de Real ya que contiene decimales, de Numrica ya que se
pueden realizar operaciones matemticas con ella, y de Literal ya que puede ser asignado a una
variable.
Figura 3 Herencia existente entre las literales
La agregacin consiste en el agrupamiento lgico de objetos relacionados (agregados) dentro de una
clase (agregacin). La agregacin modela relaciones de tipo: amo / esclavo, todo / partes, en donde una
clase est contenida en otra y su existencia depende de la otra. Esto es, cuando la clase agregacin deja
de existir, todos sus agregados desaparecen consigo [vase Seccin 2.5]. La Figura 4 despliega un
ejemplo de agregacin, en donde la clase Coche contiene las clases Motor, Volante y Pedal; el motor, a
su vez contiene la clase buja. Si el coche desaparece, todos sus agregados hacen lo propio.
Coche
Motor
Figura 4 Agregacin existente en un Coche
1.3.5 Polimorfismo
En ocasiones nos encontramos con el caso de que un conjunto de objetos realizan una misma accin
pero la llevan a cabo de diferente manera. Por ejemplo, todos los animales pueden desplazarse, pero
cada animal lo realiza de una manera muy particular: algunos lo hacen volando, otros arrastrndose,
otros nadando, etc. Pero finalmente la accin desplazarse les permitir cambiar su posicin.
El polimorfismo le permite a una entidad adoptar una variedad de representaciones. En POO, el
polimorfismo consiste en tratar a un objeto de diferentes maneras dentro de una funcin que no conoce
la clase del objeto, sino slamente a la clase base abstracta o la interfaz que implementa su clase. Para
lograr este cometido, Java proporciona interfaces y clases abstractas tiles para especificar las acciones
que un conjunto de objetos podrn realizar, cada uno, de una manera particular. Para informacin ms
detallada de polimorfismo, clases abstractas e interfaces, consultar captulos 8.3 y 8.4.
Literal
Alfanumrica
Lgica
Numrica
Real
Entero
Cadena de texto
Caracter
float
real
Buja
Volante
Pedal
CAPTULO 1: INTRODUCCIN AL PARADIGMA ORIENTADO A OBJETOS 5
1.4 Caractersticas de un objeto
En la programacin orientada a objetos, un objeto no representa slamente una agrupacin de datos y
de cdigo, sino que tambin se caracteriza por tener: estado, comportamiento e identidad.
1.4.1 Identidad
La identidad caracteriza la existencia de un objeto, esto es, distingue de manera unvoca a un objeto de
los dems; cada objeto posee una identidad de manera implcita (inherente). Esta identidad no se
representa de manera especfica en modelado ya que los LOO internamente gestionan la identidad de
todos los objetos creados.
1.4.2 Estado
El estado representa el conjunto de los valores de todos los atributos de un objeto en un instante dado
de su existencia. El estado de un objeto evoluciona con el tiempo.
Figura 4 Ejemplo de un objeto que guarda un estado
En la Figura 4 observamos un objeto Mi coche el cual, en un momento dado de su existencia, tiene
asignados los valores Azul, 1500 y 10 para los atributos Color, Kilometraje y Gasolina,
respectivamente, pertenecientes a la clase Coche. Estos valores en su conjunto determinan el estado en
que se encuentra el coche. Si el coche se mantiene en marcha, la cantidad de gasolina disminuir, el
kilometraje aumentar y, por lo tanto, el estado cambiar.
1.4.3 Comportamiento
El comportamiento de un objeto agrupa todas sus competencias, es decir, todas las acciones que puede
realizar; a la unidad mnima de comportamiento se le denomina operacin o mtodo. Los mtodos
suceden como consecuencia de un estmulo externo: mensaje [vase Seccin 5.2]. La Figura 5
despliega todas las acciones que puede realizar el objeto Mi coche, las cuales definen su
comportamiento.
Figura 5 Ejemplo de un objeto que exhibe un comportamiento
1.4.4 Relacin entre estado y comportamiento
El estado y el comportamiento estn ntimamente relacionados. Esto es, el comportamiento en un
instante dado depende del estado actual, y el estado puede ser modificado por el comportamiento. Lo
Mi coche
Arrancar( )
Frenar ( )
Acelerar ( )
Mi coche
Azul
1500 km.
10 lt.
6 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
anterior se puede apreciar grficamente en la Figura 6, donde Persona1 enva mensajes a Micoche
indicndole la accin que deber realizar y que modificar su estado; de acuerdo al estado en que se
encuentra Micoche es el conjunto de acciones que podr efectuar.
Figura 6 Ejemplo de relacin de estado y comportamiento
CAPTULO 2
MODELANDO OBJETOS CON UML
En esta captulo se presenta UML [Unified Modeling Language], una notacin grfica til para el
modelado de sistemas de software utilizando el paradigma orientado a objetos.
2.1 Breve historia de UML
Debido a la proliferacin de los lenguajes de POO durante los aos 90s, comenzaron a surgir una gran
variedad de notacones para representar grficamente a los objetos y todo lo que tenga que ver con ellos:
mensajes, relaciones, acciones, asociaciones, etc. Entre todos los autores que propusieron sus
notaciones grficas, podemos destacar a Jim Rumbaugh y Grady Booch. A finales de 1994, decidieron
unificar sus trabajos en un lenguaje nico: el mtodo unificado. Un ao ms tarde, se les uni Ivar
Jacobson, el creador de los casos de uso: una tcnica eficaz para la determinacin de necesidades.
A partir de ah, surgieron algunas versiones posteriores del mtodo unificado. Finalmente, se
transform en UML the unified modeling language for object-oriented development con el objetivo
de definir un lenguaje universal y simple para modelar todo tipo de objetos.
Pero, para qu queremos modelar? Un modelo es una representacin o descripcin general de un
sistema o un proceso. En el caso de UML, tal descripcin es grfica. Modelar nos permite comprender
con mayor facilidad la organizacin y la operacin de los sistemas complejos. UML proporciona 9
diferentes tipos de diagramas tiles para representar los diferentes aspectos de un sistema durante la
etapa de anlisis y diseo. El modelado con UML comienza a partir de la obtencin de los
requerimientos del sistema hasta la codificacin de mdulos del sistema.
1. Casos de uso
2. Clases
3. Objetos
4. Colaboracin
5. Secuencia
6. Estado
7. Actividades
8. Componentes
9. Despliegue
El presente captulo se enfocar en presentar la notacin de los diagramas de clases nicamente.
Componentes lgicos del sistema (parte esttica del sistema)
Modelado de las necesidades del sistema
Interaccin de tales componentes
Parte dinmica del sistema
Parte fsica del sistema
8 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
2.2 Representacin grfica de las clases
Una clase se representa en UML utilizando un rectngulo dividido en tres compartimentos: uno para
especificar el nombre de la clase, otro para sus atributos, y el ltimo para las operaciones.
Figura 7 Ejemplos de descripcin grfica de clases
En la Figura 7 se puede observar que todo objeto de tipo Automvil se caracteriza por tener una marca,
modelo, color, gasolina disponible y kilmetros recorridos. Adems un objeto Automvil puede
encenderse, apagarse, acelerar, desacelerar y frenar; el mtodo acelerar() ocasiona decrementos e
incrementos constantes en los valores de los atributos gasolina y kilometraje, respectivamente.
De manera similar, un Cronmetro tiene 5 atributos y 5 mtodos. Los mtodos del cronmetro podrn
cambiar constantemente el valor de sus atributos. Por ejemplo, poner_ceros() asigna el valor 0 a los
atributos centsimas, segundos y minutos; iniciar_conteo() cambia el valor de Estado y ocasionar
incrementos sucesivos en los valores de los atributos anteriores.
2.3 Visibilidad de atributos / mtodos
Como se puede observar en la Figura 7, todos los atributos estn precedidos por un signo , y los
mtodos por un signo +. Estos signos representan el nivel de visilibidad que se asignan a los atributos y
mtodos. C++ propone tres niveles de visibilidad:
1. Privado: un atributo privado solamente puede ser ledo y modificado dentro de la clase que lo
contiene; de manera similar, un mtodo privado solamente puede ser invocado dentro de la
clase que lo contiene; en la notacin UML, el nivel privado se representa con el signo
2. Protegido: un atributo o mtodo protegido puede ser ledo/invocado dentro de la clase que lo
contiene y dentro de las clases derivadas de la clase proveedora [vase Captulo 8]; el nivel
protegido se representa con el signo # en UML
3. Pblico: todos los objetos tienen acceso a los atributos y mtodos pblicos de una clase; se
rompe la nocin de visibilidad; se modela con el signo + en la descripcin de clases
De modo predeterminado, los atributos son privados (ocultos) y los mtodos pblicos (visibles). En las
captulos siguientes se vern ejemplos de codificacin de clases a partir de la descripcin grfica
utilizando notacin UML.
CAPTULO 2: MODELANDO OBJETOS CON UML 9
2.4 Asociacin
La asociacin es una conexin semntica bidireccional entre clases. A menudo viene acompaada de
una forma verbal activa o pasiva. El sentido de lectura se especifica con los caracteres <, >.
Figura 8 Ejemplo 1 de asociacin entre clases utilizando formas verbales
Podemos agregar una etiqueta en la conexin para especificar el tipo de objeto que participa en la
relacin. Ntese en la Figura 9 que tal etiqueta se escribe en cursiva.
Figura 9 Ejemplo 2 de asociacin entre clases utilizando etiquetas
Las relaciones suelen contener tambin informacin de multiplicidad, esto es, el nmero de instancias
[vase Seccin 5.1] participantes en una relacin. Los valores de multiplicidad ms comunes son:
1 Uno y slo uno
0, 1 Cero o uno
m .. n De m a n; donde m y n son nmeros naturales incluyendo al 0
m, n m n; donde m y n son nmeros naturales incluyendo al 0
0 .. * De cero a varios; se puede utilizar tambin *
1 .. * De uno a varios; se puede utilizar tambin +
Figura 10 Ejemplo 3 de asociacin entre clases utilizando multiplicidad
En el ejemplo de la Figura 10 podemos apreciar que a cada Factura le corresponde uno o ms
Productos, y un Cliente; adems, a cada Cliente y a cada Producto le corresponden cero o ms Facturas.
Usando palabras ms cotidianas, mediante una Factura se pueden vender uno o ms productos a un
Cliente; un mismo Producto puede venderse ms de una vez o no venderse; se pueden emitir 0 o ms
facturas a un mismo Cliente.
Ntese que para que exista una Factura, debe existir previamente al menos un Cliente y un Producto; en
caso contrario, la Factura no puede crearse. Adems, si se elimina una Factura, no se tienen por qu
eliminar el Cliente comprador y los Productos incluidos en la factura.
10 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
2.5 Agregacin
La agregacin es una forma particular de asociacin que expresa el acoplamiento entre clases, esto es,
una clase se encuentra contenida en otra. La agregacin modela relaciones de tipo: amo/esclavo, y
todo/partes. Para representarlo grficamente, se agrega un rombo del lado de la clase contenedora o
agregacin, como se puede apreciar en el diagrama de clases de la Figura 11 (lado izquierdo).
Figura 11 Representacin de la agregacin utilizando notacin UML
El diagrama del lado derecho de la Figura 11 muestra otra forma de representar la agregacin
utilizando objetos en lugar de clases. Esta forma se denomina agregacin por contencin fsica, esto es,
un objeto contiene fsicamente a otros objetos. Podemos distinguir un objeto de una clase porque su
nombre est subrayado en el diagrama y comienza con el caracter :.
Figura 12 Ejemplo 1 de agregacin entre clases y por contencin fsica
El diagrama de clases de la Figura 12 representa un reloj que puede contener de uno a cuatro alarmas y
un solo cronmetro. Ntese que la alarma y el cronmetro se modelan tambin como clases porque
cada uno de ellos contienen a su vez atributos y mtodos que los caracterizan. Del lado derecho de la
Figura 12, se modela por contencin fsica un objeto de tipo Reloj que cumple con la especificacin del
diagrama de clases, ya que este reloj contiene un objeto de tipo alarma y uno de tipo cronmetro.
Figura 13 Ejemplo 2 de agregacin entre clases y por contencin fsica
La figura 13 modela un coche como una agregacin de un motor y 2 3 pedales. El motor a su vez
puede contener 4, 6 8 bujas. Ntese que no se especifica multiplicidad en la relacin del lado de la
agregacin; en estos casos, la multiplicidad predeterminada es 1. En este curso slamente se modelarn
y codificarn relaciones de agregacin que tengan multiplicidad 1 del lado de la clase agregacin; lo
anterior quiere decir que una clase agregado estar contenido dentro de una sla clase agregacin, y no
dentro de 2 ms.
:Agregacin por contencin fsica
:Componente :Componente
= Agregacin Componente
*
1
Reloj
1
1..4
1
Cronmetro Alarma
1
:Reloj
:Alarma :Cronmetro
Coche Motor Buja
Pedal
4, 6, 8
2, 3
1
:Coche
:Pedal
:Pedal
:Motor
:Buja :Buja
:Buja :Buja
CAPTULO 2: MODELANDO OBJETOS CON UML 11
A diferencia de la asociacin, la agregacin no exige la existencia previa de un objeto agregado para
poder crear el objeto agregacin. Esto es, cuando se crea la agregacin, se crean todos los agregados
consigo; asimismo, cuando se elimina la agregacin, se eliminan todos los agregados: si destruimos un
coche, se destruyen tambien sus pedales, el motor y las bujas.
2.6 Relacin muchos a muchos con Asociacin/Agregacin
Durante el modelado de sistemas, a menudo nos encontramos con relaciones entre clases de tipo
muchos a muchos, en los cuales a cada objeto de tipo P le corresponden varios de tipo Q, y a cada
objeto de tipo Q le corresponden varios de tipo P. En el ejemplo de la Figura 10 encontramos que las
relaciones FacturaProducto y FacturaCliente son de tipo muchos a muchos. Para poder codificar este
tipo de relaciones en el lenguaje Java con las frmulas presentadas en los Captulos 7.4 y 7.5, es
necesario transformarlas en relaciones 1 a 1, 1 a muchos; para lograr este objetivo, creamos una clase
intermedia, intercambiamos los valores de multiplicidad y combinamos los conceptos de asociacin y
agregacin como se puede apreciar en la figura 14.
Figura 14 Modelado de la relacin muchos a muchos combinando asociacin y agregacin
La frmula representada en la Figura 14 podr entenderse mejor analizando el ejemplo de la Figura 15.
La relacin FacturaProducto es de manera inherente muchos a muchos, por lo tanto, es necesario
transformar o bajar de nivel tal relacin para poder llevarla a la codificacin. Ntese que toda
Factura contiene uno o ms productos vendidos, los cuales se irn creando durante la generacin de la
misma; adems, si eliminamos la factura, se eliminarn consigo todos los productos vendidos que
fueron creados; lo anterior denota una tpica relacin de agregacin; por lo tanto, creamos una clase
intermedia Prod_vendido la cual ser un agregado de la clase Factura, esto es, una factura contendr
uno o ms objetos de tipo Prod_vendido.
Figura 15 Ejemplo de modelado de la relacin muchos a muchos combinando asociacin y agregacin
* +
Clase A
* +
Clase B
Clase A Clase B Clase AB
* 1 + Relacin muchos a
muchos eliminada
Factura Producto
Factura Producto Prod_vendido
* 1 +
:Factura
:Prod_Vendido
:Prod_Vendido
:Prod_Vendido
:Prod_vendido
1
1
:Factura
:Prod_Vendido
:Prod_Vendido
:Producto
1
1
1
1
:Producto
:Producto
12 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Ntese tambin que cada objeto Prod_vendido tiene asociado un objeto de tipo Producto, el cual
deber existir previamente; adems, cada objeto Producto podr estar incluido en muchas Facturas,
esto es, podr ser asignado a varios objetos de Prod_vendido. Lo anterior denota una relacin de
asociacin que nos servir para obligar la previa existencia de productos para crear una factura y
prevenir la eliminacin de productos como consecuencia de la eliminacin de Facturas. En la parte
inferior de la Figura 15, se modelan objetos utilizando agregacin por contencin fsica de tipo
Factura, Producto y Producto_vendido cuyas relaciones cumplen con la especificacin del diagrama
de clases.
2.7 Herencia
Las relaciones de herencia se modelan con UML utilizando rboles, donde cada relacin contiene una
flecha que apunta siempre a la clase ms general: la superclase. Existen 2 puntos de vista en las
jerarquas de clases: especializacin y generalizacin. La especializacin consiste en crear una clase a
partir de otra ya existente; la nueva clase (subclase) hereder y extender el comportamiento definido
en la clase existente (superclase) [vase Seccin 8.2]. En la generalizacin, se forma una clase ms
general a partir de un conjunto de clases que exhiben una serie de elementos en comn. El Seccin 8.3
introduce las clases abstractas y el polimorfismo, los cuales son producto de la generalizacin.
Figura 16 Ejemplos de herencia de clases
En la Figura 16 podemos observar 2 ejemplos de herencia de clases. Del lado derecho de la figura
apreciamos que existen 3 tipos de pedales: acelerador, clutch y freno; mientras que del lado izquierdo
notamos que existen 2 tipos de automviles: automtico y estndar. Adems, todo automvil contiene
un acelerador y un freno, y todo automvil estndar tiene un clutch. Ntese que debido a que Estndar
hereda de Automvil, todo objeto Estndar tambin contiene un objeto Acelerador y un objeto Freno.
Cabe mencionar que en los diagramas de clases podemos usar conectores de la misma manera que
como se utilizan en los diagramas de flujo tradicionales: para atender el problema de los espacios de
trabajo reducidos.
2.8 Ejemplos
Esta seccin est encaminado a presentar varios ejemplos de diagramas de clases utilizando la notacin
UML y describiendo previamente y de manera textual el problema a modelar.
El diagrama de la Figura 17 modela el siguiente escenario: un grupo de cierta universidad se caracteriza
por tener asociado una materia, un maestro, uno o dos salones, y al menos 5 y no ms de 30 alumnos
inscritos. Una materia puede impartirse en varios grupos a la vez, o no impartirse. Una materia tiene
asignado una especialidad y cada especialidad se asigna al menos a una materia. Un saln siempre
Pedal
Acelerador Clutch Freno
2
1
1
1
1
1
Automvil
Automtico Estndar
2
1
CAPTULO 2: MODELANDO OBJETOS CON UML 13
tendr al menos un grupo asignado, pero puede tener ms. Existen 2 tipos de salones: las aulas y los
laboratorios. Un maestro puede dar un grupo o ms, o quedarse sin trabajar. Existen 2 tipos de
maestros: los adjuntos y los asociados. Un alumno deber estar inscrito en al menos 3 grupos, pero en
no ms de 6.
Figura 17 Modelado de un sistema escolar
En la Figura 18 se presenta el diagrama de clases que modela el siguiente problema: un viaje de cierta
lnea camionera se caracteriza por tener asignado un camin, uno o dos choferes, un origen y un
destino. Adems, en un viaje se pueden realizar hasta 3 paradas, o ninguna. Todas las ciudades
registradas pueden ser origen, destino o lugar de parada en diferentes viajes, pero no en todas las
ciudades se hacen paradas.
Un chofer contratado puede realizar muchos viajes, o estar inactivo en un momento dado. Para que el
viaje se lleve a cabo, es necesario juntar al menos a 5 pasajeros, y a un mximo de 36. Un camin
puede utilizarse para uno o ms viajes, o quedar inactivo en un momento dado. Un camin puede
contener 32 36 asientos. Cada pasajero tiene asignado un asiento en un viaje dado, y cada asiento
podr tener a un pasajero o estar vaco. Un cliente de la lnea camionera podr ser pasajero en uno o
ms viajes.
La figura 19 describe el siguiente panorama: en una agencia de automviles, un cliente puede comprar
uno o ms productos a travs de una orden de compra. Una orden tiene asociada solamente un cliente y
contiene al menos un detalle de compra; en cada detalle se especifica un producto vendido al cliente.
Los productos pueden ser automviles, refacciones o servicios. Por otro lado, un cliente que emiti una
orden de compra podr efectuar ms de un pago para saldar su deuda. Cada pago del cliente deber
tener asociado una orden de compra al cual est abonando. Cada pago se puede llevar a cabo de 3
formas diferentes: en efectivo, en cheque o con tarjeta de crdito.
Saln
Aula Laboratorio
Grupo
1, 2
+
Inscrito
5 . . 30
Alumno
3 . . 6
1
Materia
Especialidad
* 1
+
1
1 *
Maestro
Adjunto
Asociado
5 . . 30
3 . . 6
14 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Figura 18 Modelado de un sistema de viajes
Figura 19 Modelado del sistema de una agencia de automviles
Cliente
Orden
Pago
Crdito Efectivo Cheque
Detalle
Producto
Automvil Refaccin Servicio
1
1
1
v||dos: 1, ,
v||dos: ,
Destino Origen
Ciudad
Viaje
1
+
Pasajero
5, 36
Camin
Asiento
* 1
32, 36
1, 2 *
Chofer
Parada
0..3
*
1
+
0..1 1
Cliente
1 +
5, 36
+
CAPTULO 3
INTRODUCCIN AL LENGUAJE JAVA
Java es un lenguaje de programacin orientado a objetos desarrollado por la empresa Sun
MicroSystems. El objetivo principal de Java es permitir el desarrollo de aplicaciones distribuidas en
redes heterogneas como Internet; para permitir tal objetivo, Java resuelve los problemas de
incompatibilidad inherentes entre las diferentes arquitecturas de hardware, sistemas operativos y
sistemas de ventanas existentes en el mercado.
3.1 Origen de Java
A finales de los ochentas, la empresa Sun MicroSystems inicia un proyecto de investigacin
encabezado por James Gosling con el propsito de desarrollar un lenguaje de programacin para
dispositivos electrnicos como tostadoras, hornos microondas y asistentes digitales personales. Gosling
y su equipo de investigacin llegaron a la conclusin de que el software para dispositivos de consumo
tiene algunos requerimientos de diseo nicos. Por ejemplo, el software necesita ser capaz de trabajar
en nuevos chips de computadora. Cuando los chips son introducidos, los fabricantes ms de una vez los
cambian por otros por ser ms baratos o introducir nuevos mecanismos.
El software tambin necesita ser extremadamente inteligente, porque cuando un producto del
consumidor falla, el fabricante usualmente tiene que reemplazar todo el dispositivo y no el componente
que origin el fallo. Gosling y su equipo tambin descubrieron que existan lenguajes de programacin
como C y C++ con los cuales no se poda realizar la tarea de hacer un software que fuera independiente
de la arquitectura en donde se est ejecutando. Un programa escrito en C o C++ se compila para un
chip de computadora particular. Cuando se cambia de chip, el programa debe ser recompilado.
Como resultado de lo dicho anteriormente, en 1990 Gosling comenz a disear un nuevo lenguaje de
programacin que fuera ms apropiado para dispositivos que utilizan software electrnico. Este
lenguaje fue conocido originalmente como Oak. Fue pequeo, confiable e independiente de la
arquitectura. En 1993, cuando el equipo de Java continuaba trabajando en el diseo del nuevo lenguaje,
surgi la Word Wide Web. El equipo de Java consider que un lenguaje de arquitectura neutral sera
ideal para programar en la Internet, porque permitira que los programas desarrollados fueran
ejecutados en cualquier tipo de computadora conectada.
Finalmente, el lenguaje Java se present como total en agosto de 1995 y encontr en Internet un mbito
de desarrollo de software con posibilidades de disputar la supremaca de Microsoft.
16 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
3.2 Caractersticas de Java
Sun describe al lenguaje Java de la siguiente manera: simple, orientado a objetos, distribuido, robusto,
de arquitectura neutral y multitarea.
3.2.1 Simple
Java ofrece toda la funcionalidad de un lenguaje potente, pero sin las caractersticas menos usadas y
ms confusas de stos. Aprovechando que C y C++ son los lenguajes ms difundidos, Java se dise
para ser parecido a C++ y as facilitar el aprendizaje. Java elimina muchas de las caractersticas de
otros lenguajes como C++ para mantener reducidas las especificaciones del lenguaje y aadir
caractersticas muy tiles como el reciclador de memoria dinmica (garbage collector). No es
necesario preocuparse por liberar la memoria, el reciclador se encarga de ello y, como es de baja
prioridad, permite liberar bloques de memoria muy grandes cuando entra en accin. Adems, Java
reduce en un 50% los errores ms comunes de programacin al eliminar muchas caractersticas de
stos, entre las que destacamos: aritmtica de punteros, macros, definicin de tipos, registros,
referencias y necesidad de liberar memoria.
3.2.2 Orientado a objetos
Java implementa la tecnologa bsica de C++ con ciertas mejoras y elimina algunas cosas para
mantener el objetivo de la simplicidad del lenguaje. Java soporta las tres caractersticas propias del
paradigma de la orientacin a objetos: encapsulamiento, hernecia y polimorfismo. Como en C++, las
plantillas de objetos son llamadas clases y sus copias, instancias. Estas instancias necesitan ser
construidas y destruidas en espacios de memoria.
3.2.3 Distribuido
Java se ha construido con extensas capacidades de interconexin TCP/IP. Java en s no es distribuido,
sino que proporciona herramientas para que los programas puedan ser distribuidos; esto es, existen
libreras de rutinas para acceder e interactuar con protocolos como http y ftp, que permiten a los
programadores acceder a la informacin a travs de la red con tanta facilidad como a los archivos
locales.
3.2.4 Robusto
Java realiza verificaciones en busca de problemas tanto en tiempo de compilacin como en tiempo de
ejecucin. La comprobacin de tipos en Java ayuda a detectar errores en el ciclo de desarrollo. Java
maneja internamente la memoria para eliminar las preocupaciones por parte del programador en cuanto
a la liberacin o corrupcin de la memoria.
3.2.5 Arquitectura neutral
El compilador de Java genera un cdigo objeto (ByteCode) cuyo formato es independiente a la
arquitectura de la mquina en que se ejecutar; cualquier mquina que tenga instalada la mquina
virtual de Java (JVM) puede ejecutar tal cdigo intermedio sin importar que ste haya sido generado en
otra arquitectura de hardware, otro sistema operativo u otro sistema de ventanas. Esto puede ser posible
porque, durante la ejecucin de un programa de Java, la JVM convierte el cdigo objeto en cdigo
binario correspondiente a la arquitectura donde se est ejecutando. Cabe mencionar que debe existir
CAPTULO 3: INTRODUCCIN AL LENGUAJE JAVA 17
una JVM apropiada para cada arquitectura en donde se desee ejecutar cdigo de Java. Actualmente,
existen JVMs para Solaris, SunOs, Windows 9x, Windows NT, Linux, HP-UX, Irix, Aix, MacOS,
Apple, entre otros sistemas operativos.
3.2.6 Multitarea
Permite la ejecucin concurrente de varios procesos ligeros o hilos de ejecucin (mejor rendimiento),
esto es, Java permite realizar muchas actividades simultneas en un programa. El beneficio de ser
multitarea (multi-threaded) consiste en un mejor rendimiento interactivo y mejor comportamiento en
tiempo real que los entornos de flujo nico de programa (single-threaded).
3.3 Programacin bsica en Java
Esta captulo presenta la sintaxis para implementar en Java ciertos aspectos que todo lenguaje de
programacin de alto nivel debe considerar. Gran parte de esta sintaxis ha sido heredada de C/C++.
3.3.1 Comentarios
Los comentarios se utilizan para documentar el cdigo, esto es, proporcionan una explicacin general
de lo que algn segmento de cdigo realiza o, tal vez, informacin adicional que no se lee directamente
en el cdigo. Los comentarios deben contener slamente informacin que sea relevante para la lectura
y entendimiento del programa.
En java, existen 3 tipos de comentarios:
1) Comentarios de una sla lnea. Cualquier caracter que se encuentre en la misma lnea y despus
de los caracteres // ser considerado comentario y, por lo tanto, ignorado por el compilador:
x = x + 1; // esta lnea incrementa en uno el valor de x
2) Comentarios de una o ms lneas. Cualquier carcter que se encuentre entre las parejas de
caracteres /* y */ sern considerados comentarios e ignorados por el compilador:
x = x + 1; /* dentro de este ciclo, el valor de x ser
incrementado en uno mientras ste sea menor a 100 */
y = /* esto es vlido, pero no recomendable */ y + 1;
3) Comentarios de documentacin. Estos comentarios son exclusivos de Java y estn delimitados
por los caracteres /** y */. Tambin son de una o ms lneas. Los comentarios de
documentacin describen la especificacin que ha dado lugar al cdigo desde una perspectiva
ms general que los comentarios de implementacin (los 2 anteriores), para que pueda ser
comprendida por los desarrolladores que no les interese comprender el cdigo fuente, sino las
funciones que proporciona tal cdigo. Utilizando la herramienta javadoc podemos extraer estos
comentarios a ficheros HTML [vase Captulo 12.4].
/** El siguiente mtodo devuelve el valor del rea de un rectngulo
de base b y altura h; el rea es un valor flotante */
public float getArea(float b, float h) {
18 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
3.3.2 Identificadores
Los identificadores sirven para nombrar unvocamente a variables, funciones, clases y objetos definidos
por el usuario. Un identificador debe comenzar con una letra, un subrayado o un smbolo de peso. Los
caracteres siguientes pueden ser letras, dgitos o subrayados.
Identificadores vlidos: x, _variable, nombre_cliente, Nombre_cliente, $abc, MiClase3
3.3.3 Tipos de datos y literales
Los tipos de datos definen los mtodos de almacenamiento disponibles para representar informacin,
junto con la manera en que dicha informacin ha de ser interpretada. Java es un lenguaje con control
fuerte de tipos (Strongly Typed), esto significa que cada variable y cada expresin tiene asignado un
tipo de dato que es conocido en el momento de la compilacin. Este tipo limita los valores que una
variable puede contener, limita las operaciones soportadas sobre esos valores y determina el significado
de las operaciones.
Los tipos de datos en Java pueden dividirse en dos categoras: simples y compuestos. Los simples son
tipos atmicos que no se derivan de otros tipos: enteros, reales, lgicos y caracteres. Los tipos
compuestos se construyen con base en los tipos simples: cadenas de caracteres, arreglos, clases e
interfaces. A excepcin de las cadenas de caracteres, los tipos de datos compuestos son tipos definidos
por el usuario o por el programador de libreras de Java. En esta captulo veremos los tipos de datos
simples y las cadenas de caracteres.
Cada tipo de dato simple soporta un conjunto de literales, las cuales definen la sintaxis que debe tener
un valor, esto es, la forma de expresar/representar valores constantes como 134, a, -75.6.
3.3.3.1 Enteros
Se utilizan para representar nmeros enteros con signo. Hay cuatro tipos: byte, short, int y long.
Tipo Tamao
byte 1 Byte (8 bits)
short 2 Bytes (16 bits)
int 4 Bytes (32 bits)
long 8 Bytes (64 bits)
Tabla 1 Tipos de datos enteros
Literales enteros;
o Decimal: Los literales decimales aparecen como nmeros ordinarios sin ninguna notacin especial:
155, -3456
o Hexadecimal: Los hexadecimales (base 16) aparecen con un 0x 0X inicial, notacin similar a la
utilizada en C y C++: 0x3F, 0xAD16
o Octal: Los octales aparecen con un 0 inicial delante de los dgitos: 017, 032345
CAPTULO 3: INTRODUCCIN AL LENGUAJE JAVA 19
Por ejemplo, un literal entero para el nmero decimal 10 se representa en Java como 10 en decimal,
como 0xA en hexadecimal, y como 012 en octal. Los literales enteros se almacenan por defecto en el
tipo int, o si se trabaja con nmeros muy grandes, en el tipo long, aadiendo una L l al final del
nmero.
3.3.3.2 Reales
Se usan para representar nmeros con partes fraccionarias. Hay dos tipos de datos reales en Java: float
y double. El primero reserva almacenamiento para un nmero de precisin simple de 4 bytes y el
segundo lo hace para un numero de precisin doble de 8 bytes.
Tipo Tamao
float 4 Byte (32 bits)
double 8 Bytes (64 bits)
Tabla 2 Tipos de datos reales
Literales reales:
Representan nmeros decimales con partes fraccionarias. Pueden representarse con notacin estndar (-
156.75) o cientfica (3.2456e2). De forma predeterminada, un valor real es de tipo double (8 bytes).
Para tratar un valor real como float se agrega el caracter F f al final del nmero: 3.1492f.
3.3.3.3 Lgicos
Se usan para almacenar variables que presenten dos estados: verdadero falso. Representan valores bi-
estado, provenientes del lgebra de Boole. Hay un tipo de dato lgico en Java: boolean.
Literales lgicos:
Java utiliza dos palabras clave para los estados: true (para verdadero) y false (para falso). Este tipo de
literales es nuevo respecto a C/C++, donde el valor de falso se representaba por un 0 numrico, y el
verdadero con cualquier nmero diferente a 0.
3.3.3.4 Caracter
Utilizados para almacenar caracteres Unicode simples. Hay un tipo de dato caracter en Java: char.
Cabe mencionar que Unicode es una especificacin que proporciona un nmero nico para cada
caracter existente, sin importar la plataforma, el programa o el idioma. Debido a que el conjunto de
caracteres Unicode se compone de valores de 16 bits, el tipo de datos char se almacena en un entero sin
signo de 16 bits.
Literales caracter:
Representan un nico carcter (de la tabla de caracteres Unicode 1.1) y aparecen dentro de un par de
comillas simples, de forma similar que en C/C++: a, 3, #. Los caracteres especiales (de control, no
20 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
desplegables) se representan con una barra invertida ('\') seguida del cdigo asociado, como se puede
observar en la Tabla 3.
Descripcin Representacin Valor Unicode
Caracter Unicode \udddd
Numero octal \ddd
Retroceso \b \u0008
Retorno de carro \r \u000D
Tabulacin horizontal \t \u0009
Lnea nueva \n \u000A
Barra invertida (\) \\ \u005C
Comillas simples () \ \u0027
Comillas dobles () \" \u0022
Nmeros arbigos ASCII 0 9 \u0030 a \u0039
Alfabeto ASCII en maysculas A Z \u0041 a \u005A
Alfabeto ASCII en minsculas a z \u0061 a \u007A
Tabla 3 Caracteres especiales Java
3.3.3.5 Cadenas de caracteres
Utilizados para almacenar informacin textual (letras, palabras) de tamao indefinido. En Java se
utiliza el tipo de dato String para almacenar cadenas de caracteres. A diferencia de C/C++, el tipo de
dato String es una clase de Java, y una variable de tipo String es un objeto [vase Captulo 5] y, por lo
mismo, tiene atributos y proporciona mtodos tiles para la manipulacin de cadenas de texto.
Literales para cadenas de caracteres:
Una cadena de caracteres representa mltiples caracteres los cuales se encuentrar limitados por un par
de comillas dobles (): sta es una cadena de caracteres. Aunque una variable String realmente sea
un objeto, Java nos permite tratar a este tipo de variables como si pertenecieran a un tipo de dato
primitivo, esto es, podemos asignarle valores constantes directamente sin preocuparnos por reservar
espacio de memoria previamente, como se tiene que hacer para los dems objetos.
3.3.4 Operadores
Java proporciona un conjunto de operadores para poder realizar acciones sobre uno o dos operandos.
Un operador que acta sobre un slo operando es un operador unario, y un operador que acta sobre
dos operandos es un operador binario. Existen operadores (!, -) que pueden funcionar como ambos. Los
operadores de Java se pueden dividir en cinco principales categoras: aritmticos, relacionales,
condicionales, a nivel de bits y de asignacin.
CAPTULO 3: INTRODUCCIN AL LENGUAJE JAVA 21
3.3.4.1 Aritmticos
Estos operadores pueden actuar sobre nmeros enteros y reales; en algunos casos, tambin actan sobre
cadenas de texto.
Los operadores binarios aritmticos soportados por Java son:
+ : suma los operandos;
: resta el operando de la derecha al de la izquierda
* : multiplica los operandos
/ : divide el operando de la izquierda entre el de la derecha
% : residuo de la divisin del operando izquierdo entre el derecho
+ : concatena cadenas de texto
Los operadores unarios aritmticos soportados por Java son:
+ : indica un valor positivo
: negativo, o cambia el signo albegraico
++ : suma 1 al operando, como prefijo o sufijo
: resta 1 al operando, como prefijo o sufijo
3.3.4.2 Relacionales
Estos operadores son tiles para comparar valores numricos, lgicos o caracteres. Devuelven siempre
un valor lgico (true, false). Todos los operadores relacionales son binarios.
> : el operando izquierdo es mayor que el derecho
>= : el operando izquierdo es mayor o igual que el derecho
< : el operando izquierdo es menor que el derecho
<= : el operando izquierdo es menor o igual que el derecho
== : el operando izquierdo es igual que el derecho
= : el operando izquierdo es diferente al derecho
3.3.4.3 Condicionales (lgicos)
Estos operadores sirven para realizar operaciones utilizando valores lgicos. Todos los operadores
condicionales son binarios y devuelven un valor lgico (true, false).
&& : operador AND; devuelve true si ambos operandos son true
| | : operador OR; devuelve true si algn operando es true
! : operador NOT; alterna el valor lgico del operando
3.3.4.4 A nivel de bits
Java y C/C++ comparten un conjunto de operadores que realizan operaciones sobre un slo bit a la vez.
Adems, Java incluye el operador >>> que no existe en C/C++, el cual nos permite realizar
desplazamientos a la derecha ignorando el bit de signo, esto es, rellena con ceros los bits ms
22 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
significativos que pueden quedar vacos. Los operadores a nivel de bits actan sobre nmeros enteros
nicamente y se listan a continuacin:
Operadores binarios:
>> : operador SHR; desplaza bits del operando izquierdo hacia la derecha las posiciones
indicadas en el operando derecho; este operador SI considera el bit de signo
<< : operador SHL; desplaza bits del operando izquierdo hacia la izquierda las posiciones
indicadas en el operando izquierdo;
>>> : operador SHR; desplaza bits del operando izquierdo hacia la derecha las posiciones
indicadas en el operando derecho; este operador NO considera el bit de signo
& : operador AND
| : operador OR
^ : operador XOR
Operadores unarios:
~ : complemento del operando (NOT)
3.3.4.1 De asignacin
= : operador binario de asignacin de valores; el valor representado por el operando de la
derecha del operador es copiado en la memoria indicada por el operando de la izquierda
Java incluye todo una gama de operadores de asignacin que se componen de otros operadores para
realizar la operacin que indique ese operador y luego asignar el valor obtenido al operando de la
izquierda del operador de asignacin. De este modo se pueden realizar dos operaciones con un solo
operador: += , =, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=
3.3.5 Separadores
Los separadores sirven para definir la forma en que se va a agrupar y va a funcionar el cdigo. Los
separadores admitidos en Java son:
( ) parntesis. Para contener listas de parmetros en la definicin y llamada a mtodos. Tambin se
utiliza para definir precedencia en expresiones, contener expresiones para control de flujo (for, while) y
rodear las conversiones de tipo (casts) [vase Captulo 3.6].
{ } llaves. Para contener los valores de arreglos inicializados en la declaracin. Tambin se utiliza
para definir los lmites de clases, subclases, mtodos y bucles.
[ ] corchetes. Para declarar, instanciar y manipular valores de arreglos [vase Captulo 7.1].
; punto y coma. Para separar lneas de cdigo (sentencias).
, coma. Para separar identificadores consecutivos en una declaracin de variables. Tambin se utiliza
para separar declaraciones, incrementos/decrementos y condiciones finales en sentencias for.
CAPTULO 3: INTRODUCCIN AL LENGUAJE JAVA 23
. punto. Para separar nombres de paquetes, subpaquetes y clases. Tambin se utiliza para especificar
un atributo o mtodo pblico a partir del identificador del objeto [vase Captulo 5.2].
3.4 Impresin en pantalla
En ocasiones es importante conocer el valor de alguna variable en algn momento de la ejecucin de la
aplicacin; Java proporciona dos mtodos tiles para imprimir informacin en la consola.
sintaxis:
System.out.print(expresion);
System.out.println(expresion); // imprime un retorno de carro al final (enter)
donde expresion puede ser:
a) una variable primitiva: x, aa, y
b) una constante : 2, x, \n, 0xF370, -15.6, ja, PI
c) un objeto: cadenaTexto, miArreglo, vector1, triangulo3
d) una operacin : x * y, (base + altura) / 2, s + hola
La clase final System tiene un atributo esttico llamado out de tipo PrintStream (flujo de impresin); la
clase PrintStream proporciona los mtodos print y println, los cuales se pueden invocar utilizando
como parmetro un valor de cualquier tipo de dato. Esto significa que podemos imprimir cualquier cosa
en la consola enteros, reales, lgicos, caracteres, cadenas, objetos ya que, finalmente, Java convierte
el valor a imprimir en una cadena de texto. Este valor puede ser el resultado de alguna operacin.
ejemplos:
System.out.print(58.75);
System.out.print(area / 2);
System.out.println(hola);
System.out.println(area del crculo es + area);
El signo + puede cambiar su significado de acuerdo a los operadores; el signo + representa una:
suma aritmtica : si todos los operadores son valores numricos
concatenacin : si al menos un operador es una cadena de texto
ejemplos:
int a = 5;
System.out.print(100 + a + 25); // imprimir 130
System.out.print(100 + a + 25); // imprimir 10525
Podemos utilizar parntesis para indicar la operacin que se realizar primero en una expresin.
ejemplos:
String s = 5;
int a = 2;
System.out.print(s + a + 10); // imprimir 5210 porque al menos uno
// de los operadores es una cadena de texto
System.out.print(s + (a + 10)); // imprimir 512 porque primero realiza
// la suma aritmtica de enteros y luego
// la concatenacin de cadenas
System.out.print(s + a * 10); // imprimir 520 porque primero realiza
// la multiplicacin aritmtica y luego
// la concatenacin de cadenas
24 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
3.5 Control de flujo
Las sentencias de control de flujo nos permiten crear flujos de programa alternativos que se tomarn de
acuerdo a las acciones del usuario de la aplicacin y, en general, al valor de las variables en algn
momento de la ejecucin. Cada flujo de programa indica un camino diferente que conlleva a la
terminacin del programa. Muchas de estas sentencias que veremos a continuacin se han tomado de
C/C++.
Existen 3 tipos principales de sentencias de control de flujo:
a) Sentencias de salto : para elegir un proceso a ejecutar dada una condicin
b) Sentencias de bucle : para repetir un proceso mientras no se cumpla una condicin
c) Excepciones : para manejar errores en tiempo de ejecucin
3.5.1 Sentencias de salto
Las sentencias de salto eligen la siguiente secuencia de operaciones a ejecutarse, entre varias posibles,
de acuerdo al cumplimiento de alguna condicin. Java proporciona 2 tipos de sentencias de salto que
hereda de C/C++: if y switch.
3.5.1.1 Sentencia if
La sentencia if analiza el cumplimiento de una condicin dada a travs de una variable o expresin
lgica; esto es, si el valor de la variable lgica o el resultado de la expresin resulta verdadero se
ejecuta una secuencia de operaciones; en caso contrario, se ejecuta otra secuencia de operaciones, pero
esta ejecucin es opcional. El efecto de la sentencia if consiste en elegir una ruta a seguir de solamente
2 caminos posibles. La Figura 20 muestra un diagrama de flujo con estructura de rbol binario que
representa el comportamiento de la sentencia if.
Figura 20 Diagrama de flujo de la sentencia if
sintaxis:
if( expresionLogica ) {
sentencias; // condicin cumplida; expresionLogica = true
} else {
ms sentencias; // condicin no cumplida; expresionLogica = false
}
NOTAS:
a) la presencia de la sentencia else es opcional: existen casos en los que no se necesita tomar algn
camino cuando la condicin no se cumple
b) se puede prescindir de las llaves si el camino a seguir consta de una sla sentencia
ejemplo:
public void operacion(float a, float b, int opcion) {
// si la opcion no esta entre 1, 2 salir del metodo; ejemplo de if sin else
if(opcion <= 0 || opcion > 2) return;
?
true false
CAPTULO 3: INTRODUCCIN AL LENGUAJE JAVA 25
if(opcion == 1) {
float suma = a + b;
System.out.println(a + b = + suma);
} else {
float resta = a - b;
System.out.println(a - b = + resta);
}
}
En el mtodo anterior solamente podemos realizar una de dos operaciones aritmticas, de acuerdo al
valor de la variable opcion. Si queremos incrementar la funcionalidad de este mtodo podemos utilizar
sentencias if anidadas. La figura 21 muestra un diagrama de flujo con estructura de rbol binario que
representa el comportamiento de la sentencia if anidada.
Figura 21 Diagrama de flujo de la sentencia if anidada
sintaxis:
if( expresionLogica1 ) {
sentencias; // expresionLogica1 = true
}
else if { expresionLogica2 ) {
sentencias; // expresionLogica2 = true; expresionLogica1 = false;
}
:
:
else if ( expresionLogican ) {
sentencias; // expresionLogican = true; todas las demas = false;
} else {
sentencias; // todas las expresiones = false;
}
ejemplo:
public void operacion(float a, float b, int opcion) {
float total = 0.0f;
if(opcion <= 0 || opcion > 4) {
System.out.println(opcion no valida);
return;
}
// no es necesario agregar un else en la siguiente lnea por la presencia de
// la sentencia return
if(opcion == 1) total = a + b;
else if(opcion == 2) total = a b;
else if(opcion == 3) total = a * b;
else {
// es necesario prevenir una divisin entre cero
if(b == 0) System.out.println(divisor no vlido);
else total = a / b;
}
System.out.println(resultado de la operacin: + total);
}
?
true false
?
true false
26 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
3.5.1.2 Sentencia switch
La sentencia switch analiza una variable de tipo entero o caracter y, dado el valor obtenido, se elegir
uno de varios caminos posibles. Esta sentencia suele ser una alternativa ideal para evitar el anidamiento
de sentencias if. La Figura 22 muestra un diagrama de flujo con estructura de rbol n-ario que
representa el comportamiento de la sentencia switch.
Figura 22 Diagrama de flujo de la sentencia switch
sintaxis:
switch(variable) {
case valor1: sentencias;
break;
case valor2: sentencias;
break;
:
default: sentencias;
}
NOTAS:
a) variable debe ser de algn tipo entero o caracter (int, short, byte, char)
b) valor1, valor2 son constantes del mismo tipo que variable
c) la presencia de default es opcional (como else en la sentencia if)
d) break evita que se ejecutan todos los casos
ejemplo:
public void operacion(float a, float b, int opcion) {
float total = 0.0f;
switch(opcion) {
case 1: total = a + b;
case 2: total = a b;
case 3: total = a * b;
case 4: if(b == 0) System.out.println(divisor no vlido);
else total = a / b;
default: System.out.println(opcion no valida);
}
System.out.println(resultado de la operacin: + total);
}
3.5.2 Sentencias de bucle
Las sentencias de bucle nos sirven para repetir una secuencia de instrucciones tantas veces como sea
necesario, esto es, mientras no se cumpla la condicin de terminacin. Java proporciona 3 tipos de
sentencias de bucle o ciclos que tambin son heredadas de C/C++: for, while, do/while.
3.5.2.1 Ciclo for
Este ciclo es uno de los ms usados para repetir una secuencia de instrucciones sobre todo cuando se
conoce la cantidad exacta de veces que se desea ejecutar un proceso dado.
?
...
CAPTULO 3: INTRODUCCIN AL LENGUAJE JAVA 27
sintaxis:
for (inicializacion; condicion_terminacion; inc/decremento) {
sentencias;
}
La inicializacin es una instruccin de asignacin que carga una o ms variables de control de ciclo con
sus valores iniciales. Se pueden declarar tales variables dentro del ciclo for. La condicin de
terminacin es una expresin relacional que evala la variable de control de ciclo contra un valor final
o de parada que determina cuando debe acabar el ciclo. El incremento o decremento define la manera
en que la variable de control de ciclo debe cambiar cada vez que finalice un ciclo. Se deben separar
esos 3 argumentos con punto y coma (;).
ejemplos:
for(int i = 0; i < 5; i ++) System.out.print(i); // imprime 01234
int m = 0, n = 100;
for (int i = 0, j = 10; i < 10 ; i ++, j --) {
m += i;
n -= j;
} // al final m, n = 45
3.5.2.2 Ciclo while
En este ciclo, el cuerpo de instrucciones se ejecutar mientras una condicin dada permanezca como
verdadera; en el momento en que la condicin se convierte en falsa, el ciclo terminar; ntese que es
posible que el cuerpo de instrucciones no se ejecute nunca.
sintaxis:
declarar/iniciar variables condicionales
while (condicion) {
sentencias;
instruccion(es) que nos permitiran salir del ciclo en algun momento
}
donde condicion es una expresin relacional, y las instrucciones para salir del ciclo tarde o temprano
sern capaces de cambiar el valor actual de condicion.
ejemplo:
public int obtenerFactorialDe(int numero) {
int factorial = 1;
int i = 2;
while(i < numero) {
factorial = factorial * i;
i ++;
}
return factorial;
}
3.5.2.3 Ciclo do / while
Su diferencia bsica con el ciclo while es que la prueba de condicin se realiza al finalizar el ciclo; con
esto, el cuerpo de instrucciones se ejecutar al menos una vez; por esta razn se le conoce tambin
como ciclo de condicin de salida.
28 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
sintaxis:
declarar/iniciar variables condicionales
do {
sentencias;
instruccin(es) para salir del ciclo
} while (condicion);
donde condicion es una expresin relacional, y las instrucciones para salir del ciclo tarde o temprano
sern capaces de cambiar el valor actual de condicion.
ejemplo:
public void fibonacci(int limite) {
int a = 0;
int b = 1;
do {
int c = a + b;
System.out.println(c);
a = b;
b = c;
} while(a + b < limite);
}
3.6 Conversin de tipos
Java realiza una conversin automtica de tipos numricos cuando el tipo de dato de la variable
resultante es mayor que el tipo del valor original. Esto es, cuando deseamos convertir un valor de byte a
short, short a int, float a double, char a int, o de un tipo entero a un tipo real, el tipo de dato resultante
est implcito en la asignacin. Si el tipo de dato de la variable resultante es menor que el tipo del valor
original, es necesario realizar un moldeo o cast al valor original para forzar la conversin; se dice que
el tipo de dato resultante est explcito en la asignacin. El cast se realiza colocando entre parentsis el
tipo de dato al que se quiere convertir un valor.
sintaxis:
tipoDato1 identificador = (tipoDato1) valor
donde valor tiene un tipo mayor que tipoDato1
ejemplo:
short sh = (short) 10000;
Existen otros tipos de conversiones de tipos que involucran cadenas de caracteres; en estos casos, se
utilizan mtodos de ciertas clases provistas por la API de Java: Integer, String, Float, entre otros. A
continuacin, se proporcionan ejemplos de conversiones de tipos comunes en Java y se clasifican de
acuerdo a los tipos de datos participantes en la conversin.
Entre tipos enteros:
byte a short/int:
byte b = 0x3F;
short s = b;
int i = b;
short a int:
short s = 300;
int i = s;
CAPTULO 3: INTRODUCCIN AL LENGUAJE JAVA 29
int a short/byte:
short s = (short) 1000;
byte b = (byte) 0x7F;
byte b = (byte) s;
Entre tipos reales:
float a double:
float f = 1567.3;
double d = f;
double a float:
float f = (float) 56789.34;
float f = 56789.34f;
Entre tipos enteros y reales:
float a int:
int i = (int) 1505.67f; // i = 1505
double a long:
long l = (long) -1335345.45; // l = -1335345
int a float:
float f = 7501; // f = 7501.0f
long a double:
double d = 56780000; // d = 5678000.0
Entre tipos numricos y cadenas de texto:
int a String:
String st = new Integer(1500).toString(); // st = 1500
float a String:
String st = new Float(1500.5f).toString(); // st = 1500.0
String a int:
int i = new Integer("1500").intValue(); // i = 1500
int i = Integer.parseInt(1500);
String a float:
float f = new Float(1500.0f).floatValue(); // f = 1500.0f
float f = Float.parseFloat(1500.0f);
int a binario:
String st = Integer.toBinaryString(0x0F34); // st = 0000111100110100
Entre tipos carcter y enteros:
int a char:
char c = (char) 65; // c = A
char a int:
int i = A; // i = 65
30 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Entre tipos carcter y cadenas de texto:
char a String:
String st = String.valueOf(A); // st = A
String a char:
String st = hola;
char c = st.charAt(0); // c = h
CAPTULO 4
ESTRUCTURA DE UN PROGRAMA
A continuacin se presenta la estructura general de un programa de Java:
// encabezado de la clase
package geometria;
import java.util.Vector;
import estadisticas.*;
// definicin de la clase principal
public class Triangulo {
// seccion de declaracin de atributos
private float base, height;
// seccion de implementacin de mtodos
public float getArea() {
return (base * height) / 2;
}
}
4.1 Encabezado
El encabezado de una clase es lo primero que se escribe en un programa de Java, pero su presencia no
es obligatoria. En el encabezado especificamos el paquete al que pertenece la clase actual, y todas las
libreras de clases que va a utilizar en algn lugar del cdigo. Estas libreras pueden ser de Java o
propias del programador.
La instruccin package nos permite agrupar clases e interfaces. Java organiza sus libreras de clases en
paquetes de forma similar a C++. Los nombres de los paquetes son palabras separadas por puntos y se
almacenan en directorios que coinciden con esos nombres. De esta manera, a cada directorio de clases
de Java -o del programador- le corresponde un nombre de paquete.
sea paquete de la forma : nombreDirectorio(.nombreSubdirectorio)*
donde (*) indica que podemos incluir 0 o ms subdirectorios separados por (.)
sintaxis:
package paquete;
32 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
ejemplo:
El archivo Vector.java contiene el cdigo fuente de una clase de Java que est incluido originalmente
en el subdirectorio \java\util\ de la API; por lo tanto, el encabezado de esta clase debe contener la lnea
de cdigo:
package java.util;
La instruccin import nos permite utilizar clases que no estn en nuestro directorio de trabajo o en
nuestro proyecto; estas clases incluyen libreras de Java o libreras propias; el similar de C++ es la
directiva #include.
sintaxis:
import paquete.nombreClase;
import paquete.*;
Retomando el ejemplo anterior, todas las clases que deseen utilizar la clase Vector debern incluir la
siguiente lnea de cdigo:
import java.util.Vector;
o si se desea utilizar ms de una clase que se encuentre en un directorio:
import javax.swing.*;
Es importante saber que esta sentencia slamente incluye las clases que se encuentren en el directorio
\javax\swing\, lo que significa que no incluye las clases contenidas en los subdirectorios; para
incluirlas hay que especificar el nombre del subdirectorio. En el siguiente ejemplo se importan todas las
clases contenidas en los subdirectorios \event y \border.
import javax.swing.event.*;
import javax.swing.border.*;
Una clase que incluya estas 2 lneas en su encabezado podr utilizar todas las clases contenidas en los
paquetes javax.swing.event y javax.swing.border.
4.2 Definicin de la clase
Todo archivo que contenga cdigo Java deber tener asociado un nombre nico de acuerdo al paquete
(directorio) al que pertenezca, respetando la sintaxis definida en la Seccin 3.3.2. La extensin de tal
archivo debra ser .java. Adems, deber contener una sla clase principal con el mismo nombre del
archivo, la cual deber ser pblica y podr contener atributos y mtodos. Dentro de una clase tambin
se pueden definir subclases con sus propios atributos y mtodos; a esto se le denomina anidamiento de
clases. En captulos posteriores se presentarn programas de ejemplo que incluyen clases anidadas. Lo
ms recomendable es que el programador defina un archivo diferente por cada clase que vaya a
desarrollar.
sintaxis:
public class NombreClase {
// cuerpo del programa
}
CAPTULO 4: ESTRUCTURA DE UN PROGRAMA 33
ejemplo:
package miPaquete.geometria;
import miPaquete.estadisticas.*;
public class Triangulo {
}
Esta clase deber guardarse en el archivo: \miPaquete\geometria\Triangulo.java, y puede utilizar
todas las clases contenidas en el directorio: \miPaquete\estadisticas\ .
4.3 Declaracin de atributos
Los atributos son las variables globales de una clase que pueden ser llamadas dentro de cualquier
mtodo de la misma o por otras clases (si son protegidas o pblicas). Un atributo puede ser una variable
de tipo primitivo (int, float) o un objeto (su tipo es una clase).
sintaxis:
[visibilidad] [modificador] tipo_dato identificador [= valor_inicial]
visibilidad [vase Seccin 2.3]
o public para atributos pblicos
o protected para atributos protegidos
o private para atributos privados
o por omisin de visibilidad, el atributo es pblico dentro de las clases del mismo paquete; este
nivel de visibilidad es denominado Friendly o amigable en C/C++
modificador : cambia el comportamiento de un atributo [vase Captulo 6.1]
o final para atributos constantes
o static para atributos estticos
tipo_dato : es el tipo de dato del atributo (int, float, String, NombreClase )
identificador : nombre de la variable
valor_inicial : el valor predeterminado de una variable; si el atributo es un objeto el valor inicial
puede ser null o puede ser una instanciacin [vase Captulo 5.1].
ejemplos:
public String s = esto es una cadena pblica;
protected float base, altura, area;
private MiClase m = null;
Si dos o ms atributos comparten el mismo tipo de dato y los mismos modificadores, pueden declararse
en una sla lnea de cdigo separados por comas, como se observa en el segundo ejemplo.
4.4 Declaracin de mtodos
Los mtodos de una clase son funciones que pueden ser invocadas dentro de cualquier mtodo de la
misma clase o por otras clases (si no son privados).
34 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
sintaxis:
[visibilidad] [modificador] tipo_devuelto identificador(tipo1 id1, tipo2 id2,
, tipon idn)
donde n 0
visibilidad [vase Captulo anterior]
modificador: cambia el comportamiento de un mtodo [vase Captulo 6.2]
o static para mtodos estticos
o abstract para mtodos abstractos
o synchronized para mtodos sincronizados
tipo_devuelto : es el tipo de dato que devuelve el mtodo; void si no devuelve nada; el tipo devuelto
puede ser primitivo o una clase
identificador: nombre del mtodo
tipo1 id1, tipo2 id2, , tipon idn : lista de los parmetros de entrada; cada parmetro incluye el tipo
de dato y el nombre de la variable; el tipo de dato puede ser primitivo o una clase
ejemplos:
public float getArea(float height, float base)
public static String intToBinary(int i)
protected void removeRange(int fromIndex, int toIndex)
private Shape3D getShape3D(int index)
Cabe mencionar que no pueden existir 2 mtodos con el mismo nombre y los mismos parmetros de
entrada dentro de una clase. Cuando tenemos 2 mtodos con el mismo nombre y tipo devuelto, pero
con diferentes parmetros de entrada se dice que realizamos sobrecarga de funciones.
4.4.1 Invocacin de mtodos y sentencia return
Si el tipo devuelto por el mtodo es void, entonces el mtodo no devuelve ningn valor, y la sentencia
return nos servir para abandonar el mtodo en cualquier momento
sintaxis:
return;
ejemplo:
public void iniciarTriangulo(float b, float a) {
if(a == 0 || b == 0) return; // si algn parametro es 0, abandonar el mtodo
base = b;
altura = a;
}
Para invocar un mtodo cuyo tipo devuelto es void, especificamos el nombre del mtodo y enseguida
los parmetros de entrada entre parntesis. Si el mtodo no tiene parmetros de entrada, los parntesis
no se eliminan en la invocacin.
ejemplos:
inciarTriangulo(10.0f, 7.5f);
borrarTriangulo();
CAPTULO 4: ESTRUCTURA DE UN PROGRAMA 35
Si el tipo devuelto por el mtodo no es void, entonces el mtodo tiene que devolver un valor cuyo tipo
de dato sea igual al tipo devuelto, en caso contrario, se genera un error de sintaxis. Ese valor ser
recibido por el proceso que invoc al mtodo.
sintaxis:
return expresion;
donde expresion puede ser:
a) una variable primitiva: x, aa, y
b) un objeto: cadenaTexto, miArreglo, vector1, triangulo3
c) una constante : 0, null, -15.6, ja, PI, new Circulo(15) [vase Captulo 5.1]
d) una operacin : x * y, (base * altura) / 2, s + hola
ejemplo:
public float obtenerCociente(float numerador, float denominador) {
if(denominador == 0.0f) return 0.0f;
float cociente = numerador / denominador;
return cociente; // otra solucion: return numerador / denominador;
}
Para invocar un mtodo que devuelve un tipo diferente a void utilizamos la misma sintaxis que para un
mtodo que devuelve void, con la excepcin de que aqu lo tratamos si fuera un valor cuyo tipo est
dado por el tipo devuelto.
ejemplos:
promedio = obtenerMayor(x, 5, 7); // donde x, promedio ya estn declaradas
float cociente = obtenerCociente(10.0f, 0.0f); // cociente = 0.0f
float prom = (obtenerCociente(10.0f, 2.0f) + obtenerCociente(10.0f, 5.0f))/2;
// prom = (5.0f + 2.0f) / 2 = 3.5f
lo siguiente no est bien, porque un valor no puede estar aislado:
obtenerCociente(12.84f, 8.56f);
es como si escribiramos:
1.5f;
Cabe mencionar que debe existir una sentencia return para cada ruta posible que nos lleve a la
terminacin del mtodo. Esto es muy frecuente cuando hacemos uso de las sentencias de salto y de
bucle [vase Seccin 3.5].
ejemplo:
public int obtenerMayor(int a, int b, int c) {
if(a >= b)
if(a >= c) return a;
else return c;
else if(b >= c) return b;
else return c;
}
4.4.2 Constructores
El primer mtodo que se ejecuta al crear un objeto es el constructor de la clase al que pertenece este
objeto. El constructor nos permite realizar algn proceso de inicializacin antes de que se comiencen a
utilizar los mtodos de la clase. El constructor debe ser pblico, no devuelve ningn valor y su nombre
deber ser igual al de la clase al que pertenece. Una clase puede tener 0 ms constructores, donde
cada uno deber tener una lista diferente de parmetros de entrada.
36 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
sintaxis:
public NombreClase(/* parametros de entrada */) {
Cuando definimos ms de un constructor en una clase (con diferentes parmetros de entrada) se dice
que realizamos sobrecarga de constructores.
ejemplo:
public class Triangle {
private float base, height;
public Triangle(float b, float h) {
base = b; // en este constructor, se especifican de manera
height = h; // inicial los parmetros del tringulo
}
public Triangle(float b) {
base = b; // en este constructor, el valor de la altura
height = 2 * h; // est en funcin de la base
}
public setBase(float b) {
base = b;
}
public setHeight(float h) {
height = h;
}
public float getArea() {
return (base * height) / 2;
}
}
4.4.3 Mtodo main
Una aplicacin de Java consta de una o ms clases, pero una de ellas ser necesariamente la puerta de
entrada para la ejecucin de la aplicacin, esto es, al menos una clase deber incluir el mtodo principal
de la aplicacin a partir del cual se crean todas las dems clases; al igual que C/C++ y otros lenguajes
de programacin, Java consta con un mtodo principal (main) el cual se invocar automticamente al
momento de ejecutar una clase con el comando c:\>java NombreClase, o a travs de algna funcin
de un IDE (Integrated Development Environment) de Java.
sintaxis:
public static void main(String[] args) {
Como en C/C++, el nombre del mtodo principal de Java es main y devuelve void, adems es pblico,
esttico [vase Seccin 6.2] y espera un arreglo de cadenas de texto. Este arreglo representa la lista de
argumentos de la aplicacin. A diferencia de C/C++, este mtodo no espera la longitud del arreglo (int
argc) ya que todo arreglo en Java tiene un atributo length til para obtener la cantidad de elementos
[vase Seccin 7.1.3].
ejemplo:
public class UnaClase { // clase que imprime el area de un circulo
final PI = 3.1416; // de radio 1.5
public static void main(String[] args) {
float radio = 1.5f;
float area = PI * Math.pow(radio, 2); // pow es un metodo esttico de la clase
// Math para efectuar la potenciacin
System.out.println(El radio es: + area);
}
}
CAPTULO 4: ESTRUCTURA DE UN PROGRAMA 37
ejecucin:
c:\>java UnaClase
El radio es: 7.0686
c:\>
Cabe mencionar que una clase que solamente tenga el mtodo main pierde las caractersticas de la
orientacin a objetos y se comporta como cualquier programa estructurado de C/C++.
4.5 mbito de una variable
El mbito de una variable representa el contexto dentro del cual una variable est definida y puede ser
utilizada. Las variables de Java slo son vlidas desde el punto donde estn declaradas hasta el final de
la sentencia compuesta que la engloba. Se pueden anidar estas sentencias compuestas, y cada una puede
contener su propio conjunto de declaraciones de variables locales. Sin embargo, no se puede declarar
una variable con el mismo nombre que una de mbito exterior. El siguiente ejemplo intenta declarar
dos variables separadas con el mismo nombre. En C/C++ son distintas, porque estn declaradas dentro
de mbitos diferentes; sin embargo, esto es ilegal en Java.
ejemplo:
public void imprimeDobles(int max) { // crea un mbito
int j = 0;
for(int i = 0; i < max; i ++) { // crea un nuevo mbito
int j = 2 * i; // error de compilacin
System.out.println(j);
}
}
Las variables se puede declarar en tres lugares diferentes:
1. En el encabezado de la clase: pueden ser utilizados por todos los mtodos de la clase; pueden ser
pblicos, privados o protegidos
2. Dentro de un mtodo: son reconocidos dentro del mtodo donde se declar; desaparecen cuando se
abandona el mtodo
3. En un bucle (if/else, switch, for, while, do/while): son reconocidos slamente dentro del bucle;
dejan de existir al terminar el bucle
ejemplo:
public class Estadisticas { // ambito 1 inicia
private int limite;
public Estadisticas(int limite) { // ambito 2 inicia
this.limite = limite;
} // ambito 2 termina
public int obtenerSumatoria( ) { // ambito 3 inicia
int sum = 0;
for(int i = 0; i < limite; i ++) { // ambito 4 inicia
sum += i;
} // ambito 4 termina
return sum;
} // ambito 3 termina
} // ambito 1 termina
Variables de clase: limite
Variables de metodo: limite, sum
Variables de bucle: i
38 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Cabe mencionar que Java permite declarar variables de mtodo o de bucle con el mismo nombre que
las variables de clase; en ese caso, cuando se realiza un llamado a tales variables, se estar refiriendo a
las variables de mtodo/bucle. Para poder distinguir las variables de clase (atributos) de las variables de
mtodo/bucle se utiliza la instruccin this seguida de un punto y el nombre del atributo, como se puede
apreciar en el ejemplo anterior.
4.6 Traduccin de una clase en notacin UML a una clase en cdigo Java
En El Captulo 2.2 se present la notacin UML para representar grficamente una clase, pero no se
incluyeron tipos de datos de los atributos ni los tipos devueltos de los mtodos. La sintaxis para
especificar tales situaciones es la siguiente:
* nombreAtributo : tipoDato
* nombreMtodo(tipo1 id1, , tipon idn) : tipoDevuelto
donde * { +, #, -}
NOTA: si tipoDevuelto = void entonces no se especifica en el modelo
A continuacin se presentan dos ejemplos prcticos de codificacin de una clase de Java a partir de su
modelo en notacin UML.
Cuadrado
+ Cuadrado(float l)
+ Cuadrado(int x, int y, float l)
+ mover(int dx, int dy)
+ obtenerLado() : float
+ redimensionar(int dl)
lado : float
# posX, posY: int
ColorRGB
+ ColorRGB(int r, int g, int b)
+ ColorRGB( )
+ R, G, B : int
public class ColorRGB {
public int R, G, B;
public ColorRGB(int r, int g, int b) {
R = r; // color Rojo
G = g; // color Verde
B = b; // color Azul
}
public ColorRGB() {
R = 127; // crear un color gris
G = 127; // de manera predeterminada
B = 127;
}
}
public class Cuadrado {
private float lado;
protected int posX, posY;
public Cuadrado(float l) {
lado = l;
}
public Cuadrado(int x, int y, float l) {
posX = x;
posY = y;
lado = l;
}
public void mover(int dx, int dy) {
posX += dx;
posY += dy;
}
public float obtenerLado() {
return lado;
}
public void redimensionar(int dl) {
lado += l;
}
}
CAPTULO 5
OBJETOS
Para comprender la relacin existente entre un objeto y una clase, analicemos la siguiente frase:
Un plano es a un conjunto de casas, como una clase es a un conjunto de objetos
As como un plano es un modelo que describe la manera en que se va a construir una casa, una clase es
una plantila que describe la manera en que se va a comportar un objeto; todas las casas que se
construyan a partir de un mismo plano debern exhibir un conjunto de caractersticas visuales y
funcionales en comn. Similarmente, todos los objetos creados a partir de una clase compartirn un
conjunto de atributos y mtodos que definirn su comportamiento. A partir de un plano podemos crear
muchas casas y a partir de una clase podemos crear muchos objetos.
5.1 Creacin
Una clase por s sola no tiene vida, es decir, no puede ejecutarse; para poder ejecutar una clase y
utilizar sus atributos y mtodos es necesario crear una instancia de esa clase: un objeto. Un objeto, en
cambio, s tiene vida: se crea, se utiliza, evoluciona y, tarde o temprano, es destruido (por el
programador o por el recolector de basura).
Cuando creamos un objeto, estamos reservando un espacio de memoria en donde se almacenar el
estado del objeto: los valores de todos sus atributos y de las variables del mtodo en ejecucin. Una
variable cuyo tipo sea un objeto es realmente una referencia o apuntador a tal espacio de memoria. Para
crear un objeto instanciar una clase utilizamos la sentencia new de la siguiente manera:
sintaxis:
Clase1 objeto1 = new Clase1(/* parmetros */); // crea un objeto y lo asigna
// a una variable
new Clase1(/* parmetros */); // crea un objeto slamente
ejemplos:
ColorRGB color1 = new ColorRGB(190, 128, 50);
Cuadrado cuadrado1 = new Cuadrado(x, y, 3.5f);
new Aplicacion();
tambin podemos crear objetos en la invocacin de mtodos o con la sentencia return:
40 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
ejemplos:
String s = invertirTexto(new String(mensaje a invertir));
cambiarFigura(indice, new Cuadrado(x, y, lado));
return new Triangulo(base, altura);
5.2 Uso de atributos y mtodos de clase
Un programa en ejecucin es una coleccin de objetos, donde dichos objetos interactuantes son creados
y destrudos. Esta interaccin se basa en mensajes que son mandados de un objeto a otro, donde el
emisor le pide al receptor que aplique un mtodo a s mismo. Es entonces a partir de los objetos que
podemos manipular los atributos e invocar los mtodos de una clase, siempre y cuando stos sean
declarados como pblicos. Para realizar ello especificamos el del objeto y el nombre del
atributo/mtodo pblico a utilizar separados por un punto.
sintaxis:
objeto.atributo = 15;
objeto.metodo(/* parmetros */); // metodo que devuelve void
variable = objeto.metodo(/* parmetros */); // metodo que devuelve algo
ejemplos:
ColorRGB color1 = new ColorRGB();
color1.R = 156;
color1.B = color.G - 10;
System.out.println(color es: + color1.R + , + color1.G + , + color1.B);
// imprime: color es: 156, 127, 117
Cuadrado c = new Cuadrado(10, 20, 15.5f);
c.mover(2, -3); // atributos posX y posY valen 12 y 17, respectivamente
c.redimensionar(1.5f);
float lado = c.obtenerLado(); // lado = 17.0f;
c.redimensionar(c.obtenerLado());
System.out.println(c.obtenerLado()); // imprime 34.0f;
5.3 Pase por valor / referencia
El pase por valor se efecta si, al invocar un mtodo, las variables que se incluyeron en los parmetros
no modificarn su valor al terminar el mtodo. Internamente, la aplicacin realiza una copia de la
variable en una nueva localidad de memoria. En el pase por referencia, por lo contrario, una variable
enviada como parmetro s podr modificar su valor al terminar el mtodo; esto se debe a que el
mtodo recibe realmente la localidad de memoria donde se encuentra dicha variable. En C/C++ el pase
por referencia se realiza utilizando apuntadores. Como Java maneja no apuntadores, de manera
predeterminada el pase por valor en Java se realiza con variables cuyo tipo de dato sea primitivo (int,
char, float) o String, y el pase por referencia se lleva a cabo utilizando objetos, esto es, variables cuyo
tipo de dato sea una clase.
ejemplo:
public class Pase {
public void aumentarRojo(ColorRGB color, int r) {
r += 15;
color.R += 15;
}
public Pase() {
int r = 50;
ColorRGB color = new ColorRGB(r, 150, 200);
aumentarRojo(color, r); // color pasa por referencia, r por valor
CAPTULO 5: OBJETOS 41
System.out.println(color.R); // imprime 65 (objeto modificado)
System.out.println(r); // imprime 50 (variable intacta)
}
public static void main(String[] args) {
new Pase();
}
}
Lo mismo sucede en la igualacin de variables: si las variables son de tipo primitivo, se pasa el valor
del dato origen a la variable destino, pero las variables son independientes entre s. En cambio, si las
variables son objetos, se pasa la referencia del dato origen a la variable destino, y cualquier cambio que
suceda en el objeto fuente se ver reflejado en el destino, y viceversa.
ejemplo:
ColorRGB c1 = new ColorRGB(100, 200, 150);
ColorRGB c2 = c1;
System.out.println(c2.R); // imprime 100
c1.R = 40;
System.out.println(c2.R); // imprime 40
5.4 Alcance de un objeto
Los objetos de Java tienen un tiempo de vida y consumen recursos durante el mismo; cuando un objeto
ya no se va a usar debera liberar el espacio que ocupaba en la memoria de forma que las aplicaciones
no la agoten. En Java, la liberacin de memoria es responsabilidad de un proceso llamado recolector
automtico de basura o garbage collector, en ingls. El recolector de basura monitorea el alcance de
los objetos creados y elimina aquellos que ya se salieron del alcance. Un objeto se dice que se sale del
alcance cuando ya no existe una referencia hacia l, es decir, no existe una variable que apunta al
espacio de memoria asignado para tal objeto. Normalmente, este alcance se pierde cuando se crea un
nuevo objeto x utilizando una variable que apuntaba previamente a un objeto y; en este caso, se dice
que y queda fuera del alcance.
ejemplo:
String s; // memoria no asignada, objeto no creado
s = new String(hola); // memoria asignada, objeto creado
s = adis; // nueva memoria asignada, nuevo objeto
// creado con la misma variable
Al final de la tercera sentencia, el primer objeto creado de nombre s que contiene la cadena hola se
ha salido del alcance porque ya no hay forma de acceder a l; como consecuencia de ello, este objeto es
marcado y eliminado posteriormente por el recolector de basura. Una forma de liberar inmediatamente
un objeto es asignndole un valor null.
ejemplo:
ColorRGB color = new ColorRGB(100, 200, 150);
color = null; // se perdi el alcance al objeto; en este momento
// el recolector de basura deber marcar el objeto
// para eliminarlo posteriormente
CAPTULO 6
MODIFICADORES
Los modificadores son palabras reservadas de Java que se colocan delante de la definicin de los
atributos o mtodos de una clase con el fin de proporcionarles una caracterstica adicional. Un
modificador define la forma en que sern utilizados los atributos y mtodos.
En captulos anteriores se han descrito los modificadores de acceso, private, protected y public, las
cuales nos permiten limitar el acceso a los componentes de una clase o a la clase en si.
A continuacin se presentan los principales modificadores que proporciona Java, y se clasifican de
acuerdo al tipo de elemento que califican: atributo, mtodo o clase.
6.1 Para atributos
final: un atributo final nunca podr cambiar su valor durante la ejecucin de la clase que la contiene; se
utiliza para declarar constantes.
sintaxis:
[visibilidad] final identificador = valor;
ejemplo:
public final double PI = 3.1416;
no se podr hacer esto:
public void iniciarPI() {
PI = 3.141592;
}
static: un atributo esttico es una variable que no se asocia a una instancia de una clase (objeto), sino
que se asocia a la clase misma; no hay una copia del dato para cada objeto, sino una sla copia que es
compartida por todos los objetos pertenecientes a la clase; si uno de los objetos cambia el valor del
atributo, ste cambiar para todos los objetos.
sintaxis:
[visibilidad] static tipoDato identificador [= valor_inicial];
44 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
ejemplo:
public class Punto { Punto p1 = new Punto(1,-3);
int posX , posY; Punto p2 = new Punto(3, 10);
static int numPuntos = 0; Punto p3 = new Punto(12, 6);
// el programa imprimira:
Punto(int posX, int posY) { // 1 2 3
this.posX = posX;
this.posY = posY;
numPuntos ++ ;
System.out.print(numPuntos + );
}
}
Un atributo puede ser public, static y final al mismo tiempo, lo que indica que tal atributo ser una
constante compartida entre muchas clases; adems, podremos tener acceso a tal atributo sin realizar una
instancia de la clase que la contiene. Un ejemplo tpico es el atributo PI de la clase Math:
public final class Math {
public static final double PI = 3.1516926535;
}
modo de uso:
float diametro = 2 * radio * Math.PI;
Math.PI += 2; // incorrecto
6.2 Para mtodos
static: al igual que con los atributos, un mtodo esttico no es propia de una instancia de una clase, sino
de la clase misma; lo anterior implica que podemos utilizar un mtodo esttico (pblico) sin crear una
instancia de la clase que la contiene, sino especificando slamente el nombre de su clase. Un mtodo
esttico slamente accede a variables estticas. Cualquier variable declarada dentro de un mtodo
esttico ser tambin esttica.
sintaxis:
[visibilidad] static tipoDevuelto nombreMetodo( /* parametros */) {
ejemplos:
public class Punto { Punto p1 = new Punto(1,-3);
int posX , posY; Punto p2 = new Punto(3, 10);
static int numPuntos = 0; Punto p3 = new Punto(12, 6);
int p = p3.obtenerPuntos();
Punto(int posX, int posY) { // p = 3
this.posX = posX;
this.posY = posY;
numPuntos ++ ;
}
public static int obtenerPuntos() {
return numPuntos;
}
}
public class Stats {
public static float obtenerMayor(float a, float b) {
if(a >= b) return a;
else return b;
}
}
CAPTULO 6: MODIFICADORES 45
modo de uso:
float m = Stats.obtenerMayor(3.5, 100); // m = 100
abstract: un mtodo abstracto es aquel que no se implementa, es decir, nada ms se especifica su
prototipo en la clase; los mtodos abstractos pertenecen exclusivamente a clases abstractas. Ms
detalles sobre mtodos y clases abstractas en la Seccin 8.3.
sintaxis:
[visibilidad] abstract tipoDevuelto nombreMetodo( /* parametros */);
synchronized: un mtodo sincronizado slo puede ser invocado por un proceso a la vez; definir
mtodos sincronizados nos permite gestionar la concurrencia. Cuando se invoca un objeto
sincronizado, el objeto que lo contiene se bloquea hasta que finalice el mtodo. Si existen muchos
mtodos sincronizados, slo un mtodo puede estar activo en un objeto a la vez; todos los dems
procesos que intentan invocar mtodos sincronizados debern esperar. Estos mtodos son tiles
slamente cuando se desarrollan aplicaciones multihilos [vase Captulo 10].
sintaxis:
[visibilidad] synchronized tipoDevuelto nombreMetodo( /* parametros */) {
6.3 Para clases
abstract: una clase abstracta no puede ser instanciada, slamente derivada; las clases abstractas nos
sirven para definir un comportamiento en comn de algn conjunto de clases (las subclases); una clase
abstracta puede contener mtodos abstractos, los cuales debern ser implementados por todas sus
subclases. Para ms detalles sobre clases abstractas, consulte la Seccin 8.3.1.
sintaxis:
public abstract class NombreClase {
final: una clase final no podr tener clases derivadas o subclases; las clases finales cierran la cadena de
la herencia [vase Captulo 8]. Una clase declarada como final se considera como una clase completa,
la cual no es necesaria especializarla para agregarle funcionalidad. Ejemplos clsicos de clases finales
son: String y Math. Algunas de las razones por las que se declaran clases finales son: desempeo,
diseo del sistema, seguridad e integridad de objetos. Cabe mencionar que una clase no puede ser final
y abstract al mismo tiempo.
sintaxis:
public final class NombreClase {
lo siguiente no ser permitido:
public final class NombreClase1 extends NombreClase {
En cuanto al tema de seguridad, un mecanismo que utilizan mucho los hackers para alterar sistemas es
crear una subclase de una clase perteneciente a una aplicacin, y luego sustituir la clase original por su
clase. La subclase del hacker tendr la misma apariencia y ser tratada por Java de la misma manera
que la clase original, pero har cosas diferentes, como causar dao u obtener informacin privada.
46 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Como ejemplo de alteracin de clases, a continuacin se presenta una clase que hereda de la clase
java.util.Vector; esta clase, tambin llamada Vector, sobreescribe el mtodo size() de tal manera que
devuelve el doble del tamao real del vector. Para ms detalles del uso de vectores y la sintaxis de la
herencia de clases, vanse las Secciones 7.2 y 8.2, respectivamente.
public class Vector extends java.util.Vector {
public Vector() {
super(); // inicializa la clase padre
}
public int size() { // sobrecarga del mtodo size()
return 2 * super.size(); // obtiene el tamao del vector y lo duplica
}
}
una aplicacin que utilice la clase Vector:
Vector v = new Vector(); // se cre un vector
v.addElement(new String("elemento 1")); // se agreg un elemento
v.addElement(new String("elemento 2")); // se agreg otro elemento
System.out.println(v.size()); // imprime 4, en lugar de 2
6.3.1 Clases no derivables / no instanciables
Una forma alternativa y muy til para especificar que una clase no se puede derivar es definiendo un
constructor privado. El compilador de Java no permitir extender tal clase porque el mtodo constructor
no es alcanzable desde fuera de su clase. El uso de esta tcnica tiene como consecuencia que no
podamos crear instancias de una clase fuera de ella.
El esquema adoptado por la siguiente clase es til para evitar que se realice ms de una instancia de una
clase:
public class Singular {
static private Singular singular = new Singular();
private Singular() {
System.out.println("creado");
// algun proceso de inicialiacin
}
public static Singular crearSingular() {
return singular;
}
}
modo de uso:
Singular sin1 = Singular.crearSingular(); // sin1 y sin2 representan 2
Singular sin2 = Singular.crearSingular(); // variables para el mismo objeto
Singular.crearSingular(); // otra forma de invocar el mtodo
// al final de la ejecucin se ver impreso creado una sla vez (no 3)
Es para considerar que si definimos un constructor protegido, la clase que lo contiene nicamente podr
ser instanciada dentro de las clases derivadas.
6.4 Representacin de modificadores utilizando notacin UML
Para simplificar la representacin de modificadores dentro del modelo de una clase, se adoptarn las
siguientes convenciones que representan una extensin de la notacin UML.
CAPTULO 6: MODIFICADORES 47
Atributo final: NEGRITA
Atributo esttico: subrayado
Atributo final esttico: NEGRITA-SUBRAYADO
Mtodo abstracto: cursiva ( )
Mtodo esttico: subrayado ( )
Mtodo sincronizado: sync nombreMetodo ( ... )
Clase final: Negrita
Clase abstracta: Cursiva
ejemplo:
clase correspondiente:
public final class Console {
private static String text = ""; // lnea leda desde la consola
private static void readLine() { // lee una lnea de la consola y lo
// asigna al atributo text
}
public static float getf() { // convierte la lnea leda en flotante
// y lo devuelve
}
public static int geti() { // convierte la lnea leda en entero
// y lo devuelve
}
public static String gets() { // devuelve la lnea leda
}
}
Console
readLine ( )
+ getf ( ) : float
+ geti ( ) : int
+ gets ( ) : String
text: String
CAPTULO 7
ALMACENAMIENTO DE DATOS
En este captulo se estudian 3 tcnicas muy comunes provistas por Java para el almacenamiento de
colecciones de datos en memoria: arreglos, vectores y tablas hash.
7.1 Arreglos
Un arreglo es una sucesin ordenada y finita de datos del mismo tipo. En Java, podemos declarar
arreglos de cualquier tipo primitivo e incluso de objetos. De manera similar a las cadenas de caracteres,
no se puede conocer la longitud que tendr un arreglo en el momento de su declaracin; por esta razn,
Java trata a los arreglos como objetos que necesitan instanciarse antes de ser utilizados, y liberarse al
concluir su uso.
7.1.1 Declaracn
Para declarar un arreglo en Java, especificamos el tipo de elementos que va a almacenar, seguido del
identificador del arreglo y una pareja de corchetes para especificar que estamos declarando un arreglo.
Al igual que en otros lenguajes de programacin, tambin podemos declarar arreglos de dos o ms
dimensiones. En estos casos agregamos una pareja de corchetes por cada dimensin adicional.
sintaxis:
tipoDato identificador[]; // arreglo de una dimensin
tipoDato[] identificador; // arreglo de una dimensin
tipoDato identificador[][]; // arreglo de ms de una dimensin
tipoDato[][] identificador; // arreglo de ms de una dimensin
ejemplo:
String listaClaves[];
Triangulo triangulos[];
float coordenadas2D[][];
double[][][] coordenadas3D;
7.1.2 Instanciacin
Una vez declarado los arreglos, se debe proceder a la instanciacin (creacin) para reservar un espacio
de memoria dentro del cual se almacenarn los elementos del arreglo. Si utilizamos el arreglo sin crear
previamente la instancia encontraremos errores en tiempo de ejecucin. Debido a que un arreglo es
50 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
tratado como un objeto, para instanciarlo utilizamos la instruccin new seguida del tipo de dato que
almacena el arreglo y el(los) tamao(s) especificado(s) entre corchetes. Una vez definida la longitud del
arreglo, sta no podr cambiar durante la ejecucin del programa; la nica forma de redefinirla es
volviendo a instanciar el arreglo, lo que ocasionar la prdida de datos.
sintaxis:
identificador = new tipoDato[tamao]; // arreglo de una dimensin
identificador = new tipoDato[tamao 1][tamao n]; // arreglo de n dimensiones
donde: tamao es una variable o constante de tipo entero y mayor que cero.
ejemplos:
listaClaves = new String[35];
triangulos = new Triangulo[max];
coordenadas2D = new float[25][80];
coordenadas3D = new double[100][100][100];
Tambin podemos declarar y crear el arreglo en una sla lnea de cdigo, por ejemplo, en la seccin de
declaracin de atributos de la clase.
sintaxis:
tipodato identificador[] = new tipoDato[tamao];
tipodato identificador[][] = new tipoDato[tamao 1][tamao n]
ejemplos:
String listaClaves[] = new String[35];
Triangulo[] triangulos = new Triangulo[max];
float coordenadas2D[][] = new float[25][80];
double[][][] coordenadas3D = new double[100][100][100];
7.1.3 Manipulacin
Para leer/modificar un elemento de un arreglo previamente declarado y creado se especifica el
nombre del arreglo y entre corchetes el ndice donde se encuentra el elemento a manipular.
sintaxis:
valor = nombreArreglo[indice];
valor = nombreArreglo[indice1][indice2];
nombreArreglo[indice] = nuevoValor;
nombreArreglo[indice1][indice2] = nuevoValor;
Si el arreglo almacena objetos, entonces se tiene que instanciar los elementos del arreglo antes de ser
utilizados.
sintaxis:
nombreArreglo[indice] = new tipodato(/* parametros */);
nombreArreglo[indice1][indice2] = new tipodato(/* parametros */);
Para obtener la longitud de un arreglo se utiliza el atributo length accesible desde cualquier arreglo:
sintaxis:
int longitud1 = nombreArreglo.length; // longitud de la 1ra dimensin
int longitud2 = nombreArreglo[0].length; // longitud de la 2da dimensin
CAPTULO 7: ALMACENAMIENTO DE DATOS 51
ejemplo:
public float obtenerMayor(float[] numeros) {
if(numeros == null) return 0; // si el arreglo no ha sido instanciado
float max = numeros[0];
for(int i = 1; i < numeros.length; i ++)
if(numeros[i] > max) max = numeros[i];
return max;
}
7.1.4 Ejemplo
A continuacin se presenta la clase Lienzo la cual contiene un arreglo que almacena objetos de tipo
Rectangulo; la clase Rectangulo est definida dentro de la clase Lienzo, y su constructor recibe la base
y la altura del rectngulo. Las lneas de cdigo en negrita realizan algn tipo de operacin con arreglos.
El constructor de Lienzo espera el nmero de rectngulos que se agregarn utilizando el mtodo
agregarRectngulo(). El mtodo obtenerMayor() devuelve el rectngulo con mayor rea.
public class Lienzo {
private Rectangulo[] rectangulos;
private int numRectanguloActual = 0;
class Rectangulo { // definicin de una clase anidada
public float base, altura;
public Rectangulo(float base, float altura) {
if(base > 0) this.base = base;
else this.base = 1.0f;
if(altura > 0) this.altura = altura;
else this.altura = 1.0f;
}
public float obtenerArea() {
return base * altura / 2;
}
}
public Lienzo (int no_rectangulos) {
if(no_rectangulos <= 0) no_rectangulos = 1;
rectangulos = new Rectangulo[no_rectangulos];
}
public void agregarRectangulo(float base, float altura) {
if(numRectanguloActual == rectangulos.length) return;
rectangulos[numRectanguloActual] = new Rectangulo(base, altura);
numRectanguloActual ++;
}
public Rectangulo obtenerMayor() {
if(rectangulos == null) return null; // si el arreglo no se ha creado
Rectangulo maxTemp = rectangulos[0];
for(int i = 1; i < rectangulos.length; i ++) {
float area = rectangulos[i].obtenerArea();
if(area > maxTemp.obtenerArea()) maxTemp = rectangulos[i];
}
return maxTemp;
}
public static void main(String[] args) {
Lienzo l = new Lienzo(3);
l.agregarRectangulo(3.5f, 4.4f);
l.agregarRectangulo(12.1f, -2.5f);
l.agregarRectangulo(10.0f, 2.6f);
Rectangulo recMayor = l.obtenerMayor();
System.out.println("Area mayor = " + recMayor.obtenerArea());
System.out.println("Rectangulo: " + recMayor.base + ", " + recMayor.altura);
} // imprime: Area mayor = 13.0
} // Rectangulo: 10,0, 2.6
52 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Ntese que Lienzo trabaja igual para cualquier nmero de rectngulos, pero tal nmero se deber
especificar inicialmente y no se podr cambiar a menos que se cree otro objeto de tipo Lienzo. Adems,
la aplicacin lanzar un error en tiempo de ejecucin en caso de que se agreguen menos rectngulos del
mximo. Si se agregan ms rectngulos del mximo, sern ignorados por la clase Lienzo. Esta tcnica
no se recomienda para manejar estructuras de datos de tamao dinmico.
7.1.5 Declaracin / instanciacin / rellenado
Existe una forma para declarar, crear y rellenar un arreglo con una sla lnea de cdigo. Esta solucin
es til cuando sabemos de antemano cuntos y cules son los elementos que va a contener un arreglo.
sintaxis:
tipodato nombreArreglo[] = { valorInicial1, , valorInicialn };
donde el tipo de dato de valorInicial debe ser tipodato
ejemplos:
int numeros[] = { 15, -34, 100, 0x3F, 0};
System.out.println(numeros[2]); // imprime 100
Rectangulo r = new Rectangulo(4, 2.5f);
Rectangulo[] rect = { new Rectangulo(10, 20), r, null };
System.out.println(rect[1].obtenerArea()); // imprime 5
Nota: no olvidar que el valor null puede ser asignado a cualquier objeto, sin importar a qu clase
pertenezca.
7.1.6 Igualacin
Recordando que los arreglos en Java son objetos, la igualacin de arreglos tiene el mismo efecto que la
igualacin de objetos, esto es, se copia la referencia al primer elemento del arreglo, y no se copian los
elementos en s. Si hacemos un cambio en el arreglo destino, ste se va a ver reflejado en el arreglo
fuente, y viceversa.
ejemplo:
float[] arreglo1 = { 1.5f, 3.4f, -12.75f, 36.0f };
float[] arreglo2;
arreglo2 = arreglo1; // igualacin de referencias
arreglo2[3] -= 5; // cambio en arreglo destino se ver
System.out.println(arreglo1[3]); // reflejado en el fuente; imprime 31.0
Si se desea copiar el contenido solamente, y mantener la independencia entre los arreglos, es necesario
crear un nuevo arreglo y copiar uno por uno cada elemento.
ejemplo:
float[] arreglo1 = { 1.5f, 3.4f, -12.75f, 36.0f };
float[] arreglo2 = new float[4];
for(int i = 0; i < arreglo1.length; i ++)
arreglo2[i] = arreglo1[i]; // igualacin de valores
arreglo2[3] -= 5; // cambio en arreglo destino no se ver
System.out.println(arreglo1[3]); // reflejado en el fuente; imprime 36.0
CAPTULO 7: ALMACENAMIENTO DE DATOS 53
7.2 Vectores
Para solucionar el problema inherente de los arreglos, el tamao fijo, Java proporciona la clase Vector,
la cual nos permite almacenar muchos datos en una estructura de datos de tamao variable.
Un vector es una sucesin ordenada de elementos de diferente tipo. Cada elemento deber ser un
objeto, debido a que los vectores no admiten variables primitivas. El tamao del vector es 0
inicialmente, pero podr cambiar dinmicamente conforme a las adiciones y eliminaciones realizadas.
7.2.1 Declaracin / creacin
La clase Vector forma parte del paquete java.util; por lo tanto, es necesario importar tal paquete en
todas las clases en donde se vayan a utilizar vectores. Es muy comn que declararemos e instanciemos
un vector en una sla lnea de cdigo, ya que el tamao del vector no se especifica en la creacin.
sintaxis:
import java.util.Vector;
Vector nombreVector = new Vector();
7.2.2 Adicin de elementos
Para agregar elementos utilizamos el mtodo miembro de la clase Vector: addElement( ); este mtodo
recibe como parmetro un objeto, el cual se agregar al final del vector; el tamao del vector se
incrementar en uno automticamente.
sintaxis:
nombreVector.addElement(nombreObjeto);
nombreVector.addElement(new NombreClase(/* parametros */ ));
Si se desea guardar un elemento en una posicin dada del vector y sustituir el elemento actual, se utiliza
el mtodo setElementAt( ) de la siguiente manera:
sintaxis:
nombreVector.setElementAt(nombreObjeto, indice);
donde: indice es un entero mayor o igual a 0 y menor al tamao actual del vector.
7.2.3 Navegacin
La navegacin de un vector involucra bsqueda, obtencin de elementos y conocimiento del tamao
del vector. Al igual que en un arreglo, la bsqueda en un vector es secuencial; podemos referirnos a un
elemento especfico a travs del ndice, esto es, el lugar relativo que ocupa dentro del vector.
Para obtener un elemento de un vector utilizamos el mtodo get( ), el cual recibe como parmetro la
posicin que ocupa tal elemento dentro del vector y devuelve un objeto de tipo Object; para tratar el
objeto devuelto como un objeto del tipo esperado es necesario convertirlo a travs de un cast.
sintaxis:
Clase objetoObtenido = (Clase) nombreVector.get(indice);
donde: indice es un entero mayor o igual a 0 y menor al tamao actual del vector.
Clase es el tipo de dato esperado del objeto situado en la posicin indice
54 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Para obtener el tamao actual del vector utilizamos el mtodo size( ) de la siguiente manera:
sintaxis:
int tamao = nombreVector.size();
7.2.4 Eliminacin de elementos
Para eliminar elementos de un vector, podemos utilizar el mtodo miembro: removeElementAt( ); este
mtodo recibe como parmetro la posicin del objeto que queremos eliminar. El tamao del vector se
decrementar en uno automticamente.
sintaxis:
nombreVector.removeElementAt(indice);
donde: indice es un entero mayor o igual a 0 y menor al tamao actual del vector.
Si se desea obtener la referencia del objeto que se desea eliminar del vector para realizar alguna
operacin con l antes de ser eliminado, utilizamos el mtodo remove( ) de la siguiente manera:
sintaxis:
Clase objetoEliminado = (Clase) nombreVector.remove(indice);
donde: indice es un entero mayor o igual a 0 y menor al tamao actual del vector.
Clase es el tipo de dato esperado del objeto a eliminar
Como el mtodo remove( ) devuelve un objeto de tipo Object, es necesario efectuar un cast al objeto
devuelto para convertirlo en un objeto del tipo esperado.
7.2.5 Ejemplo
A continuacin se implementa la clase Lienzo, presentada en El Captulo 7.1.4, utilizando vectores; esta
nueva versin va a permitir que se agreguen rectngulos de manera indefinida; para ejercitar los
mtodos vistos en las captulos anteriores, la clase va a permitir obtener, eliminar, sustituir y desplegar
los datos de un rectngulo, adems de obtener el rectngulo con el rea mayor. Las lneas de cdigo en
negrita realizan alguna operacin con vectores.
import java.util.Vector;
public class Lienzo {
private Vector rectangulos = new Vector();
class Rectangulo { // definicin de una clase anidada
public float base, altura;
public Rectangulo(float base, float altura) {
if(base > 0) this.base = base;
else this.base = 1.0f;
if(altura > 0) this.altura = altura;
else this.altura = 1.0f;
}
public float obtenerArea() {
return base * altura / 2;
}
}
public void agregarRectangulo(float base, float altura) {
rectangulos.addElement(new Rectangulo(base, altura));
}
CAPTULO 7: ALMACENAMIENTO DE DATOS 55
public Rectangulo obtenerRectangulo(int index) {
if(index < 0 || index >= rectangulos.size()) return null;
Rectangulo r = (Rectangulo) rectangulos.get(index);
return r;
}
public void eliminarRectangulo(int index) {
if(index < 0 || index >= rectangulos.size()) return;
rectangulos.removeElementAt(index);
}
public void sustituirRectangulo(int index, Rectangulo r) {
if(index < 0 || index >= rectangulos.size()) return;
rectangulos.setElementAt(r, index);
}
public void desplegarRectangulo(Rectangulo r) {
System.out.println(Base = + r.base + . Altura = + r.altura);
System.out.println(Area = + r.obtenerArea());
}
public int obtenerMayor() {
if(rectangulos.size() < 0) return -1;
int indiceMax = 0;
float maxTmp = obtenerRectangulo(0).obtenerArea();
for(int i = 1; i < rectangulos.size(); i ++) {
float area = obtenerRectangulo(i).obtenerArea();
if(area > maxTmp) {
maxTmp = area;
indiceMax = i;
}
}
return indiceMax;
}
public static void main(String[] args) {
Lienzo1 l = new Lienzo1();
l.agregarRectangulo(3.5f, 4.4f);
l.agregarRectangulo(12.1f, -2.5f);
l.agregarRectangulo(10.0f, 2.6f);
int indiceMayor = l.obtenerMayor();
Rectangulo r = l.obtenerRectangulo(indiceMayor);
l.desplegarRectangulo(r);
}
// la aplicacin imprime: Base = 10.0 Altura = 2.6
} // Area = 13.0
7.3 Tablas hash
Una tabla hash es una coleccin no ordenada y de tamao variable de objetos de diferente tipo. La
caracterstica ms importante de las tablas hash es que proporcionan acceso directo a cada elemento, en
lugar del tpico acceso secuencial inherente en los arreglos y vectores. El acceso a un elemento de la
tabla se realiza a travs de su clave asignada en lugar de utilizar su posicin relativa (ndice); esto surge
para solucionar el problema de desempeo implcito en los largos ciclos de bsqueda de elementos que
cumplan cierta condicin. Al igual que con los vectores, los elementos de las tablas hash no pueden ser
de tipo primitivo. El tamao inicial de la tabla es 0, pero podr cambiar dinmicamente conforme a las
adiciones y eliminaciones realizadas.
7.3.1 Declaracin / creacin
Java proporciona la clase Hashtable que nos sirve para implementar tablas hash; esta clase tambin
forma parte del paquete java.util, por lo tanto, es necesario importar tal paquete en todas las clases en
56 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
donde se vayan a utilizar tablas hash. Es muy comn que declararemos e instanciemos una tabla hash
en una sla lnea de cdigo, ya que su tamao no se especifica en la creacin.
sintaxis:
import java.util.Hashtable;
Hashtable nombreTabla = new Hashtable();
7.3.2 Adicin de elementos
Cada elemento deber tener asociado una clave nica en el momento de ser agregado a la tabla. Al
igual que los elementos, las claves son objetos; se recomienda utilizar claves de tipo String, Integer o
Float ya que podemos realizar igualaciones entre objetos de esos tipos, utilizando el mtodo miembro:
equals ( ).
Para agregar elementos utilizamos el mtodo miembro de la clase Hashtable: put( ); este mtodo recibe
como parmetro el elemento a agregar y el valor de la clave que tendr asignado; el tamao de la tabla
se incrementar en uno automticamente.
sintaxis:
nombreTabla.put(clave, elemento);
donde: clave y elemento son objetos
ejemplo:
miTabla.put(new Integer(105), new Rectangulo(10.0f, 30.0f));
7.3.3 Obtencin de elementos
Para obtener un elemento de una tabla hash utilizamos el mtodo miembro get( ); este mtodo recibe
como parmetro la clave del elemento a buscar y devuelve un objeto de tipo Object; para tratar el
objeto devuelto como un objeto del tipo esperado es necesario convertirlo a travs de un cast.
sintaxis:
Clase objetoObtenido = (Clase) nombreTabla.get(clave);
donde: clave es un objeto
Clase es el tipo de dato esperado del objeto que tiene asignado clave
ejemplo:
Rectangulo r = (Rectangulo) miTabla.get(new Integer(105));
7.2.4 Eliminacin de elementos
Para eliminar elementos de una tabla hash, se utiliza el mtodo miembro: remove( ); este mtodo recibe
como parmetro la clave asignada al objeto que queremos eliminar. El tamao de la tabla hash se
decrementar en uno automticamente.
sintaxis:
nombreTabla.remove(clave);
donde: clave es un objeto
CAPTULO 7: ALMACENAMIENTO DE DATOS 57
ejemplo:
tablaAlumnos.remove(new String(190));
Este mtodo tambin nos permite obtener la referencia del objeto que se desea eliminar para realizar
alguna operacin con l antes de ser eliminado.
sintaxis:
Clase objetoEliminado = (Clase) nombreTabla.remove(clave);
donde: clave es un objeto
Clase es el tipo de dato esperado del objeto que tiene asignado clave
ejemplo:
Alumno a = (Alumno) tablaAlumnos.remove(new String(190));
7.2.5 Ejemplo
A continuacin se presenta la clase Inventario, la cual contiene una tabla hash que almacena objetos de
tipo Producto; un producto tiene asignado una clave alfanumrica a travs de la cual podr ser
identificada, adems del nombre, el precio y las existencias. Para ejercitar los mtodos vistos en las
captulos anteriores, la clase va a permitir obtener, agregar, eliminar, modificar y desplegar los datos de
un producto. Las lneas de cdigo en negrita realizan alguna operacin con tablas hash.
import java.util.Hashtable;
public class Inventario {
private Hashtable productos = new Hashtable();
private Producto obtenerProducto(String clave) {
Producto p = (Producto) productos.get(clave);
if(p == null) Imprimir.mensaje(0, clave);
return p;
}
public void agregarProducto(String c, String n, float f, int e) {
productos.put(c, new Producto(c, n, f, e));
Imprimir.mensaje(1, c);
}
public void eliminarProducto(String clave) {
if(productos.remove(clave) == null) Imprimir.mensaje(0, clave);
else Imprimir.mensaje(2, clave);
}
public void cambiarPrecio(String clave, float precio) {
Producto p = obtenerProducto(clave);
if(p != null) {
p.cambiarPrecio(precio);
Imprimir.mensaje(3, clave);
}
}
public void desplegarProducto(String clave) {
Producto p = obtenerProducto(clave);
if(p != null) p.desplegar();
}
}
Para comprender mejor la operacin de la clase Inventario, a continuacin se lista el cdigo de las
clases Impresin y Producto, utilizadas en Inventario. La comprensin de las lneas de cdigo de cada
una de estas clases se deja al lector.
58 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
public class Producto {
private String clave;
private String nombre;
private float precio;
private int existencias;
public Producto(String clave, String nombre, float precio, int existencias) {
this.clave = clave;
this.nombre = nombre;
this.precio = precio;
this.existencias = existencias;
}
public String claveEs() {
return clave;
}
public void cambiarPrecio(float precio) {
if(precio > 0) this.precio = precio;
}
public void desplegar() {
Imprimir.linea('-', 30);
System.out.println(" Clave: " + clave);
System.out.println(" Nombre: " + nombre);
System.out.println(" Precio: " + precio);
System.out.println("Existencias: " + existencias);
Imprimir.linea('=', 30);
}
}
public final class Imprimir {
public static void mensaje(int no_mensaje, String clave) {
switch(no_mensaje) {
case 0: System.out.println("Clave " + clave + " no valida"); break;
case 1: System.out.println("Producto " + clave + " agregado con exito");
break;
case 2: System.out.println("Producto " + clave + " eliminado con exito");
break;
case 3: System.out.println("Precio del producto " + clave + " cambiado con
exito");
}
}
public static void linea(char caracter, int repeticion) {
for(int i = 0; i < repeticion; i ++)
System.out.print(caracter);
System.out.println();
}
}
La clase Hashtable proporciona el mtodo elements( ) que nos devuelve una sucesin ordenada de
todos los objetos almacenados en la tabla. El tipo de dato de esta sucesin es Enumeration, una
interfaz que proporciona dos mtodos tiles para realizar recorridos secuenciales y obtener los
elementos de la sucesin:
hasMoreElements( ) : devuelve true si la sucesin tiene ms elementos
false si lleg al final de la sucesin
nextElement( ) : devuelve el objeto siguiente; cast necesario
El siguiente mtodo se agregar a la clase Inventario de tal manera que se pueda imprimir un catlogo
de todos los productos dados de alta.
public void desplegarTodos() {
Enumeration e = productos.elements();
while(e.hasMoreElements()) {
CAPTULO 7: ALMACENAMIENTO DE DATOS 59
Producto p = (Producto) e.nextElement();
p.desplegar();
}
}
Otra forma de resolver el problema del recorrido en tablas hash es utilizando estructuras de datos
secuenciales indexados. Uniendo las capacidades de los vectores y las tablas hash, podemos designar
un vector para almacenar las claves de todos los productos y una tabla hash para almacenar la
informacin de cada producto. Cada vez que se agreguen o eliminen productos de la tabla, se tendr
que hacer una operacin similar en el vector. Cuando se busque un producto para edicin o consulta, no
ser necesaria la participacin del vector.
En cambio, cuando se desee realizar recorridos (barridos) del inventario de productos, se tendrn que
efectuar bsquedas secuenciales a lo largo del vector, y a travs de cada clave obtenida se buscar el
producto respectivo en la tabla hash. De esta manera, combinamos las facilidades para realizar accesos
directos en tablas hash con los recorridos secuenciales en vectores. Se deja al lector modificar la clase
Inventario de tal manera que utilice la tcnica secuencial indexado.
7.4 Implementacin de la asociacin de clases
a) Relacin 1..*, 1..+: Sea A la clase con multiplicidad 1 y B la clase con multiplicidad * + en una
relacin de asociacin. A tendr un atributo designado como clave y representado en el modelo de
manera explcita con un asterisco. B tendr un atributo de manera implcita cuyo tipo de dato ser el
mismo que el de la clave de A. El nombre y la visibilidad de este atributo estarn dados por la etiqueta
contenida en la relacin del lado de B, como se puede apreciar en el esquema de la Figura 23. De
manera predeterminada todo atributo clave es privado .
modelo:
Figura 23. Esquema de la relacin de asociacin 1..*
implementacin:
public class ClaseA {
private tipoDato idClase;
}
public class ClaseB {
private tipoDato id_A;
}
A travs del atributo id_A, la clase B podr hacer referencia al objeto de tipo A que tendr asociado.
ejemplo:
Factura
1 *
+ cliente
Cliente
* no_cliente : int
ClaseB
1 *
id_A
ClaseA
* idClase : tipoDato
...
60 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
implementacin:
public class Factura {
public int cliente; // este atributo almacenara la clave del cliente
// al que se le emite la factura
}
7.5 Implementacin de la agregacin de clases
a) Relacin 1..1: La clase Agregacin tendr un atributo implcito cuyo tipo de dato es la clase
Componente. El nombre y la visibilidad de tal atributo estar dado mediante una etiqueta situada en la
relacin del lado del componente, como se puede apreciar en la Figura 24. La instanciacin del
atributo implcito en la declaracin es opcional. La especificacin de multiplicidad 1 tambin lo es.
modelo:
Figura 24. Esquema de la relacin de agregacin 1..1
sintaxis:
public class Agregacion {
private Componente componente [= new Componente(/* parametros */)];
}
ejemplo:
implementacin:
public class Cubo {
protected Coord3D centro = new Coord3D(0.0f, 0.0f, -10.0f);
public ColorRGB color = new ColorRGB(127, 127, 127); // gris claro
}
b) Relacin 1..n, n 5: Cuando la cantidad de componentes del mismo tipo es relativamente pequea,
digamos n, la clase Agregacin deber incluir n atributos implcitos de tipo Componente, como se
puede observar en el modelo de la Figura 25. Ntese que la especificacin de la multiplicidad es
opcional cuando se escriben los nombres de los atributos en el modelo. En caso de que no se
especifiquen el nombre de los atributos, la multiplicidad s deber de aparecer.
modelo:
Figura 25. Esquema de la relacin de agregacin 1..n, n 5
Agregacin Componente
1
componente
Agregacin Componente
+ componente1
componente2
1
# centro
Cubo Coord3D
1
+ color
ColorRGB
CAPTULO 7: ALMACENAMIENTO DE DATOS 61
implementacin:
public class Agregacion {
public Componente componente1 = new Componente(/* parametros */);
private Componente componente2 = new Componente(/* parametros */);
}
ejemplo:
implementacin:
public class Factura {
private Fecha fecha_Emision;
private Fecha fecha_Pago;
}
c) Relacin 1..n, n > 5: Cuando la cantidad de componentes del mismo tipo es relativamente pequea,
digamos n, la clase Agregacin deber incluir en su lista de atributos un arreglo de n objetos de tipo
Componente, como se puede apreciar en la Figura 26.
modelo:
Figura 26. Esquema de la relacin de agregacin 1..n, n > 5
sintaxis:
public class Agregacion {
private Componente[] componentes = new Componente[n];
}
ejemplo:
implementacin:
public class Cubo {
protected Coord3D[] vertices = new Coord3D[8];
}
d) Relacin 1..*, 1..+: Cuando la cantidad de componentes del mismo tipo est indefinido, la clase
Agregacin deber incluir en su lista de atributos un vector, que almacenar una cantidad variable de
objetos de tipo Componente.
modelo:
Figura 27. Esquema de la relacin de agregacin 1..*, 1..+
Agregacin Componente
n
componentes
Agregacin Componente
* +
componentes
Factura Fecha
fecha_Emision
fecha_Pago
Cubo Coord3D
8
# vertices
62 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
sintaxis:
import java.util.Vector;
public class Agregacion {
private Vector componentes = new Vector();
}
ejemplo:
implementacin:
import java.util.Vector;
public class Factura {
public Vector prod_Vendidos = new Vector();
}
7.6 Ejemplo final
Se deja al lector como ejercicio la implementacin de las clases participantes en el modelo de un
sistema de facturacin representado en la Figura 28.
Figura 28. Modelo de un pequeo sistema de facturacin
Factura Detalle
+
+ prod_vendidos
+ 1
cliente
Detalle
prod_vendidos +
Cliente
* no_cliente: int
+ nombre: String
+ direccion: String
saldo : float
Factura
* no_factura: int
total : float
Producto
* no_producto: int
+ nombre: String
precio : float
existencias: int
* no_detalle: int
cantidad : int
subtotal : float
* 1
producto
Fecha
+ dia: int
+ mes: int
+ anho : int
+ dia_semana: String
fecha_emision
fecha_pago
CAPTULO 8
HERENCIA Y POLIMORFISMO
8.1 Introduccin
La herencia, trmino tomado de la biologa, es una propiedad esencial de la programacin orientada a
objetos y un mecanismo por el cual se pueden definir nuevas clases en trminos de clases ya existentes.
La herencia consiste en la transmisin de atributos y comportamientos desde una clase denominada
base, hacia otra clase denominada subclase o derivada. Una clase derivada puede ser a su vez una clase
base para otras subclases.
La herencia nos permite establecer una clasificacin jerrquica entre las clases semejante a la existente
en la biologa con los animales y las plantas. Por ejemplo, a partir de la clase Mamfero se puede crear
la subclase Felino, la cual heredar todas las propiedades de un Mamfero, pero adems podr tener
otras propiedades particulares.
La ventaja principal de la herencia es la reutilizacin de cdigo. Una vez que una clase ha sido
probada y depurada, el cdigo fuente de dicha clase no necesita modificarse para poder ampliar su
funcionalidad; esto se puede lograr creando una nueva clase que herede la funcionalidad de la clae base
y aada otros comportamientos.
En Java, todas las clases derivan de la clase Object de manera implcita, por lo tanto, cualquier clase
que definamos tendr de manera predeterminada los mtodos definidos en la clase Object, lo que
incluye un constructor sin parmetros.
Existen dos paradigmas complementarios que nos llevan a definir clases bases y derivadas
a) especializacin: cuando se desea ampliar la funcionalidad de un programa sin tener que modificar
el cdigo existente; a partir de la clase base creamos la clase derivada que extiende el
comportamiento de la clase base
b) generalizacin: cuando nos damos cuenta que divesos objetos guardan un comportamiento en
comn; a partir de las clases derivadas creamos la clase base que enumerar los atributos y
mtodos generales
64 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
8.2 Especializacin
Para entender mejor la especializacin, vamos a poner un ejemplo que simule la utilizacin de libreras
de clases para crear entornos grficos como Windows 9x. En este ejemplo definiremos una clase base
con funcionalidad limitada, para despus incrementarla a travs de una clase derivada.
8.2.1 Clase base
Supongamos que tenemos una clase que describe la conducta de una ventana muy simple, aquella que
no dispone de ttulo en la parte superior, por tanto no puede desplazarse, pero si cambiar de tamao
actuando con el ratn en los bordes derecho e inferior.
La clase Ventana tendr los siguientes miembros dato: la posicin (x, y) de la esquina superior
izquierda de la ventana y sus dimensiones: ancho y alto. Las funciones miembros, adems del
constructor sern las siguientes: la funcin desplegar( ) que muestra la posicin y las dimensiones
actuales de la ventana, y la funcin redimensionar( ) que nos permite cambiar el tamao.
A continuacin se despliega el cdigo de la clase base Ventana. Ntese que todos los atributos de la
clase son protegidos, con la intencin de que sean accesibles desde las clases derivadas de Ventana.
public class Ventana {
protected int x;
protected int y;
protected int ancho;
protected int alto;
public Ventana(int x, int y, int ancho, int alto) {
this.x = x;
this.y = y;
this.ancho = ancho;
this.alto = alto;
}
public void desplegar(){
System.out.println("Posicin: (" + x + ", " + y + ")");
System.out.println("Dimensiones: " + ancho + ", " + alto)
}
public void redimensionar(int dw, int dh){
ancho += dw;
alto += dh;
}
}
8.2.2 Objetos de la clase base
Como vemos en el cdigo, el constructor de la clase base recibe como parmetros los valores iniciales
de los atributos. De la siguiente manera creamos un objeto de la clase Ventana:
Ventana ventana = new Ventana(5, 10, 25, 30);
A partir del objeto ventana podemos invocar los mtodos pblicos de la clase Ventana, de la siguiente
manera:
ventana.desplegar();
ventana.redimensionar(3, -2);
ventana.desplegar ();
CAPTULO 8: HERENCIA Y POLIMORFISMO 65
El programa imprime el siguiente texto:
Posicin: (5, 10)
Dimensiones: 25, 30
Posicin: (5, 10)
Dimensiones: 35, 40
8.2.3 La clase derivada
Incrementamos la funcionalidad de la clase Ventana definiendo una clase derivada que llamamos
Ventana1. Los objetos de dicha clase tendrn todas las caractersticas de los objetos de la clase base,
pero adems tendrn un ttulo y se podrn desplazar (se simula el desplazamiento de una ventana con el
ratn). La clase derivada heredar los atributos y mtodos de la clase base; adicionalmente tendr un
atributo para almacenar el ttulo de la ventana y un mtodo para mover la ventana.
A continuacin se despliega el cdigo de la clase base Ventana1. Ntese que el atributo titulo es
protegido para que pueda ser accesible desde las clases derivadas de Ventana1.
public class Ventana1 extends Ventana {
protected String titulo;
public Ventana1(int x, int y, int ancho, int alto, String titulo) {
super(x, y, ancho, alto);
this.titulo = titulo;
}
public void desplegar(){
System.out.println("Ttulo: " + titulo);
super.desplegar();
}
public void desplazar(int dx, int dy){
x += dx;
y += dy;
}
}
La instruccin extends indica que la clase Ventana1 extiende a o es una subclase de Ventana. La
primera sentencia del constructor de Ventana1 realiza una llamada al constructor de la clase base o
superclase mediante la palabra reservada super. A travs de esta lnea de cdigo se inicializan los
atributos x, y, ancho y alto pertenecientes a la clase base.
Si en la clase base se define al menos un constructor que tenga parmetros de entrada, las subclases
debern tener por lo menos un constructor en cuya primera lnea deber estar la sentencia super con los
parmetros adecuados para invocar a uno los constructores de la superclase.
Cuando una subclase implementa un mtodo que tiene el mismo nombre y parmetros de E/S que
alguno de la superclase, se efecta una sobreescritura de mtodos. Ventana1 sobreescribe el mtodo
desplegar definido en Ventana, para imprimir el ttulo de la ventana y luego invocar el mtodo
desplegar de la superclase para imprimir las coordenadas y dimensiones.
La sentencia super tambin se utiliza para tener acceso a los atributos/mtodos protegidos y pblicos
de la super clase, y para distinguirlos de los atributos/mtodos del mismo nombre de la subclase.
Ntese que si no se escribe la palabra super en la segunda lnea del mtodo desplegar de Ventana1, se
estara invocando de manera recursiva al mismo mtodo.
66 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
8.2.4 Objetos de la clase derivada
El constructor de la clase derivada recibe como parmetros los valores iniciales de los atributos. De la
siguiente manera creamos un objeto de la clase Ventana1:
Ventana1 ventana1 = new Ventana1(5, 7, 60, 34, Hola);
A partir del objeto ventana1 podemos invocar los mtodos pblicos de la clase Ventana1, y tambin de
la clase base Ventana de la siguiente manera:
ventana1.desplazar(10, 5);
ventana1.redimensionar(-5, 6);
ventana1.desplegar();
El programa imprime el siguiente texto:
Ttulo: Hola
Posicin: (15, 12)
Dimensiones: 55, 40
Cabe mencionar que los atributos y mtodos protegidos NO son accesibles desde las instancias
(objetos) de las clases que las contienen.
8.3 Generalizacin
Para estudiar la generalizacin vamos a considerar el ejemplo de la jerarqua de clases que describen
las figuras planas cerradas, tales como el crculo, el rectngulo y el tringulo. Tales figuras comparten
caractersticas en comn como son la posicin y el rea; la funcin para cambiar la posicin ser el
mismo para cualquier tipo de figura, pero el procedimiento para calcular el rea ser muy particular a
cada figura.
Imaginemos que se desean crear muchas figuras de distinto tipo y almacenarlas en alguna estructura de
datos para despus realizar acciones con las figuras, como clculo de rea, despliegue (simulando un
editor grfico) y movimiento, sin importar el tipo de figura del que se trate. Cada vez que obtengamos
una figura de nuestra estructura de datos ser necesario saber a que clas pertenece la figura (crculo,
rectngulo o tringulo), y tratarla como tal para invocar un mtodo de su clase.
8.3.1 Clase abstracta
Para evitar el trabajo de saber a qu clase pertenece una figura, podemos emplear una tcnica que nos
permitir tratar todas las figuras por igual e invocar sus mtodos sin importar el tipo de figura que se
trate. Para ello es necesario definir una clase asbtracta como base de cualquier clase que quiera ser
tratada como una figura.
Las clases abstractas slamente se pueden usar como clases base para otras clases. No son
instanciables, es decir, no se pueden crear objetos cuya clase sea abstracta. Sin embargo, se pueden
declarar variables de dichas clases. Una clase abstracta slamente puede ser subclase de otra clase
abstracta. En tal caso, la subclase abstracta deber incluir todos los constructores de su superclase.
CAPTULO 8: HERENCIA Y POLIMORFISMO 67
Las clases abstractas se utilizan con frecuencia para definir un patrn de comportamiento que tendrn
en comn algn conjunto de clases: sus subclases. Una clase abstracta puede contener mtodos
abstractos; stos mtodos no se implementan dentro de la clase abstracta, sino en las clases derivadas.
Retomando el ejemplo de las figuras planas, vamos a crear una clase abstracta denominada Figura que
guardar las coordenadas actuales de la figura. Tendr tres mtodos pblicos: mover, desplegar y
obtenerArea, que representan acciones en comn entre todas las figuras. La accin desplegar slamente
imprime en pantalla los datos actuales de la figura. Ntese que todas las figuras se mueven de la misma
manera: incrementan sus coordenadas de acuerdo a los parmetros de entrada; pero se despliegan y
calculan el rea de una manera particular. Por lo tanto, los mtodos desplegar y obtenerArea sern
abstractos y tendrn que implementarse en cada una de las clases que extiendan la clase abstracta
Figura. El mtodo imprimirCoordenadas imprime la posicin actual de la figura, y podr ser invocada
slamente en las subclases. A continuacin se lista el cdigo de Figura.
public abstract class Figura {
private int x;
private int y;
public Figura(int x, int y) {
this.x = x;
this.y = y;
}
protected void imprimirCoordenadas() {
System.out.println(Posicion: ( + x + , + y + ));
}
public void mover(int dx, int dy) {
x += dx;
y += dy;
}
public abstract void desplegar();
public abstract double obtenerArea();
}
8.3.2 Clases derivadas
A continuacin se lista el cdigo de alguna de las clases derivadas de Figura; como estas clases son
subclases de una clase abstracta debern incluir la sentencia extends en la definicin de la clase
seguida del nombre de la superclase; adems debern implementar los mtodos abstractos desplegar y
obtenerArea definidos en Figura. En las subclases estos mtodos no son abstractos. Finalmente, cada
subclase podr tener diferentes atributos de acuerdo al tipo de figura del que se trate.
public class Circulo extends Figura {
protected double radio;
public Circulo(int x, int y, double radio){
super(x, y);
this.radio = radio;
}
public void desplegar() {
System.out.println(Circulo);
imprimirCoordenadas();
System.out.println(Radio = + radio);
}
public double obtenerArea() {
return Math.PI * radio * radio;
}
}
68 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
public class Rectangulo extends Figura {
protected double base, altura;
public Rectangulo(int x, int y, double base, double altura){
super(x,y);
this.base = base;
this.altura = altura;
}
public void desplegar() {
System.out.println(Rectangulo);
imprimirCoordenadas();
System.out.println(Base = + base + , altura = + altura);
}
public double obtenerArea() {
return base * altura;
}
}
public class Triangulo extends Figura {
protected double base, altura;
public Triangulo(int x, int y, double base, double altura){
super(x,y);
this.base = base;
this.altura = altura;
}
public void desplegar() {
System.out.println(Triangulo);
imprimirCoordenadas();
System.out.println(Base = + base + , altura = + altura);
}
public double obtenerArea() {
return base * altura / 2;
}
}
8.3.3 Objetos de una clase derivada
Vamos a crear un objeto de tipo Circulo e invocar mtodos propios de su clase y de la clase base
Figura. El constructor recibe como parmetros los valores iniciales de los atributos. De la siguiente
manera creamos un objeto de la clase Circulo:
Circulo circulo = new Circulo(5, 10, 75.3);
circulo.mover(7, -3);
circulo.desplegar();
System.out.println(Area = + circulo.obtenerArea());
El programa imprime el siguiente texto:
Circulo
Posicin: (15, 12)
Radio = 75.3
Area = 17813.113
8.3.4 Enlace dinmico
En el lenguaje C, como en la mayora de los lenguajes estructurados, los identificadores de la funcin
estn asociados siempre a direcciones fsicas antes de la ejecucin del programa, esto se conoce como
enlace esttico. Ahora bien, los lenguajes C++ y Java permiten decidir a que funcin llamar en tiempo
de ejecucin, esto se conoce como enlace dinmico. A continuacin, se presenta un ejemplo de ello
utilizando las clases derivadas de Figura.
CAPTULO 8: HERENCIA Y POLIMORFISMO 69
Si creamos un arreglo de tipo Figura, cada casilla podr hospedar ya sea objetos de tipo Figura u
objetos cuya clase sea derivada de Figura. En nuestro caso, como Figura es una clase abstracta, no la
podemos instanciar, por lo tanto, vamos a guardar nicamente objetos de tipo Tringulo, Rectngulo o
Crculo. Esto es permisible porque estas 3 clases son derivados de Figura.
Figura[] figuras = new Figura[4];
figuras[0] = new Circulo(15, 37, 4.7);
figuras[1] = new Rectangulo(12, 3, 6.5, 3.5);
figuras[2] = new Triangulo(60, 58, 6, 7.8);
figuras[3] = new Circulo(0, 0, 3.0);
La sentencia:
figuras[i].mover(13, 10)
invocar al mtodo mover propio de la clase base Figura; la decisin de qu funcin invocar se toma en
momento de compilar el programa. En este caso, se dice que se lleva a cabo un enlace esttico.
Pero, la sentencia:
figuras[i].obtenerArea()
a qu mtodo obtenerArea va a invocar, al de Circulo, Rectangulo o Triangulo? La respuesta es:
segn sea el valor del ndice i. Si i = 0, se invocar el mtodo obtenerArea de la clase Circulo porque el
primer elemento del arreglo guarda una referencia a un objeto de esta clase. Si el ndice es 1, entonces
se invocar el mtodo obtenerArea propio de la clase Rectangulo, y as sucesivamente. La decisin de
qu funcin invocar se toma en el momento de la ejecucin del programa. En estos casos, se dice que
se lleva a cabo un enlace dinmico. Es importante saber que si el mtodo obtenerArea no estuviera
definido en la clase abstracta Figura, no podri ser invocado desde ningn elemento del arreglo, a
menos que se realizara un cast con el nombre de la subclase.
8.3.5 Polimorfismo en accin
Supongamos que deseamos saber cul es la figura que tiene mayor rea, independientemente de su
forma. Para ello, codificamos un mtodo que reciba un arreglo de figuras, como la definida arriba, y
que devuelva una referencia a la figura con rea mayor. Este mtodo, obtenerFiguraMayor, tendr la
ventaja principal de que est definida en trminos de variables de tipo Figura, por tanto, trabaja no
slamente para una coleccin de crculos, rectngulos y tringulos, sino tambin para cualquier otra
figura derivada de la clase base Figura. De esta manera, si se deriva Pentgono de Figura y se aade a
la jerarqua de clases, este mtodo podr manejar objetos de dicha clase, sin modificar para nada el
cdigo del mismo. La codificacin del mtodo es como sigue:
public Figura obtenerFiguraMayor(Figura[] figuras) {
Figura figuraMayor = null;
double areaMayor = figuras[0].obtenerArea();
for(int i = 1; i < figuras.length; i ++) {
if(figuras[i].obtenerArea() > areaMayor) {
figuraMayor = figuras[i];
areaMayor = area;
}
}
return figuraMayor;
}
70 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Esta es la llamada al mtodo obtenerFiguraMayor, utilizando el arreglo definido anteriormente:
Figura figuraMayor = obtenerFiguraMayor(figuras);
System.out.println(El area mayor es: + figuraMayor.obtenerArea());
Se deber imprimir el siguiente mensaje
El area mayor es: 69.397781
que corresponde al primer crculo
Para conocer el valor del rea, se invoca el mtodo obtenerArea a partir de figuraMayor. El mtodo que
realmente se va a invocar depender del tipo de objeto al que hace referencia la variable figuraMayor.
Si guarda una referencia a un objeto Circulo, llamar al mtodo obtenerArea definido en dicha clase.
De manera similar para las otras figuras.
La combinacin de herencia y enlace dinmico se denomina polimorfismo. El polimorfismo es, por
tanto, la tcnica que permite pasar un objeto de una clase derivada a funciones que conocen el objeto
slamente por su clase base. El polimorfismo nos ayuda a hacer los programas ms flexibles, porque en
el futuro podemos crear nuevas clases derivadas de la clase abstracta Figura sin tener que modificar los
mtodos que los utilizan.
8.4 Herencia mltiple
La herencia mltiple consiste en definir una clase en trminos de varias clases ya existentes, esto es, la
subclase heredar el comportamiento de todas sus superclases. En el lenguaje C++ es posible
implementar la herencia mltiple permitiendo que una clase extienda a muchas clases, pero este tipo de
herencia puede presentar dificultades.
Por ejemplo, si dos clases B y C derivan de una clase base A, y a su vez una clase D deriva de B y C, se
presenta un problema conocido con el nombre de diamante. Supongamos que A tiene un atributo
protegido x, entonces B y C heredarn ese atributo con el mismo nombre. Pero como D hereda todos
los atributos protegidos de B y C, tendr 2 atributos implcitos con el mismo nombre x. Esta situacin
de conflicto de nombres se despliega en la Figura 29. Para evitar este tipo de problemas, el lenguaje
Java slamente permite heredar de una clase a la vez, pero de todos modos s nos permite implementar
la herencia mltiple a travs del uso de interfaces.
Figura 29. Problema del diamante en herencia mltiple
B
D
C
A
# x : tipo
x de A x de A
x de B x de C
conflicto
CAPTULO 8: HERENCIA Y POLIMORFISMO 71
8.4.1 Interfaces
Una interfaz es un protocolo de comportamiento que nos permite describir algunas de las caractersticas
que tendr alguna clase, pero sin definir su personalidad completa. Consiste en una coleccin de
constantes y declaraciones de mtodos no implementados. De manera implcita , estos mtodos son
abstractos, pblicos y estticos. Una interfaz, como una clase abstracta, no puede ser instanciada, pero
s podemos declarar una variable de tipo interfaz. Una clase abstracta es extendida por las subclases a
travs de una estructura jerrquica; una interfaz, en cambio, es implementada por una o ms clases que
no guardan necesariamente una relacin jerrquica. Tales clases debran implementar todos los
mtodos y podrn hacer uso de las constantes, ambos definidos en la interfaz.
Las interfaces definen similitudes entre clases sin forzar su relacin, debido a que permiten que clases
no relacionadas puedan tener comportamientos similares: dos clases que implementan la misma
interfaz pueden no estar relacionadas en la jerarqua de clases. Una clase slamente puede derivarse de
una clase base, pero puede implementar varias interfaces. Una interfaz a su vez puede extendar una o
ms interfaces, esto significa que entre interfaces s hay herencia mltiple.
A continuacin se presenta la sintaxis para la definicin de interfaces. El nombre del archivo deber ser
el mismo que el nombre de la interfaz, y la extensin ser .java. El nivel de visibilidad de las constantes
y de los mtodos es pblico por defecto; adems, las constantes son estticas.
sintaxis:
public interface Interfaz {
tipo_dato1 constante1 = valor1;
tipo_datom constantem = valorm;
tipo_devuelto1 metodo1(/* parametros de entrada */);
tipo_devuelton metodon(/* parametros de entrada */);
}
8.4.2 Clase implementadora
As como las clases abstractas, las interfaces no sirven de mucho si no existe al menos una clase que las
implemente: la clase implementadora. Esta clase deber realizar todos los mtodos definidos en cada
una de las interfaces que la clase implemente; tales mtodos debern ser pblicos y no estticos. A
continuacin se presenta la sintaxis para la clase implementadora, resaltando en negrita las sentencias
importantes.
sintaxis:
public class Clase1 implements Interfaz1, , Interfazn {
public tipo_devuelto1 metodo1DeInterfaz1(/* parametros de entrada */);
public tipo_devueltom metodomDeInterfaz1(/* parametros de entrada */);
public tipo_devuelto1 metodo1DeInterfazn(/* parametros de entrada */);
public tipo_devuelton metodomDeInterfazn(/* parametros de entrada */);
}
72 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
8.4.3 Herencia mltiple en accin
En esta seccin llevaremos a la prctica la herencia mltiple utilizando una clase abstracta denominada
Animal, una interfaz Volador, y 2 clases concretas: Hombre, Superman. La clase Hombre hereda el
comportamiento de Animal; la clase Superman extiende a la clase Hombre e implementa adems la
interfaz Volador. De esta manera, Superman exhibe propiedades de un Hombre y de un ser Volador.
A continuacin se presenta la clase Animal que define el comportamiento bsico de un animal.
public abstract class Animal {
protected final int DORMIDO = 0;
protected final int DESPIERTO = 1;
protected final int MUERTO = 2;
protected int estado = DORMIDO;
public void dormir() {
if(estado == DESPIERTO) {
estado = DORMIDO;
System.out.println(... durmiendo ...);
}
}
public void despertar() {
if(estado == DORMIDO) {
estado = DESPIERTO;
System.out.println(... despertando ...);
}
}
public void morir() {
if(estado != MUERTO) {
estado = MUERTO;
System.out.println(... muriendo ...);
}
}
public abstract void caminar();
public abstract void comer();
}
La clase Hombre hereda el comportamiento de Animal, implementa los mtodos caminar y comer,
adems de agregar la accin pensar.
public class Hombre extends Animal {
public void caminar() {
System.out.println(caminando con mis 2 pies);
}
public void comer() {
System.out.println(comiendo con cubiertos);
}
public void pensar() {
System.out.println(... pensando ...);
}
}
La interfaz Volador define el comportamiento bsico de un objeto que tenga las facultades de volar.
public interface Volador {
String tipo = Volador;
void ascender(int metros);
CAPTULO 8: HERENCIA Y POLIMORFISMO 73
void descender(int metros);
void aterrizar();
}
La clase Superman extiende a la clase Hombre e implementa la interfaz Volador, por lo que tendr que
implementar todos los mtodos de Volador; los mtodos de Animal ya no tiene que implementarse aqu
porque ya se realizaron en Hombre. De esta manera, Superman presenta herencia mltiple.
public class Superman extends Hombre implements Volador {
private int poder = 100;
public void debilitarse(int kriptonita) {
poder -= kriptonita;
System.out.println(oh oh! Hay kriptonita!);
}
public void fortalecerse(int fuerza) {
poder += fuerza;
System.out.println(Fortaleciendome!!);
}
public void ascender(int metros) {
System.out.println(Ascendiendo + metros + metros);
}
public void descender(int metros) {
System.out.println(Descendiendo + metros + metros);
}
public void aterrizar() {
System.out.println(Aterrizando);
}
}
A continuacin se presenta un cdigo donde se crea un objeto de tipo Superman, y se realizan todas las
acciones que pueda llevar a cabo Superman. La primera lnea despliega la constante que hereda de la
interfaz Volador; recordar que las constantes de una interfaz son estticas de manera predeterminada.
System.out.println(Superman.tipo);
Superman s = new Superman();
s.despertar();
s.pensar();
s.comer();
s.fortalecerse(50);
s.caminar();
s.ascender(10);
s.debilitarse(10);
s.descender(5);
s.aterrizar();
s.dormir();
s.morir();
El siguiente texto se ver impreso en pantalla tras la ejecucin del cdigo anterior:
Volador
... despertando ...
... pensando ...
comiendo con cubiertos
Fortaleciendome!!
caminando con mis 2 pies
Ascendiendo 10 metros
oh oh! Hay kriptonita!
74 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Descendiendo 5 metros
Aterrizando
... durmiendo ...
... muriendo ...
8.4.4 Polimorfismo en accin
A travs del siguiente ejemplo, veremos que la importancia de las interfaces no estriba en resolver los
problemas inherentes a la herencia mltiple sin forzar relaciones jerrquicas, sino en incrementar el
polimorfismo del lenguaje ms all del que proporciona la herencia simple.
El mtodo despertarAnimal puede recibir como parmetro cualquier objeto cuya clase sea descendiente
de la clase abstracta Animal. Este tipo de polimorfismo es propio de la herencia simple.
public void despertarAnimal(Animal a) {
a.despertar();
}
El mtodo aterrizarVolador puede recibir como parmetro cualquier objeto cuya clase implemente la
interfaz Volador, sin importar la estructura jerrquica a la que pertenezca dicha clase. Este tipo de
polimorfismo ms sofisticado es propio de la herencia mltiple a travs del uso de interfaces en Java.
public void aterrizarVolador(Volador v) {
v.aterrizar();
}
En las siguientes lneas de cdigo se crea un objeto de tipo Superman y se invocan los mtodos
anteriores utilizando como parmetro el objeto creado.
Superman s = new Superman();
despertarAnimal(s); // imprime ... durmiendo ...
aterrizarVolador(s); // imprime Aterrizando
Si creamos una clase Avion que herede de alguna clase abstracta llamada Vehiculo (independiente de
Animal) y que adems implemente la interfaz Volador, podr ser pasada como parmetro para el
mtodo aterrizarVolador.
Extendemos la definicin de polimorfismo enunciada en el Captulo 8.3.5 de la siguiente manera:
tcnica que permite pasar un objeto como parmetro a funciones que conocen al objeto slamente por
su clase base o por la interfaz que implementa su clase.
8.4.5 Modelado de interfaces usando notacin UML
Una interfaz se representa con UML en cursiva como la clase abstracta y entre parntesis angulares.
Una clase deber apuntar en el diagrama hacia la interfaz que implemente, utilizando una flecha similar
a la de la herencia, pero el tringulo es sombreado. Esto se puede apreciar en la Figura 30. La Figura 31
despliega el diagrama UML para el ejemplo visto en la Seccin 8.4.3.
CAPTULO 8: HERENCIA Y POLIMORFISMO 75
Figura 30. Representacin de la implementacin de interfaces con UML
Figura 31. Modelo de la aplicacin presentada en el Captulo 8.4.3
<Interfaz>
Clase
implementadora
<Volador>
Superman
Hombre
Animal
CAPTULO 9
EXCEPCIONES
Los programadores de cualquier lenguaje se esfuerzan por escribir programas libres de errores, sin
embargo, es muy difcil que los programas reales se vean libres de ellos. En Java las situaciones que
pueden provocar un fallo en el programa se denominan excepciones.
Java lanza una excepcin en respuesta a una situacin poco comn. El programador tambin puede
lanzar sus propias excepciones. Las excepciones en Java son objetos de clases derivadas de la clase
base Exception. Existen tambin los errores internos que son objetos de la clase Error que no se
estudiarn en este captulo. Ambas clases son derivadas de la clase base Throwable.
Existe toda una jerarqua de clases derivada de la clase base Exception. Estas clases derivadas se ubican
en dos grupos principales:
1) Las excepciones en tiempo de ejecucin ocurren cuando el programador no ha tenido cuidado al
escribir su cdigo. Por ejemplo, cuando se sobrepasa la dimensin de un arreglo se lanza la
excepcin ArrayIndexOutOfBounds. Cuando se hace uso de una referencia a un objeto que no
ha sido creado se lanza la excepcin NullPointerException. Estas excepciones le indican al
programador qu tipos de fallos tiene el programa y que debe arreglarlo antes de proseguir.
2) Las excepciones que indican que ha sucedido algo inesperado o fuera de control
En este captulo veremos las excepciones en tiempo de ejecucin
9.1 Excepciones comunes
En la Seccin 3.6 se vieron funciones para convertir cadenas de texto a valores numricos. Estas
funciones son muy usadas cuando creamos aplicaciones visuales. El usuario introduce un nmero en
algn control de edicin de texto, se obtiene el contenido del texto y se convierte a su valor numrico
para guardarse en alguna variable. Si el usuario no escribi un nmero vlido, al momento de intentar
convertir el texto a nmero, Java generar una excepcin en tiempo de ejecucin, desplegando un
mensaje en la consola.
A continuacin se despliega un ejemplo que genera este tipo de excepcin:
int edad = new Integer("35A").intValue();
int edad = Integer.parseInt(35 );
78 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Si se introducen caracteres no numricos o no se quitan los espacios en blanco al principio y al final del
string, mediante la mtodo trim( ) de String, se lanza una excepcin NumberFormatException.
En muchas ocasiones, por mala programacin, intentamos utilizar un atributo o invocar un mtodo de
un objeto que no ha sido previamente inicializado.
String cadena;
int l = cadena.length();
El compilador nos suele avisar con el mensaje variable cadena might not have been initialized. En
otras ocasiones, el compilador no puede tener la certeza de que un objeto no ha sido creado o se ha
liberado previamente, por lo tanto, no suceden errores al compilar. Pero, al ejecutar la aplicacin, se
lanza la excepcin NullPointerException cuando se intenta usar un objeto que hace referencia a ningn
espacio de memoria.
public void dibujarTriangulo(Triangulo t) {
t.desplegar(); // si t no esta inicializado, se lanza una excepcion
}
Otra excepcin que vemos con mucha frecuencia es ArrayIndexOutOfBoundsException, la cual se
desencadena cuando intenamos realizar un acceso a un elemento de un arreglo que no existe. En el
siguiente mtodo se va a generar esta excepcin durante la ltima iteracin del ciclo for, despus de
haber impreso los primeros numeros.length-1 numeros del arreglo. La excepcin ocurre porque no
existe el elemento nmero numeros.length, ya que la numeracin en Java comienza desde cero.
public void desplegar(int[] numeros) {
for(int i = 0; i <= numeros.length; i ++)
System.out.println(numeros[i]);
}
Existen excepciones que suceden muy a menudo cuando se ejecutan funciones de Entrada / Salida; por
lo tanto, Java obliga al programador a capturar una excepcin cada vez que se ejecuta alguna de estas
funciones. Una funcin tpica de E/S es la siguiente:
System.in.read();
Cuando compilamos el programa, nos aparece un mensaje de error indicando que se debe lanzar o
capturar la excepcin IOException.
9.2 Captura de excepciones
Toda sucesin de instrucciones que sea susceptible de desencadenar al menos una excepcin durante su
ejecucin deber estar contenida en un bucle de excepcin, de la siguiente manera:
try {
// sentencias que pueden generar excepciones en tiempo de ejecucion
} catch(Exception e) {
// acciones a realizar si sucede una excepcion
}
CAPTULO 9: EXCEPCIONES 79
El bloque try nos permite proteger la ejecucin de un programa de terminaciones inesperadas debido a
errores inesperados, de programacin o de entradas de usuario. Como su nombre lo indica, try le dice a
la mquina virtual de Java que intente ejecutar el siguiente bloque de cdigo; si una de las sentencias
colocadas dentro del bloque es susceptible de desencadenar una excepcin, Java crea un objeto e de
tipo Exception y se ejecutan las sentencias contenidas en el bloque catch. En caso contrario, las
sentencias del bloque try se pueden realizar sin problemas
El siguente mtodo recibe 2 nmeros enteros y devuelve el resultado de dividir el primero entre el
segundo. Si el segundo nmero es 0, la divisin generar una excepcin porque el resultado es infinito.
Por lo anterior, es necesario colocar la operacin dentro de un bloque try para indicarle a Java que
primero intente realizar la operacin; si fuera inminente la aparicin de una excepcin como
resultado la divisin, se despiega un mensaje de error informando al usuario y el resultado ser 0, en
caso contrario, se realiza la operacin con seguridad.
ejemplo:
public int cociente(int a, int b) {
int c = 0;
try {
c = a / b;
} catch(Exception e) {
System.out.println(Division entre cero);
}
return c;
}
Ntese que en el cdigo anterior estamos tratando la excepcin de manera general, porque estamos
tratando al objeto creado por Java como un objeto de la clase Exception, la cual es la clase base para
definir cualquier excepcin. Es importante mencionar que si el resultado se guarda en una variable real
(float, double) no se genera la excepcin, sino que el resultado ser infinity.
9.2.1 Capturando varias excepciones
En ocasiones nos encontramos con la situacin de que dentro de un bloque try se pueden desencadenar
dos o ms excepciones de diferente tipo. Si queremos saber exactamente qu error sucedi para tratar
cada uno de los casos de diferente manera, agregamos un bloque catch por cada excepcin diferente
que pueda suceder y especificamos el nombre de la excepcin en lugar de usar la clase Exception.
El siguiente segmento de cdigo ilustra la manera en que podemos capturar varias excepciones. El
programa divide dos nmeros introducidos por el usuario a travs de controles de edicin, y despliega
el resultado o algn mensaje de error (en caso de suceder). Se utilizan dos variables de tipo String para
guardar estos nmeros. Para poder realizar la operacin, las variables tienen que convertirse a nmeros.
En esta aplicacin se pueden producir dos excepciones diferentes: NumberFormatException, si se
introducen caracteres no numricos, y ArithmeticException si se divide entre cero.
public static void cociente(String num1, String num2) {
String mensaje;
int numerador, denominador, cociente;
try {
numerador = Integer.parseInt(num1);
denominador = Integer.parseInt(num2);
cociente = numerador / denominador;
mensaje = new Integer(cociente).toString();
80 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
} catch(NumberFormatException ex){
mensaje = "Se han introducido caracteres no numericos";
} catch(ArithmeticException ex) {
mensaje = "Division entre cero";
}
System.out.println(mensaje);
}
En ciertas ocasiones se desea estar seguro de que un bloque de cdigo se ejecute se generen o no
excepciones. Podemos asegurar su ejecucin aadiendo un bloque finally despus del ltimo catch.
Esto es importante cuando accedemos a archivos, para asegurar que se cerrar siempre un archivo se
produzca o no un error en el proceso de lectura / escritura, o para llevar algun historial de todas las
excepciones que pudieron ocurrir y si el programa se ha recuperado de ellas o no.
sintaxis:
try {
// Este codigo puede generar una excepcion
} catch(Exception e) {
// Este codigo se ejecuta cuando se produce una excepcin
} finally {
// Este codigo se ejecuta se produzca o no una excepcin
}
9.3 Creando excepciones propias
Java proporciona las clases que manejan casi cualquier tipo de excepcin. Sin embargo, podemos
imaginar situaciones en las que producen excepciones que no estn dentro del lenguaje Java.
Extendiendo el ejemplo de la seccin anterior, estudiaremos una situacin en la que se reciben
parmetros fuera de un rango determinado, para que el programa lanza un excepcin que llamaremos
IntervalException. Esta clase extender la clase base Exception.
public class IntervalException extends Exception {
public IntervalException(String mensaje) {
super(mensaje);
// acciones que se deseen tomar una vez creada la excepcion
}
}
La definicin de la clase es muy simple: el constructor recibe como parmetro una cadena de texto con
la descripcin del error que sucedi, y a su vez lo manda al constructor de la clase base Exception
mediante la sentencia super. En las siguiente lneas de cdigo se escribirn todas aquellas acciones que
se deseen llevar a cabo una vez creado el objeto Exception, por ejemplo, desplegar algn cuadro de
dilogo que contenga informacin textual o grfica acerca del error.
9.3.1 Mtodos que lanzan excepciones
En Java podemos definir mtodos que lancen durante su ejecucin una o ms excepciones propias o del
lenguaje. La invocacin de tal mtodo deber estar localizada en un bloque try. Un mtodo que lanza
una excepcin tiene la declaracin habitual de cualquier otro mtodo pero se le aade al final la palabra
reservada throws seguida de la excepcin o excepciones que puede lanzar separadas con comas, como
se muestra en el siguiente ejemplo:
CAPTULO 9: EXCEPCIONES 81
ejemplo:
public void rango(int a) throws IntervalException {
if((a > 100) || (a < 0))
throw new IntervalException("Valor fuera de rango");
}
Cuando el numero a recibido sea mayor que 100 o negativo se lanza una excepcin mediante la
instruccin throw, donde se crea un objeto de la clase IntervalException. Dicho objeto se crea llamando
al constructor de dicha clase y pasndole un string que contiene el mensaje "Valor fuera de rango". El
siguiente ejemplo ilustra la forma en que podemos definir mtodos que lancen ms de una excepcin
propia o de Java. Ntese que las operaciones de divisin y de conversin de tipos ya no se encuentran
dentro de un bloque try.
ejemplo:
static int calcular(String a, String b) throws IntervalException,
NumberFormatException, ArithmeticException {
int num = Integer.parseInt(a);
int den = Integer.parseInt(b);
if((num > 100) || (den < -100))
throw new IntervalException("Nmeros fuera del intervalo");
return (num / den);
}
La invocacin de los mtodos rango y calcular debern estar situadas dentro de un bloque try.
9.3.2 Captura de las excepciones propias
En el siguiente cdigo se extiende la funcionalidad del mtodo cociente presentado en la Seccin 9.2.1
para presentar la manera en que capturamos excepciones propias e invocamos mtodos que lancen
excepciones. El mtodo rango verifica si el numerador sobrepasa el nmero 100 y si el denominador es
menor a -100. El mtodo getMessage( ) de la clase Exception nos devuelve la descripcin textual de la
excepcin que ha ocurrido. En el cdigo siguiente, devuelve la cadena Valores fuera de rango
public class Excepciones {
static void divisionEntera(String num1, String num2) {
String mensaje;
int numerador, denominador, cociente;
try {
numerador = Integer.parseInt(num1);
denominador = Integer.parseInt(num2);
rango(numerador, denominador);
cociente = numerador / denominador;
mensaje = new Integer(cociente).toString();
} catch(NumberFormatException ex){
mensaje = "Se han introducido cantidades no validas";
} catch(ArithmeticException ex){
mensaje = "Division entre cero";
} catch(IntervalException ex){
mensaje = ex.getMessage();
}
System.out.println(mensaje);
}
static void rango(int num, int den) throws IntervalException {
if((num > 100) || (den < -100))
throw new IntervalException("Valores fuera de rango");
82 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
}
public static void main(String[] args) {
divisionEntera(90, -10);
}
}
9.4 Ciclo de vida de una excepcin
El ciclo de vida de una excepcin se puede resumir del siguiente modo:
1. Se coloca la llamada a la funcin susceptible de producir una excepcin en un bloque try..catch
2. En dicha funcin, se crea un objeto de la clase Exception o de una clase derivada
3. Se lanza mediante throw el objeto recin creado
4. Se captura en el correspondiente bloque catch
5. En el bloque catch se notifica al usuario acerca del error sucedido, imprimiendo el mensaje
asociado a dicha excepcin, o realizando una tarea especfica.
CAPTULO 10
HILOS
Un hilo o thread en informtica es un proceso individual ejecutndose en un sistema y representa un
flujo de control del programa. A veces se les llama procesos ligeros o contextos de ejecucin.
Normalmente, cada hilo se crea para controlar un nico aspecto dentro de un programa, como puede ser
supervisar la entrada en un determinado perifrico, gestionar alguna animacin, realizar bsquedas de
informacin o controlar toda la entrada/salida del disco. Todos los hilos comparten los mismos
recursos, a diferencia de los procesos en donde cada uno tiene su propia copia de cdigo y datos
(separados unos de otros).
10.1 Flujos de un programa
Un programa de flujo nico o mono-hilvanado (single-threaded) utiliza un nico flujo de control para
controlar su ejecucin. Muchos programas no necesitan la potencia que proporciona el uso de mltiples
flujos de control. Sin necesidad de especificar explcitamente que se quiere un nico flujo de control,
muchos de los applets y aplicaciones son de flujo nico (de manera predeterminada).
Por ejemplo, en la siguiente aplicacin trivial:
public class UnHilo {
public static void main(String[] args) {
System.out.println( "Este programa tiene un solo hilo" );
}
}
cuando se llama al mtodo main(), la aplicacin imprime el mensaje y termina. Esto ocurre dentro de
un nico hilo: el predeterminado. En esta aplicacin, no vemos el hilo que ejecuta nuestro programa,
sin embargo, Java posibilita la creacin y control de hilos de manera explicita. La simplicidad para
crear, configurar y ejecutar hilos permite que se puedan implementar aplicaciones muy poderosas y de
buen desempeo que no se puede con otros lenguajes de tercera generacin. En un lenguaje orientado a
Internet como es Java, esta herramienta es vital.
Si se ha utilizado un navegador con soporte Java, se habr visto el uso de mltiples threads en Java.
Podemos observar que dos applets se pueden ejecutar al mismo tiempo o que podemos desplazar la
pgina del navegador mientras el applet contina ejecutndose. Esto no significa que el applet utilice
mltiples hilos , sino que el navegador es multi-hilo (multi-threaded).
84 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Las aplicaciones y applets multi-hilo utilizan muchos contextos de ejecucin para cumplir su trabajo.
Hacen uso del hecho de que muchas tareas contienen subtareas distintas e independientes. Se puede
utilizar un hilo para cada subtarea. Mientras que los programas de flujo nico pueden realizar su tarea
ejecutando las subtareas secuencialmente. Un programa mulit-hilo permite que cada hilo comience y
termine tan pronto como sea posible. Este comportamiento presenta una mejor respuesta a la entrada en
tiempo real.
10.2 Creacin de un hilo
Jara proporciona 2 tcnicas para crear hilos en Java. Una es extendiendo la clase Thread, y la otra
consiste en implementar la interfaz runnable. La segunda tcnica es la ms habitual y la que
utilizaremos en los ejemplos de este captulo.
La siguiente clase representa el primer modo de crear un hilo. La presencia de las sentencias en negrita
es fundamental para esta tcnica.
public class MiHilo extends Thread {
public void run() {
}
}
El ejemplo anterior crea una clase MiHilo que hereda todas las propiedades de un hilo, ya que extiende
a la clase Thread; adems, esta clase sobrecarga el mtodo Thread.run() por su propia
implementacin. El contenido del mtodo run() representa todo el trabajo que va a realizar el hilo una
vez que est en ejecucin. Extendiendo la clase Thread, se pueden heredar los mtodos y variables de
la clase padre.
Una de las limitantes de esta tcnica radica en el hecho de que Java solamente puede extender una clase
a la vez; esto significa que una clase que extienda a Thread para poder ser tratada como un hilo, ya no
puede heredar de otra clase. Esta situacin puede ser solucionada utilizando la segunda tcnica:
implementar la interfaz Runnable, como se aprecia en el siguiente ejemplo:
public class MiHilo implements Runnable {
int inicio = 0;
public MiHilo(int inicio) {
this.inicio = inicio;
}
public void run() {
for(int i = inicio; i < inicio + 100; i ++) System.out.print(i + );
}
}
Para poner a funcionar este hilo, creamos una objeto de la clase Thread, mandando como parmetro
una instancia de la clase MiHilo; enseguida invocamos el mtodo start( ) propio de la clase Thread.
Esto se puede apreciar en el siguiente cdigo:
Thread thread1 = new Thread(new MiHilo(100));
thread1.start();
Thread thread2 = new Thread(new MiHilo(350));
thread2.start();
CAPTULO 10: HILOS 85
En el proceso anterior se recorren 2 ciclos de manera simultnea, uno que cuenta del 100 al 200 y otro
que cuenta del 350 al 450. Los hilos se ejecutan aparentemente de forma paralela.
10.3 Estados de un hilo
Durante el ciclo de vida de un hilo, ste se puede encontrar en diferentes estados. El diagrama
presentadoen la Figura 32 se aproxima al funcionamiento real de un hilo, mostrando los estados por los
que puede pasar y los eventos que provocan el paso de un estado a otro.
Figura 32. Estados de un hilo
10.3.1 Nuevo
La siguiente sentencia crea un nuevo hilo pero no lo arranca, lo deja en el estado de Nuevo:
Thread miThread = new Thread(miRunnable);
Cuando un hilo se encuentra en este estado es simplemente un objeto Thread vaco. El sistema no ha
destinado ningn recurso para l. Desde este estado solamente puede arrancarse llamando al mtodo
start( ), o detenerse definitivamente, llamando al mtodo stop( ); la llamada a cualquier otro mtodo no
tendr razn de ser y provocar la generacin de la excepcin IllegalThreadStateException.
10.3.2 En ejecucin
La llamada al mtodo start( ) crear los recursos del sistema necesarios para que el hilo pueda
ejecutarse, lo incorpora a la lista de procesos disponibles para ejecucin del sistema y llama al mtodo
run( ) de la clase Thread.
miThread.start();
En este momento nos encontramos en el estado Ejecutable del diagrama. Se le llama Ejecutable y no en
Ejecucin, porque cuando el hilo est aqu no esta corriendo. Muchos computadoras tienen slamente
un procesador lo que hace imposible que todos los hilos estn corriendo al mismo tiempo. Java
implementa un tipo de calendarizacin (scheduling) o lista de procesos, que permite que el procesador
sea compartido entre todos los hilos que se encuentran en la lista. Sin embargo, en la mayora de los
casos, se puede considerar que este estado es realmente un estado En Ejecucin, porque la impresin
Nuevo Ejecutable Suspendido
Muerto
start ( )
stop ( )
run ( ) terminado
stop ( )
stop ( )
new Thread ( )
yield ( )
86 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
que produce ante nosotros es que todos los procesos se ejecutan al mismo tiempo. Cuando el hilo se
encuentra en este estado, todas las instrucciones de cdigo que se encuentren dentro del bloque
declarado para el mtodo run( ), se ejecutarn secuencialmente. La acccin yield( ) del diagrama de
estados indica que se le ha asignado el procesador a un hilo Ejecutable para realizar la siguiente accin.
10.3.3 Suspendido
Un hilo entra en estado Suspendido cuando sucede uno de los 4 casos siguientes:
1) se invoca al mtodo suspend( ),
2) se llama al mtodo sleep(milisegundos),
3) el hilo est bloqueado en un proceso de entrada/salida
4) el hilo utiliza su mtodo wait( ) para esperar a que se cumpla una determinada condicin
A continuacin se extiende la clase MiHilo para que presente un retardo especfico despus de imprimir
cada nmero.
public class MiHilo implements Runnable {
int inicio, retardo;
public MiHilo(int inicio, int retardo) {
this.inicio = inicio;
this.retardo = retardo;
}
public void run() {
for(int i = inicio; i < inicio + 10; i ++) {
System.out.println(i);
try {
Thread.sleep(retardo);
} catch(InterruptedException e)
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new MiHilo(200, 100));
t1.start();
Thread t2 = new Thread(new MiHilo(500, 50));
t2.start();
}
}
La ejecucin de la clase MiHilo despliega lo siguiente en la consola:
200 500 501 201 502 503 202 504 505 203 506 507 204 508 205 509 206 207 208 209
Como el segundo hilo tiene la mitad del retardo que el primer hilo, por cada nmero que despliega el
primer hilo se despliegan 2 del segundo hilo, hasta que termina la ejecucin del segundo hilo.
El mtodo sleep propio de la clase Thread es esttico y por lo tanto puede llamarse sin crear instancias
de Thread. El parmetro de entrada de sleep es de tipo entero y representa los milisegundos que se
tendrn que esperar para realizar la siguiente accin del hilo que se durmi. La invocacin a este
mtodo debe estar situado en un bloque try ya que puede generar la excepcin InterruptedException
en caso que algn proceso externo detenga el hilo mientras ste est durmiendo. Cuando se ejecuta la
sentencia Thread.sleep, el hilo que la contiene pasa al estado Suspendido y tendr que esperar los
CAPTULO 10: HILOS 87
milisegundos especificados en el mtodo para volver al estado Ejecutable, incluso aunque el procesador
estuviera totalmente libre.
Para cada una de los cuatro modos de entrada al estado Suspendido hay una forma especfica de volver
al estado Ejecutable. Cada forma de recuperar ese estado es exclusiva; por ejemplo, si el hilo se ha
puesto a dormir, una vez transcurridos los milisegundos que se especifiquen, l solo se despierta y
vuelve al estado Ejecutable. Llamar al mtodo resume( ) mientras est el hilo durmiendo no servira
para nada.
Los mtodos de recuperacin del estado Ejecutable, en funcin de la forma de llegar al estado
Suspendido del hilo, son los siguientes:
1. Si un hilo est dormido, una vez que pas el lapso de tiempo
2. Si a un hilo se le ejecut el mtodo suspend( ), luego de una llamada al mtodo resume()
3. Si un hilo est bloqueado por alguna accin de entrada / salida, una vez que el comando E/S
concluya su ejecucin
4. Si un hilo est esperando una condicin con el mtodo wait( ), cada vez que la variable que controla
esa condicin vare debe llamarse a notify() o notifyAll()
10.3.4 Muerto
Cuando un hilo pasa al estado Muerto se liberan todos los recursos (procesador, memoria, E/S) que
necesit para su ejecucin. No podremos volver a ejecutar el mtodo start sobre un hilo muerto.
Un hilo puede morir de 2 formas:
a) cuando concluye de manera satisfactoria la ejecucin del mtodo run( )
b) cuando se invoca el mtodo stop( )
En la clase MiHilo, definida en la seccin anterior, se crean 2 hilos llamados t1 y t2, los cuales pasarn
al estado Muerto automticamente cuando se finalice el ciclo for colocado en el mtodo run.
Los applets utilizan el mtodo stop() para matar a todos sus hilos cuando el navegador con soporte Java
en el que se estn ejecutando le indica al applet que se detengan, por ejemplo, cuando se minimiza la
ventana del navegador o cuando se cambia de pgina.
La clase Thread incluye el mtodo isAlive(), que devuelve true si el hilo ha sido arrancado y no ha sido
detenido. Por ello, si el mtodo isAlive() devuelve false, sabemos que estamos lidiando con un hilo
Nuevo o Muerto. Si nos devuelve true, sabemos que el hilo se encuentra en estado Ejecutable o
Suspendido. No se puede distinguir entre Nuevo y Muerto, ni entre un hilo Ejecutable o Parado.
10.4 Comunicacin entre hilos
Otra clave para el xito y la ventaja de la utilizacin de mltiples hilos en una aplicacin, es que
pueden comunicarse entre s. Se pueden disear hilos para utilizar objetos comunes, que cada hilo
puede manipular independientemente de los dems. El ejemplo clsico de comunicacin de hilos es el
modelo productor/consumidor. Un hilo produce una salida que otro hilo consume.
Vamos entonces a crear un productor, que ser un hilo que ir generando letras maysculas a cierta
velocidad; programaremos tambin un consumidor que ir consumiendo los caracteres que genere el
88 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
productor, y un monitor que controlar el proceso de sincronizacin entre los hilos. Funcionar como
una estructura de cola: el productor inserta caracteres en un extremo y el consumidor los lee en el otro,
y el monitor es en s la cola. El comportamiento de nuestra aplicacin se puede apreciar en el esquema
de la Figura 33.
Figura 33. Esquema productor - consumidor
El productor implementar la interfaz Runnable y su cdigo es el siguiente:
public class Productor implements Runnable {
private Monitor monitor;
private String alfabeto = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private int retardo, no_letras;
public Productor(Monitor monitor, int retardo, int no_letras) {
// guarda la referencia del monitor para realizar la accion 'depositar'
this.monitor = monitor;
// guarda el retardo que va a sufrir el consumidor despues de cada consumo
this.retardo = retardo;
// guarda el numero de letras que se van a Producir
this.no_letras = no_letras;
}
public void run() {
// Ciclo para generar y depositar letras mayusculas en la cola del monitor
for(int i = 0; i < no_letras; i ++) {
// produce un byte con un valor aleatorio entre 65 y 90
byte b = (byte) (65 + Math.random() * 26);
// deposita el byte creado en la cola del monitor
monitor.depositar(b);
// imprime el mensaje de la accion realizada
System.out.println("Se deposito " + (char) b + " en la cola" );
// genera un retardo antes de producir ms letras mayusculas
try {
Thread.sleep(retardo);
} catch( InterruptedException e ) {
} // fin try
} // fin for()
} // fin run()
Veamos ahora el cdigo del consumidor, que tambin implementar la interfaz Runnable
public class Consumidor implements Runnable {
private Monitor monitor;
private int retardo, no_letras;
public Consumidor(Monitor monitor, int retardo, int no_letras) {
// guarda la referencia del monitor para realizar la accion 'depositar'
this.monitor = monitor;
// guarda el retardo que va a sufrir el consumidor despues de cada consumo
this.retardo = retardo;
// guarda el numero de letras que se van a consumir
this.no_letras = no_letras;
Productor Consumidor
c c
Monitor
+ depositar(char c) + recoger( ) : char
A T G U F S U
bfer
CAPTULO 10: HILOS 89
}
public void run() {
int i = 0;
// Ciclo para consumir las letras de la cola del monitor
while(i < no_letras) {
// Obtiene el primer byte de la cola del monitor
byte b = monitor.recoger();
// Si el metodo devuelve 0, entonces la cola esta vacia,
// en caso contrario, imprimir accion realizada e incrementar contador
if(b != 0) {
System.out.println("Se consumio el caracter " + (char) b);
i ++;
}
// Generar un retardo antes de recoger ms letras
try {
Thread.sleep(retardo);
} catch( InterruptedException e ) {
}
}
}
}
Una vez visto lo que realizan el consumidor y el productor, pasamos a analizar al monitor. Lo que
realiza la clase Monitor es una funcin de supervisin de las transacciones entre los dos hilos: el
productor y el consumidor. Los monitores, en general, son piezas muy importantes de las aplicaciones
multi-hilo porque mantienen el flujo de comunicacin entre los hilos. El anlisis y ejecucin de la clase
Monitor se deja al lector. Ntese que se ha implementado la cola utilizando la vectores, adems de que
se utilizan mtodos synchronized para evitar accesos concurrentes a la cola.
import java.util.*;
public class Monitor {
Vector cola = new Vector();
synchronized void imprimeVector() {
for(int i = 0; i < cola.size(); i ++) {
Byte b = (Byte) cola.get(i);
System.out.print((char) b.byteValue());
}
System.out.println();
}
public synchronized void depositar(byte b) {
cola.addElement(new Byte(b));
imprimeVector();
}
public synchronized byte recoger() {
if(cola.isEmpty()) return 0;
Byte b = (Byte) cola.remove(0);
imprimeVector();
return b.byteValue();
}
public static void main(String[] a) {
Monitor m = new Monitor();
int letrasPorConsumir = 20;
Thread t = new Thread(new Productor(m, 50, 20));
t.start();
t = new Thread(new Consumidor(m, 100, 20));
t.start();
} // fin main
} // fin clase
CAPTULO 11
INTERFAZ GRFICA DE USUARIO
La interfaz de usuario es la parte de una aplicacin que permite a sta interactuar con el usuario. Las
interfaces de usuario pueden adoptar muchas formas que van desde la lnea de comandos simple hasta
las interfaces visuales avanzadas que proporcionan las aplicaciones actuales.Una aplicacin sin una
interfaz amigable impide que los usuarios obtengan el mximo rendimiento del programa.
Java proporciona los elementos bsicos para construir de manera sencilla interfaces de usuario
aceptables a travs del AWT, y opciones para mejorarlas mediante los componentes Swing.
11.1 AWT
AWT es el acrnimo de Abstract Window Toolkit y representa una librera de clases Java para el
desarrollo de interfaces grficas de usuario. La primera versin del AWT se desarroll en slo dos
meses y, aunque se ha retocado posteriormente, es la parte ms dbil de todo lo que representa Java
como lenguaje. El entorno que ofrece es simple, y es tal vez debido a la presin de los desarrolladores
de Java de tener que lanzar algo al mercado que proporcione herramientas grficas.
Debido a la pobreza que mostr la primera versin del AWT, JavaSoft se uni con Netscape, IBM y
Lighthouse Design para crear un conunto de clases que proporcionen una sensacin visual agradable al
usuario, que sean ms fciles de utilizar por el programador y que sean fcilmente transportables entre
plataformas. Esta coleccin de clases se denominaron Java Foundation Classes (JFC), que en la
plataforma Java 2 (JDK 1.2 en adelante) estn constituidas por cinco grupos de clases: AWT mejorado,
Accessibility, Java 2D, Drag & Drop y Swing.
AWT fue diseado pensando en que el programador no tuviese que preocuparse de detalles como
controlar el movimiento del ratn o leer el teclado, ni tampoco de detalles como la escritura en pantalla.
El AWT constituye una librera de clases orientada a objetos para cubrir estos recursos y servicios de
bajo nivel.
En trminos generales, la librera AWT est constituido por:
Componentes propios de la interfaz de usuario (botones, ventanas, cuadros de texto)
Un modelo robusto para el manejo de eventos (teclado, ratn)
Herramientas para imgenes, grficos, tipos de letras
92 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
Administradores de la disposicin de componentes en un contenedor sin depender de un tamao de
ventana o resolucin de la pantalla particular
Clases para transferencia de datos (cortar y pegar) a travs del portapapeles nativo de la plataforma
Los componentes AWT estndares delegan en los peers la mayor parte de su funcionalidad. Los peers
u observadores son componentes nativos del GUI del sistema operativo en donde se ejecutan y son
manipulados por los componentes AWT. Los peers no estn escritos en Java necesariamente. Cada
componente AWT tiene un peer nativo equivalente. Cuando una aplicacin Java solicita la creacin y
despliegue de un componente AWT (men, ventana, botn), la JVM realmente crea y despliega un peer
de la plataforma actual. Es por esta razn que los componentes AWT son considerados pesados, o
heavyweight.
11.2 Swing
Swing es tambin una librera de clases para el diseo de interfaces grficas de usuario y representa un
gran paso adelante respecto al AWT. Ahora los componentes visuales son beans (componentes
especializados reutilizables, orientados a objetos) y utilizan un nuevo modelo para el manejo de eventos
(teclado, ratn). Todos los componentes Swing son ligeros o lightweight porque ya no se usan
componentes peer dependientes del sistema operativo, adems Swing est totalmente escrito en Java.
Las principales caractersticas de Swing se resumen a continuacin::
Ofrece todas las facilidades visuales y manejos de eventos del AWT
Comprende una versin de cada componente AWT pero desarrollado 100% en Java puro (JButton,
JLabel, JPanel)
Incoropora un conjunto de componentes de alto nivel (List Box, Tree View, Tabbed Panes)
El diseo es en Java puro, sin dependencia en los peers
Pluggable look & feel: la apariencia de una aplicacin se adapta dinmicamente al sistema
operativo y plataforma en que est corriendo
Debido a las ventajas que ofrece Swing sobre AWT, en este captulo dejaremos los componentes AWT
a un lado y nos concentraremos en s componentes ms importantes que ofrece el paquete Swing de
Java para desarrollar aplicaciones visuales.
El paso de AWT a Swing es muy sencillo y no hay que descartar nada de lo que se haya hecho con el
AWT. Afortunadamente, los desarrolladores de Swing han considerado que muchos programadores de
aplicaciones grficas en Java se han acostumbrado a los nombres de las clases contenidas en el paquete
AWT; por lo anterior, decidieron que cada uno de los componentes existentes en AWT tendr su
similar en Swing, pero se aadir una J al inicio del nombre del componente Swing. Ejemplo:
Button pertenece a AWT, JButton pertenece a Swing; los 2 ofrecen el mismo uso en las aplicaciones
visuales, pero el primero tiene gran dependencia de los peers de la plataforma donde se ejecuta, y el
segundo est desarrollado en Java puro, es ms transportable y ofrece ms facilidades para el
programador.
Es importante mencionar que, aunque Swing sea una versin mejorada de AWT, no significa que est
encaminado a sustituirlo por completo, sino a extenderlo, porque la funcionalidad bsica de Swing
descansa sobre el AWT. Aunque algunos componentes de Swing se corresponden a componentes del
CAPTULO 11: INTERFAZ GRFICA DE USUARIO 93
AWT, existen muchas clases tiles que slamente se encuentran en las libreras AWT y que no se han
extendido en Swing.
11.3 Creacin y configuracin de los componentes visuales bsicos de Swing
En esta seccin veremos algunos de los componentes visuales ms comunes que proporciona Swing y
estudiaremos su funcionalidad a travs de ejemplos programados. Para cada componente slamente se
presentan los mtodos que consideramos de mayor importancia. Si se desea mayor informacin de
estos componentes, consultar la API de Java.
11.3.1 JLabel
Un objeto JLabel o etiqueta corresponde a un rea para desplegar texto de slo lectura en una ventana;
el texto abarca un slo rengln; una etiqueta no responde a eventos de entrada, por lo mismo no puede
recibir el enfoque del usuario. Para crear una etiqueta, especificamos el texto que va a desplegar
inicialmente, de la siguiente manera:
JLabel etiqueta = new JLabel(Esto es una etiqueta);
Para cambiar y obtener el texto desplegado se utilizan los mtodos setText y getText, respectivamente:
etiqueta.setText(Cambio de texto);
String texto = etiqueta.getText();
Para especificar los mrgenes horizontales y verticales, utilizamos los siguientes mtodos:
o setHorizontalAlignment(int alineacion)
- JLabel.CENTER
- JLabel.LEFT
- JLabel.RIGHT
o setVerticalAlignment(int alineacion)
- JLabel.CENTER
- JLabel.BOTTOM
- JLabel.TOP
Finalmente, para establecer los colores de fondo y del texto de una etiqueta, uilizamos.
o setBackground(java.awt.Color color)
o setForeground(java.awt.Color color)
11.3.2 JTextField
Comnmente llamando cuadro de texto, JTextField es un componente que nos permite el despliegue y
edicin de una lnea de texto. Este componente s puede recibir un enfoque del usuario, es decir, a
diferencia de una etiqueta, el cursor s se puede colocar dentro del cuadro de texto.
Para crear un cuadro de texto debemos especificar, ya sea el texto que va a desplegar inicialmente, la
anchura del componente medido en columnas visibles, o ambos.
JTextField cuadroTexto = new JTextField(Texto inicial);
Valores posibles para
alineacion
94 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
JTextField cuadroTexto = new JTextField(15);
JTextField cuadroTexto = new JTextField(Texto inicial; 15);
Para cambiar y obtener el texto desplegado se utilizan los mtodos setText y getText, como en JLabel:
cuadroTexto.setText(Cambio de texto);
String texto = cuadroTexto.getText();
Para especificar el margen horizontal y los colores de fondo y texto utilizamos los mismos mtodos que
en el componente JLabel. Para deshabilitar el cuadro de texto e impedir que se modifique su contenido
se utiliza el mtodo setEnabled con false como parmetro; para habilitarlo otra vez, se utiliza true.
11.3.3 JButton
Esta clase crea un botn etiquetado o con una imagen asignada. Un botn puede ser oprimido por el
usuario para ocasionar que se efecten acciones especficas. Para crear un botn indicamos el texto o la
imagen que desplegar inicialmente de la siguiente manera:
JButton cancelar = new JButton("Cancelar);
JButton guardar = new JButton(new ImageIcon("imagen1.gif"));
La clase ImageIcon nos permite obtener una imagen gif a partir de un URL o directorio especificado en
su constructor, y agregarla a un botn. Esta clase se encuentra en el paquete javax.swing.
Para habilitar/deshabilitar un botn utilizamos el mtodo setEnabled de la misma manera que con el
componente JTextField.
if(status = EDICION) guardar.setEnabled(true);
else guardar.setEnabled(false);
Para especificar el texto de ayuda emergente que se va a desplegar cuando se pase el puntero del ratn
por encima del botn se utiliza el setToolTipText de la siguiente manera:
guardar.setToolTipText(Guardar los datos);
11.3.4 JList
Componente que le permite al usuario elegir uno o ms objetos de una lista visual. El componente JList
deber tener asignado una estructura de datos que almacene todos los objetos que la lista desplegar. Si
la cantidad de objetos a desplegar es fija, podemos usar un arreglo; en caso contrario, un Vector sera la
mejor opcin. El enlace entre el componente y la estructura de almacenamiento se puede realizar con el
mtodo setListData o en la construccin de la lista.
String[] datos1 = {Objeto 1, Objeto 2, Objeto 3, Objeto 4};
Vector datos2 = new Vector();
JList lista1 = new JList(); JList lista1 = new JList(datos1);
lista1.setListData(datos1);
JList lista2 = new JList(); JList lista2 = new JList(datos2);
lista2.setListData(datos2);
CAPTULO 11: INTERFAZ GRFICA DE USUARIO 95
Cuando realicemos cambios en la fuente de datos, como agregar, eliminar o modificar elementos del
vector o arreglo enlazado, es necesario actualizar la lista de manera que se desplieguen los datos
actualizados. Esto lo podemos realizar invocando el mtodo repaint de JList o cambiando la seleccin
de la lista con el mtodo setSelectedIndex.
A continuacin se listan los mtodos que definen la apariencia visual de una lista:
o setBackground(java.awt.Color color)
color de fondo de la lista
o setForeground(java.awt.Color color)
color del texto de los elementos de la lista
o setSelectionBackground(java.awt.Color color)
color de fondo del(los) elemento(s) seleccionado(s)
o setSelectionForeground(java.awt.Color color)
color del texto del(los) elemento(s) seleccionado(s)
o setFixedCellHeight(int altoCelda)
alto de cada celda en pixeles
o setFixedCellWidth(int anchoCelda)
ancho de cada celda en pixeles
Los siguientes mtodos de JList se relacionan con la seleccin de elementos:
o setSelectedIndex (int indice)
selecciona el elemento nmero indice de la lista, donde el 1er elemento tiene indice = 0; la
ausencia de seleccin se representa con indice = 1; cualquier indice < 1 ser invlido
o getSelectedIndex( ) : int
devuelve el ndice del elemento seleccionado de la lista
o getSelectedValue( ) : Object
devuelve una referencia del elemento seleccionado; implica la presencia de un cast utilizando el
tipo de dato que tengan los elementos de la lista
o clearSelection( )
despues de invocar este mtodo, ningn elemento de la lista estar seleccionado
o setSelectionMode(int modo)
establece el modo de seleccin de la lista, donde modo puede tomar uno de los siguientes valores:
- ListSelectionModel.SINGLE_SELECTION : nada ms se puede seleccionar un elemento a
la vez
- ListSelectionModel.SINGLE_INTERVAL_SELECTION : nos permite seleccionar uno o
ms elementos contiguos (utilizando shift y el botn izquierdo del mouse)
- ListSelectionModel.MULTIPLE_INTERVAL_SELECTION : nos permite seleccionar uno
o ms elementos contiguos o separados (utilizando ctrl y el botn izquierdo del mouse)
o setSelectedIndices(int[] indices)
selecciona uno o ms elementos de la lista, dado por un arreglo de enteros
o getSelectionIndices(int modo)
devuelve un arreglo de enteros indicando los elementos de la lista que estn seleccionados
o getValueIsAdjusting ( ) : boolean
devuelve true si el valor de la lista est en un proceso de ajuste como resultado de la interaccin
con el usuario; validar que el valor devuelto de este mtodo sea true nos garantiza que no suceda
nada hasta que se haya completado el cambio de seleccin
96 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
11.3.5 JScrollPane
La clase JScrollPane es un componente y a la vez contenedor de componentes Swing; nos proporciona
barras de desplazamiento vertical y horizontal para poder visualizar el componente contenido en los
casos en que el espacio visual asignado no es suficiente para desplegar toda la informacin. El
constructor de JScrollPane recibe como parmetro la referencia de un componente.
Podemos utilizar este componente para poder visualizar todos los elementos de una lista; cuando el
total de elementos agregados haya rebasado las dimensiones de la lista, aparecer una barra de
desplazamiento vertical que nos permitir navegar sobre la lista para ver los dems elementos; si el
texto de algn elemento de la lista rebasa la anchura de la lista, deber aparecer la barra horizontal.
Vector datos = new Vector();
JList lista = new JList(datos);
JScrollPane scroll = new JScrollPane(lista);
11.3.6 JComboBox
Tambin llamado cuadro combinado, JComboBox es un componente de uso semejante al JList que
combina un botn y una lista. Cuando el cuadro combinado no est en uso, slamente despliega el
elemento seleccionado de la lista. Al presionar el botn aparece la lista desplegando n elementos a
partir del seleccionado. El valor de n representa la cantidad mxima de elementos que podrn
desplegarse al mismo tiempo. Cuando la cantidad de elementos contenidos en el cuadro combinado
rebasa el valor de n, aparece una barra de desplazamiento vertical.
Para crear un cuadro combinado con datos iniciales hacemos lo mismo que con el JList: mandar como
parmetro del constructor un vector o un arreglo. Tambin podemos crear un cuadro combinado vaco.
String[] datos1 = {Objeto 1, Objeto 2, Objeto 3, Objeto 4};
Vector datos2 = new Vector();
JComboBox combo0 = new JComboBox();
JComboBox combo1 = new JComboBox(datos1);
JComboBox combo2 = new JComboBox(datos2);
A diferencia del JList, el JComboBox nos permite editar elementos a partir de mtodos propios, sin
tener que realizar tales acciones sobre el vector o el arreglo asignado inicialmente.
o addItem(Object objeto)
agrega el elemento objeto al final del cuadro combinado:
combo0.addItem(Objeto 1);
o insertItemAt(Object objeto, int indice)
agrega el elemento objeto en el lugar indice de la lista; los elementos con ndice indice se
recorren un lugar al final
o removeItemAt(int indice)
elimina el elemento nmero indice del cuadro combinado:
combo1.removeItemAt(2); // elimina Objeto 3
o getItemAt(int indice) : Object
devuelve el elemento de la lista situado en el lugar indice, como un objeto.
String s = (String) combo1.getItemAt(1); // devuelve Objeto 2
o getSelectedIndex( ) : int
devuelve el ndice del elemento seleccionado, o -1 si no hay ningn elemento seleccionado
CAPTULO 11: INTERFAZ GRFICA DE USUARIO 97
o setSelectedIndex(int indice)
selecciona el elemento dado por indice
o getItemCount( ): int
devuelve el nmero de elementos de la lista
11.3.7 Cuadros de dilogo
Una de las formas ms comunes de desplegar cuadros de dilogo informativos es utilizando el mtodo
esttico showMessageDialog de la clase JOptionPane. El cuadro de dilogo que se presenta despliega
un cono de acuerdo al tipo de mensaje a mostrar: error, aviso, informacin, pregunta. Adems, cuando
el cuadro de dilogo est visible, todas las ventanas que forman parte de la aplicacin se deshabilitan.
o showMessageDialog(Component padre, Object mensaje, String titulo, int tipoMensaje)
- padre: el componente que servir como referencia para centrar el cuadro de dilogo; los
componentes padres ms comunes son: JPanel, JFrame. Utilizamos this si el componente
padre es la referencia de la clase donde fue invocada el cuadro de dilogo, y null si no tiene
componente padre, y con ello, la referencia posicional ser la pantalla misma.
- mensaje: la informacin que se va a desplegar en el cuadro de dilogo
- titulo: la informacin que va en la barra de titulo
- tipoMensaje: existe un icono asignado para cada tipo de mensaje; los tipos de mensaje
disponibles estn dados por los siguientes atributos estticos de JOptionPane:
ERROR_MESSAGE, WARNING_MESSAGE, INFORMATION_MESSAGE,,
QUESTION_MESSAGE, PLAIN_MESSAGE
ejemplo:
public class Calculadora extends JFrame {
public void dividir(int numerador, int denominador){
if(denominador == 0)
JOptionPane.showMessageDialog(this, "Division entre cero",
Error de datos, JOptionPane.ERROR_MESSAGE);
}
}
En el ejemplo anterior, un objeto Calculadora realmente es una ventana porque su clase extiende a
JFrame. El primer parmetro del mtodo showMessageDialog (this) se refiere al objeto Calculadora
actual, por lo que, al desplegarse el cuadro de dilogo, la ventana se deshabilitar y al cerrarse el cuadro
de dilogo se volver a habilitar.
11.4 Adicin de los componentes visuales bsicos de Swing en una aplicacin
Toda aplicacin visual en Java se podr desplegar utilizando uno de dos medios visuales posibles: a
travs de un applet en una pgina de internet, o dentro de una ventana.
11.4.1 JFrame
Swing proporciona el componente JFrame que nos permite crear ventanas en pocos pasos. Dentro de un
JFrame podemos agregar cualquier otro componente visual de Swing para conformar la GUI de nuestra
98 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
aplicacin. Para crear una ventana en Java es suficiente con instanciar o extender la clase JFrame. La
segunda tcnica es la ms recomendada por cuestiones de diseo orientado a objetos, y porque nos
evita la escritura repetitiva del objeto de tipo JFrame al invocar sus mtodos. La clase JFrame se
encuentra en el paquete javaw.swing.
La siguiente clase crea y despliega una ventana utilizando la 1 tcnica:
import javax.swing.*;
public class Ventana1 {
public Ventana1() {
JFrame ventana1 = new JFrame(Mi primer ventana);
ventana1.setSize(300, 200);
ventana1.setResizable(false);
ventana1.setDefaultCloseOperation(3);
ventana1.setVisible(true);
}
public static void main(String[] args) {
new Ventana1();
}
}
Asi quedara la clase anterior utilizando la 2 tcnica: herencia.
import javax.swing.*;
public class Ventana1 extends JFrame {
public Ventana1() {
super(Mi primer ventana);
setSize(300, 200);
setResizable(false);
setDefaultCloseOperation(3);
setVisible(true);
}
public static void main(String[] args) {
new Ventana1();
}
}
Analicemos cada una de las lneas del constructor de Ventana1. Uno de los constructores que ofrece la
clase JFrame espera como parmetro de entrada una cadena de texto que representa el ttulo de la
ventana, el cual aparecer en la barra de la parte superior de la misma. Por esta razn, utilizamos la
sentencia super para enviar el ttulo de nuestra ventana a la clase base en el momento de su creacin.
Otra forma de asignar el ttulo a la ventana es utilizando el mtodo setTitle de JFrame.
El mtodo setSize asigna el tamao de nuestra ventana mediante dos valores enteros que representan
sus dimensiones de anchura y altura en pixeles. El mtodo setResizable indica que no podemos estirar o
encoger la ventana si el parmetro; setDefaultCloseOperation establece la accin que se llevar a cabo
cuando el usuario intente cerrar la ventana: 0 = no realiza accin, 1 = se oculta, 2 = se libera el espacio
de memoria, 3 = termina la aplicacin. Una vez que se hayan especificado todos los parmetros de la
ventana y agregado todos los componentes dentro de la misma, se indica al sistema que despliegue la
ventana en la pantalla mediante el mtodo setVisible y enviando como parmetro true. Para un buen
desempeo de nuestra aplicacin, este mtodo deber ser el ltimo que se invoque.
No podemos colorear un objeto JFrame ni agregar componentes directamente dentro de l; esto
slamente podemos realizarlo utilizando contenedores (Container). Todo JFrame tiene un contenedor
CAPTULO 11: INTERFAZ GRFICA DE USUARIO 99
de manera implcita, y es a travs de l que podemos agregar componentes a nuestra ventana. Este
contenedor abarca todo el ancho de la ventana excluyendo los bordes y la barra de ttulo. Para obtener
el contenedor que tiene todo objeto JFrame utilizamos el mtodo getContentPane como se ver en la
siguiente seccin.
11.4.2 JPanel
La Clase JPanel hereda de la clase Container, lo que ocasiona que un objeto JPanel o pnel tenga todas
las caractersticas de un contenedor, con la particularidad de que puede contener componentes Swing,
como los que veremos en las secciones siguientes. Un pnel tambin puede contener ms paneles, y
stos a su vez pueden contener an ms pneles. Un pnel nos sirve tambin como lienzo para dibujar
figuras geomtricas.
A travs de un objeto JPanel podemos agregar componentes visuales a una ventana. La siguiente clase
ampla la funcionalidad de la clase Ventana1 definida en la seccin anterior. Se obtiene el contenedor
que tiene todo JFrame utilizando el mtodo getContentPane( ), se convierte en un objeto de tipo JPanel,
se le asigna el color naranja de fondo y un borde amarillo.
import java.awt.Color;
import javax.swing.*;
import javax.swing.border.*;
public class Ventana1 extends JFrame {
public Ventana1() {
super(Mi primer ventana);
setSize(300, 200);
setResizable(false);
setDefaultCloseOperation(3);
JPanel panel = (JPanel) getContentPane();
panel.setBackground(Color.ORANGE);
panel.setBorder(new LineBorder(Color.YELLOW));
setVisible(true);
}
public static void main(String[] args) {
new Ventana1();
}
}
El mtodo setBackground establece el color de fondo de un panel; en Java, establecemos un color
utilizando un objeto de la clase Color, contenida en el paquete java.awt. Esta clase tiene una lista de
atributos finales estticos que nos sirven para invocar los colores ms comunes. En el ejemplo, se
colorea el pnel de color naranja. Para definir colores personalizados, creamos un objeto de tipo Color
y especificamos la cantidad de rojo, verde y azul que deseemos, de la siguiente manera:
// rojo, verde, azul
Color cafe = new Color(170, 130, 100);
El valor para cada componente de nuestro color RGB puede ir de 0 hasta 255, donde (0, 0, 0) equivale
al color negro y (255, 255, 255) al color blanco.
El mtodo setBorder nos permite especificar el borde de un pnel; en el ejemplo se establece un borde
lineal de color amarillo. A continuacin se listan los constructores para los tipos de bordes ms
comunes que proporciona Swing en la librera javax.swing.border:
100 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
o new EtchedBorder( )
o new LineBorder(java.awt.Color)
o new BevelBorder(int borde)
- BevelBorder.RAISED
- BevelBorder.LOWERED
o new SoftBevelBorder(int borde)
- SoftBevelBorder.RAISED
- SoftBevelBorder.LOWERED
11.4.3 Disposicin de componentes Swing en un JPanel
La clase JPanel proporciona el mtodo add que nos permite agregar componentes AWT o Swing dentro
de un pnel. Debido a la portabilidad que tienen las aplicaciones Java, no es posible especificar
coordenadas absolutas para la ubicacin de componentes dentro de un pnel; esto es porque estaramos
casando nuestra aplicacin con algn sistema de ventanas especfico. Para resolver este problema,
JPanel proporciona diferentes formas de disponer los componentes
La forma de ubicar los componentes en un JPanel se especifica con el mtodo setLayout, el cual recibe
como parmetro un objeto perteneciente a una clase que implemente la interfaz LayoutManager o
LayoutManager2. Alguna de estas clases implementadoras se presentan a continuacin. Todas
pertenecen al paquete java.awt.
11.4.3.1 FlowLayout
Es la disposicin o layout por omisin de un JPanel. FlowLayout acomoda los componentes en el pnel
siguiendo un flujo similar a la escritura de texto en un prrafo: de izquierda a derecha y de arriba hacia
abajo. Los componentes se agregan siguiendo una lnea horizontal; cuando algn componente no tenga
espacio suficiente para desplegarse, se avanza a la siguiente lnea o rengln. Cada lnea est centrada.
Para especificar el espacio horizontal y vertical en pixeles existente entre cada componente, utilizamos
los mtodos setHgap y setVgap, respectivamente, como se observa en el ejemplo siguiente:
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
public class Disposicion1 extends JFrame {
public Disposicion1() {
super("Disposicin en FlowLayout");
setSize(300, 150);
setResizable(false);
setDefaultCloseOperation(3);
FlowLayout flow = new FlowLayout();
flow.setHgap(10);
flow.setVgap(25);
JPanel panel = (JPanel) getContentPane();
panel.setBackground(new Color(100, 160, 190));
panel.setBorder(new BevelBorder(BevelBorder.LOWERED));
panel.setLayout(flow);
panel.add(new JButton("boton 1"));
panel.add(new JButton("boton 2"));
panel.add(new JButton("boton 3"));
Valores posibles para
borde
CAPTULO 11: INTERFAZ GRFICA DE USUARIO 101
panel.add(new JLabel("etiqueta 1:"));
panel.add(new JTextField("texto 1", 10));
panel.add(new JButton("boton 4"));
setVisible(true);
}
public static void main(String[] args) {
new Disposicion1();
}
}
La ejecucin de la clase Disposicion1 en el sistema operativo Windows XP, desplegar la siguiente
ventana:
Figura 34. Disposicin de componentes en FlowLayout
11.4.3.2 GridLayout
Este tipo de disposicin despliega los componentes en una cuadrcula. El panel se divide en rectngulos
del mismo tamao, y cada componente se coloca en un rectngulo; por esta razn, todos los
componentes tendrn las mismas dimensiones. La cantidad de filas y columnas en que se dividir el
panel se especifica comnmente en el constructor de GridLayout, como se observa en el ejemplo
siguiente:
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
public class Disposicion2 extends JFrame {
public Disposicion2() {
super("Disposicin en GridLayout");
setSize(300, 150);
setResizable(false);
setDefaultCloseOperation(3);
// (filas, columnas)
GridLayout grid = new GridLayout(3, 2);
grid.setHgap(10);
grid.setVgap(15);
JLabel etiqueta = new JLabel("etiqueta 1:");
etiqueta.setHorizontalAlignment(JLabel.RIGHT);
JPanel panel = (JPanel) getContentPane();
panel.setBackground(Color.orange);
panel.setBorder(new LineBorder(Color.red));
panel.setLayout(grid);
panel.add(new JButton("boton 1"));
102 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
panel.add(new JButton("boton 2"));
panel.add(new JButton("boton 3"));
panel.add(new JButton("boton 4"));
panel.add(etiqueta);
panel.add(new JTextField("texto 1", 10));
setVisible(true);
}
public static void main(String[] args) {
new Disposicion2();
}
}
La ejecucin de la clase Disposicion2 en el sistema operativo Windows XP, desplegar la siguiente
ventana:
Figura 35. Disposicin de componentes en GridLayout
11.4.3.3 BorderLayout
Este tipo de disposicin acomoda los componentes en 5 regiones diferentes: norte (arriba), sur (abajo),
centro, este (derecha), oeste (izquierda). Cada regin est identificada con una constante perteneciente
a la clase BorderLayout: NORTH, SOUTH, CENTER, EAST, WEST. Para agregar componentes a un
pnel teniendo como disposicin BorderLayout, se utiliza el mtodo add de JPanel con 2 parmetros:
componente y regin. Si se omite la regin, se colocar el componente en el centro. La siguiente clase
acomoda 5 botones en una ventana utilizando BorderLayout.
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
public class Disposicion3 extends JFrame {
public Disposicion3() {
super("Disposicin en BorderLayout");
setSize(300, 150);
setResizable(false);
setDefaultCloseOperation(3);
JPanel panel = (JPanel) getContentPane();
panel.setBackground(new Color(180, 200, 130));
panel.setBorder(new SoftBevelBorder(SoftBevelBorder.RAISED));
BorderLayout grid = new BorderLayout();
grid.setHgap(5);
grid.setVgap(10);
CAPTULO 11: INTERFAZ GRFICA DE USUARIO 103
panel.setLayout(grid);
panel.add(new JButton("Norte"), BorderLayout.NORTH);
panel.add(new JButton("Centro"), BorderLayout.CENTER);
panel.add(new JButton("Sur"), BorderLayout.SOUTH);
panel.add(new JButton("Oeste"), BorderLayout.WEST);
panel.add(new JButton("Este"), BorderLayout.EAST);
setVisible(true);
}
public static void main(String[] args) {
new Disposicion3();
}
}
La ejecucin de la clase Disposicion3 en el sistema operativo Windows XP, desplegar la siguiente
ventana:
Figura 36. Disposicin de componentes en BorderLayout
Existen ms formas de acomodar componentes en un pnel. Para conocer otras clases para la
disposicin de componentes consultar las interfaces LayoutManager y LayoutManager2 en la API de
Java. Si agregamos pneles dentro de pneles y asignamos a cada uno layouts diferentes, podemos
acercarnos al acomodo de componentes ms deseado.
11.5 Manejo de eventos con componentes Swing
En esta seccin aprenderemos a controlar los eventos que desencadena Java cada vez que se pulsa un
botn o se cambia la seleccin de una lista o cuadro combinado.
11.5.1 JButton
Si de desea detectar que un botn se ha presionado, es necesario asignarle un objeto listener, esto es,
aquel que est siempre escuchando o al tanto de los cambios sucedidos con el botn. De esta
manera, cuando un usuario presione el botn, el listener deber reaccionar y avisar a la aplicacin de tal
evento para que sta responda con una serie de acciones.
Para tales propsitos, Java proporciona la interfaz ActionListener que pertenece al paquete
java.awt.event. La clase que est interesada en procesar los eventos desencadenados al pulsar un botn,
deber implementar esta interfaz, incluyendo su nico mtodo: actionPerformed(ActionEvent e).
Cuando se presiona un botn que est siendo escuchado por un objeto ActionListener, se crea un
objeto de tipo ActionEvent que contiene informacin del evento, y enseguida se ejecuta el mtodo
104 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
actionPerformed. Todo lo que queramos que realice la aplicacin despus de la pulsacin del botn
deber estar contenida en tal mtodo.
La siguiente clase implementa la interfaz ActionListener, por lo tanto, tendr la cualidad de poder
escuchar las pulsaciones que sucedan en algn botn. Cuando se presione algn botn asociado,
aparecer un cuadro de dilogo desplegando la cadena de texto recibida en el consructor de la clase.
import javax.swing.*;
import java.awt.event.*;
public void DesplegarBoton implements ActionListener {
private String nombreBoton;
private JFrame parent;
public DesplegarMensaje(String nb, JFrame parent) {
nombreBoton = nb;
this.parent = parent;
}
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(parent, nombreBoton, Botn presionado,
JOptionPane.INFORMATION_MESSAGE);
}
}
Para asociar la clase DesplegarBoton con algn botn, invocamos el mtodo addActionListener de la
clase JButton, a partir del(os) botn(es) que deseen ser escuchados, y enviamos como parmetro una
instancia de DesplegarBoton. As, esta instancia reaccionar cada vez que se realicen pulsaciones sobre
los botones asociados.
Modificamos la clase Disposicion3 de tal manera que cada vez que se pulse un botn, se despliegue un
cuadro de dilogo con el nombre del botn pulsado.
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
public class Disposicion3 extends JFrame {
JButton botonNorte = new JButton("Norte");
JButton botonCentro = new JButton("Centro");
JButton botonSur = new JButton("Sur");
JButton botonOeste = new JButton("Oeste");
JButton botonEste = new JButton("Este");
public Disposicion3() {
super("Disposicin en BorderLayout");
setSize(300, 150);
setResizable(false);
setDefaultCloseOperation(3);
BorderLayout grid = new BorderLayout();
panel.setBackground(new Color(180, 200, 130));
grid.setHgap(5);
grid.setVgap(10);
JPanel panel = (JPanel) getContentPane();
panel.setBorder(new SoftBevelBorder(SoftBevelBorder.RAISED));
CAPTULO 11: INTERFAZ GRFICA DE USUARIO 105
panel.setLayout(grid);
botonNorte.addActionListener (new DesplegarBoton("Norte" , this));
botonCentro.addActionListener(new DesplegarBoton("Centro", this));
botonSur.addActionListener (new DesplegarBoton("Sur" , this));
botonOeste.addActionListener (new DesplegarBoton("Oeste" , this));
botonEste.addActionListener (new DesplegarBoton("Este" , this));
panel.add(botonNorte , BorderLayout.NORTH);
panel.add(botonCentro, BorderLayout.CENTER);
panel.add(botonSur , BorderLayout.SOUTH);
panel.add(botonOeste , BorderLayout.WEST);
panel.add(botonEste , BorderLayout.EAST);
setVisible(true);
}
public static void main(String[] args) {
new Disposicion3();
}
}
La ejecucin de la clase Disposicion3 desplegar lo siguiente al pulsar el botn Norte:
Figura 37. Efecto de la pulsacin de un botn
11.5.2 JList
Si se desea realizar alguna accin cada vez que el usuario seleccione un elemento diferente de un
cuadro de lista, es necesario asociar a la lista un objeto listener para que est al tanto de los cambios en
la seleccin de sus elementos.
Para tales propsitos, Java proporciona la interfaz ListSelectionListener que pertenece al paquete
javax.swing.event. Para que una clase pueda gestionar los cambios de seleccin de una lista, deber
implementar esta interfaz, incluyendo su nico mtodo: valueChanged(ListSelectionEvent e). Cuando
se selecciona un elemento diferente de una lista, ya sea por accin del usuario o de la aplicacin, se
crea un objeto de tipo ListSelectionEvent que contiene informacin del evento, y enseguida se ejecuta
el mtodo valueChanged. Todo lo que queramos que realice la aplicacin despus del cambio de
seleccin de la lista deber estar contenida en tal mtodo.
La siguiente clase implementa la interfaz ListSelectionListener, por lo tanto, tendr la cualidad de
poder escuchar los cambios que sucedan en alguna lista. Cuando se cambie la seleccin de la lista
asociada, aparecer un cuadro de dilogo desplegando el elemento seleccionado.
106 PROGRAMACIN ORIENTADA A OBJETOS EN JAVA
import javax.swing.*;
import javax.swing.event.*;
public class DesplegarElemento implements ListSelectionListener {
private JFrame parent;
private JList lista;
public DesplegarElemento(JFrame parent, JList lista) {
this.parent = parent;
this.lista = lista;
}
public void valueChanged(ListSelectionEvent e) {
if(lista.getValueIsAdjusting()) return;
String elemento = (String) lista.getSelectedValue();
JOptionPane.showMessageDialog(parent, elemento, "Elemento seleccionado",
JOptionPane.PLAIN_MESSAGE);
}
}
Para asociar la clase DesplegarElemento con alguna lista, invocamos el mtodo
addListSelectionListener de la clase JList, a partir del(as) lista(s) que deseen ser escuchadas, y
enviamos como parmetro una instancia de DesplegarElemento. As, esta instancia reaccionar cada
vez que se realicen cambios de seleccin sobre las listas asociadas.
La siguiente clase despliega un cuadro de dilogo con el nombre del elemento seleccionado de la lista,
cada vez que se haga un cambio de seleccin.
import javax.swing.*;
import java.awt.*;
import javax.swing.border.*;
public class EventosLista extends JFrame {
private final Color AZUL = new Color(150, 180, 200);
private String[] nombres = {"Abstraccion", "Modularidad",
"Encapsulamiento", "Agregacion",
"Herencia", "Polimorfismo"};
private JLabel titulo = new JLabel("Caractersticas de un LOO");
private JList lista = new JList(nombres);
private JScrollPane scroll = new JScrollPane(lista);
public EventosLista() {
super("Captura de eventos de una lista");
setSize(320, 150);
setResizable(false);
setDefaultCloseOperation(3);
BorderLayout grid = new BorderLayout();
grid.setVgap(5);
titulo.setHorizontalAlignment(JLabel.CENTER);
lista.setFixedCellWidth(100);
lista.setFixedCellHeight(22);
lista.setBackground(AZUL);
lista.setForeground(Color.blue);
lista.setSelectionBackground(Color.yellow);
lista.setSelectionForeground(Color.red);
CAPTULO 11: INTERFAZ GRFICA DE USUARIO 107
lista.addListSelectionListener(new DesplegarElemento(this, lista));
JPanel panel = (JPanel) getContentPane();
panel.setLayout(grid);
panel.setBackground(AZUL);
panel.setBorder(new SoftBevelBorder(SoftBevelBorder.LOWERED));
panel.add(titulo, BorderLayout.NORTH);
panel.add(scroll, BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args) {
new EventosLista();
}
}
La ejecucin de la clase EventosLista desplegar lo siguiente al seleccionar el segundo elemento con el
ratn o el teclado:
Figura 38. Efecto del cambio de seleccin de una lista
APNDICE
BIBLIOGRAFA
JAVA 2. Manual de usuario y tutorial. Agustn Froufe. Editorial Alfaomega Ra-Ma. 2 edicin.
Mxico, 2000.
Modelado de objetos con UML. Pierre-Alain Muller. Editorial Eyrolles. Gestin 2000. 1
edicin. Espaa, 1997.
Cmo programar en Java. Harvey M. Deitel, Paul J. Deitel. Editorial Prentice-Hall. 1 edicin.
Mxico, 1997.
Cmo programar en C/C++. Harvey M. Deitel, Paul J. Deitel. Editorial Prentice-Hall. 2 edicin.
Mxico, 1995.
Conceptos de orientacin a objetos.
URL: http://www.dei.uc.edu.py/tai2000/c++/down2.htm
Programacin en lenguaje Java.
URL: http://www.sc.ehu.es/sbweb/fisica/cursoJava/Intro.htm
Tutorial de Java.
URL: http://www.cica.es/formacion/JavaTut/Cap1/concept.html
Gua de iniciacin al Lenguaje JAVA.
URL: http://pisuerga.inf.ubu.es/lsi/Invest/Java/Tuto/Index.htm
Historia de Java
URL: http://personales.com/ecuador/machala/Java1/historia.html
Apuntes Lenguaje Java.
URL: http://www.arrakis.es/~abelp/ApuntesJava/indice.htm#logoJava