Escolar Documentos
Profissional Documentos
Cultura Documentos
C A PT U L O 2. PR O G R A M A C I N O R IE N T A D A A O B JE T O S .............................. 23
C A PT U L O 3. E LE M EN TO S D EL L E N G U A JE ............................................................ 37
C A P T U L O 4. ESTR U C T U R A DE UN P R O G R A M A .................................................. 63
C A P T U L O 7. M A T R IC E S .................................................................................................... 163
C A P T U L O 8. M T O D O S ..................................................................................................... 215
PA R TE 4. A P N D IC E S .................................................................. 751
A. A Y U D A ................................................................................................................................... 753
B. JA V A C O M PA R A D O C O N C /C + + ................................................................................ 755
D. C O N T E N ID O D E L C D -R O M ......................................................................................... 761
E. C D IG O S DE C A R A C T E R E S ........................................................................................ 763
F. N D IC E .................................................................................................................................... 769
CONTENIDO
P R L O G O ............................................................................................................................ X X III
C A P T U L O 1. F A S E S EN E I. D E S A R R O L L O D E U N P R O G R A M A 3
Q U ES UN P R O G R A M A ............................................................................................... 3
LEN G U A JES D E P R O G R A M A C I N ......................................................................... 4
C o m p ila d o re s................................................................................................................... 6
Intrpretes.......................................................................................................................... 6
Q U ES J A V A ? ................................................................................................................. 7
H ISTO R IA DE J A V A ......................................................................................................... 8
PO R Q U A PR EN D ER J A V A ? ................................................................................... 9
R EA L IZ A C I N DE UN PR O G R A M A EN J A V A ................................................... 9
C m o crear un p ro g ram a.............................................................................................. 11
Interfaz de lnea de rd e n es......................................................................................... 12
Q u hace este p ro g ram a?...................................................................................... 12
G uardar el program a escrito en el d is c o ............................................................ 13
C om pilar y ejecutar el p ro g ra m a ......................................................................... 13
B iblioteca de fu n c io n e s.......................................................................................... 15
G uardar el program a ejecutable en el disco....................................................... 15
D epurar un p ro g ra m a .............................................................................................. 16
E ntorno de desarrollo in te g ra d o ................................................................................. 16
E JER C IC IO S R E S U E L T O S ............................................................................................. 19
E JER C IC IO S P R O P U E S T O S .......................................................................................... 21
X JA V A: CU R SO DE PROGRAM A CIN
C A P T U L O 2. P R O G R A M A C I N O R IE N T A D A A O B J E T O S ........................ 23
C A P T U L O 3. E L E M E N T O S D E L L E N G U A J E ...................................................... 37
PA L A B R A S C L A V E .......................................................................................................... 47
C O M E N T A R IO S ................................................................................................................. 47
D E C LA R A C I N D E C O N ST A N T E S S IM B L IC A S ............................................ 48
P or qu utilizar c o n sta n te s?............................ 49
D E C L A R A C I N D E U N A V A R IA B L E ...................................................................... 49
Iniciacin d e una v ariab le............................................................................................. 50
E X PR E SIO N ES N U M R IC A S ....................................................................................... 51
C O N V E R S I N E N T R E T IPO S DE D A T O S .............................................................. 51
O P E R A D O R E S ..................................................................................................................... 52
O peradores aritm tico s.................................................................................................. 52
O peradores de re la ci n .................................................................................................. 53
O peradores l g ico s......................................................................................................... 54
O peradores unitarios....................................................................................................... 55
O peradores a nivel de b i t s ............................................................................................ 55
O peradores de asig n aci n ............................................................................................. 56
O perador c o n d ic io n a l.................................................................................................... 57
P R IO R ID A D Y O R D E N D E E V A L U A C I N ........................................................... 58
E JE R C IC IO S R E S U E L T O S ............................................................................................. 58
E JE R C IC IO S P R O P U E S T O S ........................................................................................... 60
C A P T U L O 4. E S T R U C T U R A D E U N P R O G R A M A ............................................. 63
E ST R U C T U R A D E U N A A P L IC A C I N JA V A ...................................................... 63
Paquetes y proteccin de clase s.................................................................................. 67
Proteccin de una c la s e ................................................................................................. 68
S entencia im port.............................................................................................................. 69
D efiniciones y declaracio n es....................................................................................... 70
Sentencia sim p le.............................................................................................................. 71
Sentencia com puesta o blo q u e.................................................................................... 72
M to d o s.............................................................................................................................. 72
D efinicin de un m to d o ........................................................................................ 72
M todo m a in .................................................................................................................... 73
C rear objetos de una c la s e ............................................................................................ 73
C m o acceder a los m iem bros de un o b je to ........................................................... 75
Proteccin de los m iem bros de una c la s e ................................................................ 76
M iem bro de un objeto o de una c la s e ....................................................................... 77
R eferencias a o b jeto s..................................................................................................... 79
P asando argum entos a los m to d o s ........................................................................... 82
PR O G R A M A JA V A FO R M A D O PO R M LTIPLES F IC H E R O S ..................... 83
A C C E SIB IL ID A D D E V A R IA B L E S ............................................................................ 85
E JE R C IC IO S R E S U E L T O S ............................................................................................. 86
E JE R C IC IO S P R O P U E S T O S ........................................................................................... 88
X I I JA V A: C U R S O DE PROGRAM ACIN
C A P T U L O 5. C L A S E S D E U S O C O M N ................................................................... 89
D A TO S N U M R IC O S Y C A D EN A S DE C A R A C T E R E S ................................... 89
EN TR A D A Y S A L ID A ..................................................................................................... 91
Flujos de e n tra d a ............................................................................................................ 93
Flujos de salid a................................................................................................................ 94
E xcepciones...................................................................................................................... 95
Flujos estndar de E /S ................................................................................................... 96
D eterm inar la clase a la que pertenece un o b je to ........................................... 97
B u fferedlnputS tream ............................................................................................... 98
B u ffered R ead er........................................................................................................ 99
P rintStream ................................................................................................................... 100
T rabajar con tipos de datos p rim itiv o s..................................................................... 102
C lases que encapsulan los tipos p rim itiv o s ...................................................... 103
C lase L eer......................................................................................................................... 106
D N D E SE U B IC A N LAS C LA SES Q U E DAN S O P O R T E ?........................... 109
V ariable C L A S S P A T H .................................................................................................. 110
C A R C TE R FIN DE F IC H E R O ...................................................................................... 110
C A R A C TER ES V \n.............................................................................................................. 112
M TO D O S M A T E M T IC O S......................................................................................... 114
EJER C IC IO S R E S U E L T O S ............................................................................................. 116
EJER C IC IO S P R O P U E S T O S .......................................................................................... 119
C A P T U L O 6. S E N T E N C IA S D E C O N T R O L ............................................................. 121
C A P T U L O 7. M A T R IC E S .................................................................................................. 163
C A P T U L O 8. M T O D O S ................................................................................................... 215
R EC U RSIV ID A D 585
CO N TEN ID O X I X
O R D E N A C I N D E D A T O S ........................................................................................... 591
M todo de la b u rb u ja..................................................................................................... 592
M todo de in serc i n ...................................................................................................... 595
M todo q u ick so rt............................................................................................................ 596
C om paracin de los m todos ex p u e sto s.................................................................. 600
B SQ U E D A D E D A T O S .................................................................................................. 600
B squeda secuencial...................................................................................................... 600
B squeda b in a ria............................................................................................................ 601
Bsqueda de cad en as..................................................................................................... 602
O R D E N A C I N DE FIC H ER O S EN D IS C O ............................................................. 605
O rdenacin de ficheros. A cceso secuencial............................................................ 606
O rdenacin de Ficheros. A cceso a le a to rio ............................................................... 614
A L G O R ITM O S H A S H ...................................................................................................... 616
M atrices h ash .................................................................................................................... 617
M todo hash a b ie rto ...................................................................................................... 618
M todo hash con d esb o rd am ien to ............................................................................. 619
E lim inacin de elem entos............................................................................................. 620
C lase C H ash A b ierto ...................................................................................................... 620
U n ejem plo de una m atriz h a s h .................................................................................. 624
E JE R C IC IO S R E S U E L T O S ...................................................................................... 627
E JE R C IC IO S P R O P U E S T O S .......................................................................................... 631
Q U ES IN T E R N E T ?...................................................................................................... 688
In tra n e t.............................................................................................................................. 689
E x tra n e t............................................................................................................................. 689
T erm inologa In tern et.................................................................................................... 689
SERV IC IO S EN IN T E R N E T ............................................................................................ 692
P G IN A S W E B .................................................................................................................... 695
Q u es H T M L .................................................................................................................. 695
Etiquetas bsicas H T M L .............................................................................................. 696
Etiquetas de form ato de te x to ..................................................................................... 697
U R L .................................................................................................................................... 699
Enlaces entre p g in a s.................................................................................................... 699
G rfico s............................................................................................................................. 701
M arco s............................................................................................................................... 702
O tro s................................................................................................................................... 703
PGIN AS W EB D IN M IC A S ....................................................................................... 703
A P P L E T S ............................................................................................................................... 705
C rear un a p p le t................................................................................................................ 705
La clase A p p let................................................................................................................ 707
public void init()........................................................................................................ 708
public void s ta rt()..................................................................................................... 708
public void paint(G raphics g ) ............................................................................... 708
public void s to p ()..................................................................................................... 708
public void d estro y O ............................................................................................... 709
Un ejem plo sim ple.......................................................................................................... 709
C O N TE N ID O X X I
PA R TE 4. A P N D IC E S ................................................................. 751
A. A Y U D A ................................................................................................................................... 753
B. JA V A C O M P A R A D O C O N C /C + + ............................................................................ 755
C . P L A T A F O R M A S U N IX /L IN U X ................................................................................. 759
D. C O N T E N ID O D E L C D -R O M ....................................................................................... 761
E . C D IG O S D E C A R A C T E R E S .................................................................................... 763
F. N D I C E ................................................................................................................................... 769
PARTE
Programacin bsica
Fases en el desarrollo de un program a
Program acin orientada a objetos
Elem entos del lenguaje
E structura de un program a
Clases de uso com n
Sentencias de control
M atrices
M todos
CA PTU LO 1
F.J.Cebalos/RA-MA
FASES EN EL DESARROLLO DE
UN PROGRAMA
E n este captulo aprender lo que es un program a, cm o escribirlo y qu hacer pa
ra que el ordenador lo ejecute y m uestre los resultados perseguidos. T am bin ad
quirir conocim ientos generales acerca de los lenguajes de program acin
utilizados para escribir program as. D espus, nos centrarem os en un lenguaje de
program acin especfico y objetivo de este libro, Java, presentando sus antece
dentes y m arcando la pauta a seguir para realizar un program a sencillo.
QU ES UN PROGRAMA
Probablem ente alguna vez haya utilizado un ordenador para escribir un docum ento
o para divertirse con algn juego. R ecuerde que en el caso de escribir un docu
m ento, prim ero tuvo que poner en m archa un procesador de textos, y que si quiso
divertirse con un juego, lo prim ero que tuvo que hacer fue poner en m archa el
juego. T anto el procesador de textos com o el ju eg o son program as de ordenador.
LENGUAJES DE PROGRAMACIN
Un program a tiene que escribirse en un lenguaje entendible p o r el ordenador.
D esde el punto de vista fsico, un ordenador es una m quina electrnica. Los ele
m entos fsicos (m em oria, unidad central de proceso, etc.) de que dispone el orde
nador para representar los datos son de tipo binario; esto es, cada elem ento puede
diferenciar d o s estados (dos niveles de voltaje). C ada estado se denom ina genri
cam ente b it y se sim boliza por 0 / . P or lo tanto, para representar y m anipular
inform acin num rica, alfabtica y alfanum rica se em plean cadenas de bits. S e
gn esto, se denom ina byte a la cantidad de inform acin em pleada por un ordena
d o r para representar un carcter; generalm ente un byte es una cadena de ocho bits.
i S
L
A s, por ejem plo, cuando un program a le dice al ordenador que visualice un
m ensaje sobre el m onitor, o que lo im prim a sobre la im presora, las instrucciones
correspondientes para llevar a cabo esta accin, para que puedan ser entendiles
por el ordenador, tienen que estar alm acenadas en la m em oria com o cadenas de
bits. Esto hace pensar que escribir un program a utilizando ceros y unos (lenguaje
m quina), llevara m ucho tiem po y con m uchas posibilidades de com eter errores.
Por este m otivo, se desarrollaron los lenguajes ensam bladores.
zar. Un cdigo nem otcnico es una palabra o abreviatura fcil de recordar que re
presenta una tarea que debe realizar el procesador del ordenador. Por ejem plo:
printft "hola" ):
Compiladores
Para traducir un program a escrito en un lenguaje de alto nivel (program a fuente) a
lenguaje m quina se utiliza un program a llam ado com pilador. Este program a to
m ar com o datos nuestro program a escrito en lenguaje de alto nivel y dar com o
resultado el m ism o program a pero escrito en lenguaje m quina, program a que ya
puede ejecutar directa o indirectam ente el ordenador.
Por ejem plo, un program a escrito en el lenguaje C necesita del com pilador C
para poder ser traducido. Posteriorm ente el program a traducido podr ser ejecuta
do directam ente p o r el ordenador. E n cam bio, para traducir un program a escrito
en el lenguaje Java necesita del com pilador Java; en este caso, el lenguaje m qui
na no corresponde al del ordenador sino al de una m quina ficticia, denom inada
m quina virtual Java, que ser puesta en m archa por el ordenador para ejecutar el
program a.
Intrpretes
A diferencia de un com pilador, un intrprete no genera un program a escrito en
lenguaje m quina a partir del program a fuente, sino que efecta la traduccin y
ejecucin sim ultneam ente para cada una de las sentencias del program a. Por
ejem plo, un program a escrito en el lenguaje B asic necesita el intrprete B asic para
ser ejecutado. D urante la ejecucin de cada una de las sentencias del program a,
ocurre sim ultneam ente la traduccin.
QU ES JAVA?
Java es un lenguaje de program acin de alto nivel con el que se pueden escribir
tanto program as convencionales com o para Internet.
Segn lo expuesto, Java incluye dos elem entos: un com pilador y un intrpre
te. El com pilador produce un cdigo de bytes que se alm acena en un fichero para
ser ejecutado por el intrprete Java denom inado m quina virtual de Java.
P or qu no se dise Java para que fuera un intrprete m s entre los que hay
en el m ercado? La respuesta es porque la interpretacin, si bien es cierto que pro
porciona independencia de la m quina, conlleva tam bin un problem a grave, y es
la prdida de velocidad en la ejecucin del program a. Por esta razn la solucin
fue d isear un com pilador que produjera un lenguaje que pudiera ser interpretado
a velocidades, si no iguales, s cercanas a la de los program as nativos (program as
en cdigo m quina propio de cada ordenador), logro conseguido m ediante la m
quina virtual de Java.
8 JA V A , C U R SO D E PROGRAM A CIN
C on todo, las aplicaciones todava adolecen de una falta d e rendim iento apre-
ciable. Este es uno de los problem as que siem pre se ha achacado a Java. A fortu
nadam ente, la diferencia de rendim iento con respecto a aplicaciones equivalentes
escritas en cdigo m quina nativo ha ido dism inuyendo hasta m rgenes m uy re
ducidos gracias a la utilizacin de com piladores JIT (Just In Tim e - com pilacin
al instante).
Un com pilador JIT interacciona con la m quina virtual para convertir el cdi
go de bytes en cdigo m quina nativo. C om o consecuencia, se m ejora la veloci
dad durante la ejecucin. Sun sigue trabajando sobre este objetivo y prueba de
ello son los resultados que se estn obteniendo con el nuevo y potente m otor de
ejecucin H otSpot (H otSpot P erfom ance E ngine) que ha diseado, o por los m i
croprocesadores especficos p ara la interpretacin hardw are d e cdigo de bytes.
HISTORIA DE JAVA
El lenguaje de program acin Java fue desarrollado por Sun M icrosystem s en
1991. N ace com o parte de un proyecto de investigacin para desarrollar softw are
para com unicacin entre aparatos electrnicos de consum o com o vdeos, televiso
res, equipos de m sica, etc. D urante la fase de investigacin surgi un problem a
que dificultaba enorm em ente el proyecto iniciado: cada aparato tena un m icro-
procesador diferente y m uy poco espacio de m em oria; esto provoc un cam bio en
el rum bo de la investigacin que desem boc en la idea de escribir un nuevo len
guaje de program acin independiente del dispositivo que fue bautizado inicial-
m ente com o Oak.
Java est fundam entado en C++. Q uiere esto d ecir que m ucha de la sintaxis y
diseo orientado a objetos se tom de este lenguaje. P or lo tanto, a los lectores
que estn fam iliarizados con C++ y la PO O les ser m uy fcil aprender a d esa rro
llar aplicaciones con Java. Q uiero advertir a este tipo de potenciales usuarios de
Java que en este lenguaje no existen punteros ni aritm tica de punteros, las cade
nas de caracteres son objetos y la adm inistracin de m em oria es autom tica, lo
que elim ina la problem tica que presenta C++ con las lagunas de m em oria al o l
vidar liberar bloques de la m ism a que fueron asignados dinm icam ente.
E n to rn o d e d es a rro llo
de Java
1. E d ita r el p ro g ra m a
2 . C o m p ilarlo
3. E je c u ta rlo
4 . D e p u ra rlo
A s m ism o, el C D que acom paa al libro incluye Java 2 SD K versin 1.3 para
W indow s 9x, W indow s 20(X)/NT, y Unix. Se trata del nuevo JD K 1.3. En cual
quier caso, en Internet se encuentran todas las versiones para W indow s, M acin
tosh y Unix (Solaris y otros). Vea tam bin el apndice C.
dk1.3
G bin
GE G demo
5) G d o cs
E G include
B G include old
E G ie
G l>b
La carpeta bin contiene las herram ientas de desarrollo. Esto es, los program as
para com pilar (javac), ejecutar (Java), depurar jd b ) , y docum entar (Javadoc)
los program as escritos en el lenguaje de program acin Java, y otras herra
m ientas com o appletview er para ejecutar y depurar applets sin tener que utili
zar un navegador, j a r para m anipular ficheros .ja r (un fichero .ja r es una
coleccin de clases Java y otros ficheros em paquetados en uno solo), ja va h
que es un fichero de cabecera para escribir m todos nativos, ja v a p para d es
com pilar ficheros com pilados y extcheck para detectar conflictos ja r.
C A PTU LO I: FASES EN EL D ESA RRO LLO DE UN PROGRAM A 11
La carpeta irtclude contiene los ficheros de cabecera que dan soporte para
aadir a un program a Java cdigo nativo (cdigo escrito en un lenguaje dis
tinto de Java, por ejem plo Ada o C++).
L a carpeta include-old contiene los ficheros de cabecera que dan soporte para
aadir a un program a Java cdigo nativo utilizando interfaces antiguas.
El nuevo JD K 1.3 incluye un com pilador JIT para ejecutar el cdigo en Java.
Por om isin el com pilador JIT em pleado ser jre\bin\sym jit.dll.
Slo falta un editor de cdigo fuente Java. Es suficiente con un editor de texto
sin form ato; por ejem plo el bloc de notas de W indow s. No obstante, todo el tra
bajo de edicin, com pilacin, ejecucin y depuracin, se har m ucho m s fcil si
se utiliza un entorno de desarrollo con interfaz grfica de usuario que integre las
herram ientas m encionadas, en lugar de tener que u tilizar las interfaz de lnea de
rdenes del JD K , com o verem os a continuacin.
E ntornos de desarrollo integrados para Java hay m uchos: Forte de Sun, Visual
Cafe' de Sym antec, JB uilder de B orland, K awa de T ek-T ools, Visual A g e W in
dow s de IBM , pcG R A SP de A ubum U niversity, Visual J++ de M icrosoft, etc. Las
versiones de dem ostracin operativas de algunos de ellos las tiene en el C D que se
adjunta con este libro. C oncretam ente, pcG R A SP es un entorno integrado sencillo,
que no requiere licencia, y que se ajusta a las necesidades de las aplicaciones que
sern expuestas en este libro.
E sta sencilla aplicacin la realizarem os desde los dos puntos de vista com en
tados anteriorm ente: utilizando la interfaz de lnea de rdenes del JD K y utilizan
do un entorno de desarrollo integrado.
class HolaMundo
I
/*
* P u n t o de e n t r a d a a la aplicacin.
*
* a r g s : m a t r i z de p a r m e t r o s p a s a d o s a l a a p l i c a c i n
* m e d i a n t e l a l i n e a de r d e n e s . Puede e s t a r v a c i a .
*/
public static void m a in (S trin g [] args)
I
System .out.println("H ola mundo!! ! " ) ;
La prim era lnea declara la clase de objetos H olaM undo, porque el esqueleto
de cualquier aplicacin Java se basa en la definicin de una clase. A continuacin
se escribe el cuerpo de la clase encerrado entre los caracteres { y }. A m bos ca
racteres definen un bloque de cdigo. T odas las acciones que va a llevar a cabo un
program a Java se colocan dentro del bloque de cdigo correspondiente a su clase.
Las clases son la base d e los program as Java. A prenderem os m ucho sobre ellas en
los prxim os captulos.
C A P T U L O I: FASES EN EL D ESA RRO LLO DE UN PROGRAM A 13
Las siguientes lneas encerradas entre /* y */ son sim plem ente un com entario.
Los com entarios no son tenidos en cuenta p o r el com pilador, pero ayudan a en
tender un program a cuando se lee.
El program a editado est ahora en la m em oria. Para que este trabajo pueda tener
continuidad, el program a escrito se debe grabar en el disco utilizando la orden co
rrespondiente del editor. M uy im portante: el nom bre del program a fuente debe ser
el m ism o que el de la clase que contiene, respetando m aysculas y m insculas. En
nuestro caso, el nom bre de la clase es H olaM undo, por lo tanto el fichero debe
guardarse con el nom bre H olaM undo.java.
El siguiente paso es com pilar el program a; esto es, traducir el program a fuente a
cdigo de bytes para posteriorm ente poder ejecutarlo. La orden para com pilar el
program a H olaM undo.java es la siguiente:
javac HolaMundo.java
pa t h = %p a t h % : c : \ j d k l . 3 \ b i n
-M S-D O S P I C T E S ||
l A ! le tal ls Al
M i c r o s o f t ( R ) Windows 98
( C ) C o p y r iq lit M i c r o s o f t C o rp 1 * 8 1 - 1 9 .
C :\ W IN D B M S > p < l h - # p * t M ; e : \ j * \ j i l k 1 . 3 \ b i n
G :\W IH II 0WS>cd C : \ C a p 0 1 \ H o Ia M u n d o
C : \ C a p 0 1 \ H o l. iH u n d o > d ir
E l v o l u n e n de la u n i d a d C na t i m a e t i q u e t a
E l m in e r o de s e r i e d e l u o t u n e n e s 2 F 1 F - 0 7 F 8
D i r e c t o r i o de C : \ C a p 0 1 V H o ia M u n d o
<111R> 05/06/011 2 7 : 2 8 .
< 0 IR > D 5/06/ D0 2 2 : 2 8 ..
H 0 IA M I T 1 J8U 299 05/06/00 0 :0 0 H o loH undo.jaoa
1 a rch ivas 29 b ytes
2 d ire cto rio s 1.530.392.576 bytes lib r e s
C : \ C a p 0 1 \ H o laMimdo>
O bsrvese que para com pilar un program a hay que especificar la extensin
.java. El resultado de la com pilacin ser un fichero H olaM undo.class que con
tiene el cdigo de bytes que ejecutar la m quina virtual de Java.
1 -M S-D O S B R E J|
1 A iji j J -.ilN fe l ESI f f l s a |
<0 IR >
05/06/00 22: ? :
1
< 0 R>
05/06/00 2 2 :2 8 ..
II0L8MU-1 JflU 22? 05/06/00 0 : 0 0 N o lo M u n d o . jo mo
1 o rc h iu o * 2 2 ? bytes
2 d ire cto rio s 1 .538.32 2.5 /6 bytes l i b r e *
< D IR >
05/ U6/ D 0 2 2 : 2 8 .
<111R>
05/116/011 2 2 : 2 8 ..
H0LMU*1 JflU 222 05/06/00 0:00 H o lo M und o.jo *o
II0LBMU-1 CLfl 625 05/06/00 22:60 H o lo M u n d o .e lo ss
2 orc h iu o s 726 b y t e s
2 d ire c to rio s 1. 5 2 1 1 .7 6 6 . 2 / 6 b y t e s l i b r e s
Biblioteca de funciones
S y s t e m . o u t . p r i n t l n ( H o l a m u n d o ! ! ! " ) ;
Com o hem os visto, cada vez que se realiza el proceso de com pilacin del progra
ma actual. Java genera autom ticam ente sobre el disco un fichero .class. Este fi
chero puede ser ejecutado directam ente desde el sistem a operativo, con el soporte
de la m quina virtual de Java, que se lanza invocando a la utilidad ja v a con el
nom bre del fichero com o argum ento.
1 6 JA VA : C U R SO D E PROGRAM A CIN
Hay otro tipo de errores que no dan lugar a m ensaje alguno. P or ejem plo: un
program a que no term ine nunca de ejecutarse, debido a que presenta un lazo,
donde no se llega a dar la condicin de term inacin. Para detener la ejecucin se
tienen que pu lsar las teclas C trl+ C (en un entorno integrado se ejecutar una or
den equivalente a D etener ejecucin).
Depurar un programa
Una vez ejecutado el program a, la solucin puede ser incorrecta. E ste caso exige
un anlisis m inucioso de cm o se com porta el program a a lo largo de su ejecu
cin; esto es, hay que entrar en la fase de depuracin del program a.
Para depurar un program a Java debe com pilarlo con la opcin -g. Por ejem
plo, desde la lnea de rdenes esto se hara as:
javac -g A r i t m e t i c a . j ava
D M B 1 J J P J M JjJK J |= l* l * 1 * 1 * 1 M * I J a i
| G o n o M e C SD 1 Rw noveC SD I Fort Seo: |--------------------- |10
c la a a HolaMundo
P u n c o d e e n t r a d o a l o apli c a c i n .
* orgs: m a t r i z d e p a r m e t r o s p o s a d o s o l a a p l i c a c i n
m e d i a n t e la l i n e a d e rd e n e s . P u e d e e s t a r vacia.
' i i
i---------------------------------------------------------------------------------------------------------------------
j a v a c C : \ C a p 0 1 \ H o la M iin d c i\ H o la M u n d o . j a v a
| P fo r.e sG F i n is h e d
Para editar y ejecutar la aplicacin H olaM undo anterior utilizando este entor
no de desarrollo integrado, los pasos a seguir se indican a continuacin:
3. Finalm ente, suponiendo que la com pilacin se efectu satisfactoriam ente, eje
cutarem os la aplicacin seleccionando la orden R un C aptured, o bien Run, del
men R un. Este paso exige que se est visualizando el fichero que contiene la
clase aplicacin.
O M B I - P I P I E I - 5 1 ! i = | . = 1k | A l M l x l j U m i H r l m
... i .. .. . . i~ i .... . i
p u b l i c c l a s e C A p llc n c io n
( F i le s
p u b lic s ta tic v o i d ro o ln (Strlng[] args)
< 6 CApicacicri
/ / P u n t o de e n t r a d o a l a a p l i c a c i n CApIcaoon va
C R o c io n a l r 1 , r 2 ; CRacional java
rl = n e v C R a c l o n a l (); // crear un o b j e t o CRaclonal
r 1 . A s i g n a r D a t o s (2, 5);
r 2 = rl;
r 1 . A s i g n a r D a t o s (3, 7 );
r l. V is u a liz a r R a c io n a l(); // ae visualiza 3/7
r 2 .V l s u a l l z a r R a c i o n a l ( ) ; // ae visualiza 3/7
SL
P r o c e s e F l n is h e d
4. Finalm ente, para com pilar y ejecutar la aplicacin, se procede com o se expli
c anteriorm ente.
EJERCICIOS RESUELTOS
Para practicar con un program a m s, escriba el siguiente ejem plo y pruebe los re
sultados. Hgalo prim ero desde la lnea de rdenes y despus con el entorno de
desarrollo integrado preferido por usted. El siguiente ejem plo visualiza com o re
sultado la sum a, la resta, la m ultiplicacin y la divisin de dos cantidades enteras.
Edicin
A bra el procesador de textos o el editor de su entorno integrado y edite el progra
m a ejem plo q ue se m uestra a continuacin. R ecuerde, el nom bre del fichero
fuente tiene que coincidir con el nom bre de la clase, C Aritm etica, respetando m a
ysculas y m insculas, y debe tener extensin .java.
d a t o l = 20;
d a t o 2 = 10:
20 JA VA : C U R SO DE PROGRAM A CIN
// Suma
re su lta d o = datol + dato2;
System .out.printlndatol + " + " + dato2 + " = " + r e s u lta d o ):
// R e s t a
re su lta d o = datol - dato2;
System .out.p rin t ln t d a t o l + " - " + dato2 + " = " + r e s u lta d o ):
// P r o d u c t o
re su lta d o = datol * dato2;
System .out.p rin tln fd a to l + * " + dato2 + " = " + r e s u l t a d o ) :
II C o c i e n t e
r e s u lt a d o = datol / dato2:
System, out. p r i n t l n t d a t o l + " / " + d a t o 2 + ' = " + r e s u l t a d o ) :
U na vez editado el program a, gurdelo en el disco con el nom bre C Aritm eti-
ca.java.
d a t o l = 20:
d a t o 2 = 10:
20 i 10 = 30
O bserve que la expresin resultante est form ada por cinco elem entos: d a to l,
" + ", dato2, " = ", y resultado. U nos elem entos son num ricos y otros son cons-
CA PTU LO 1: FASES EN EL D ESA RRO LLO DE UN PRO G R A M A 2 1
tantes de caracteres. Para unir los cinco elem entos en uno solo, se ha em pleado el
operador +.
EJERCICIOS PROPUESTOS
Practique la edicin, la com pilacin y la ejecucin con un program a sim ilar al
program a A ritm e tic a ja v a realizado en el apartado anterior. Por ejem plo, m odif-
quelo para que ahora realice las operaciones de sum ar, restar y m ultiplicar con
tres datos: d a to /, dato2. dato3. En un segundo intento, puede tam bin com binar
las operaciones aritm ticas.
CA PTU LO 2
<S>F.J.Ceballos/KA-MA
PROGRAMACIN ORIENTADA A
OBJETOS
La program acin orientada a objetos (PO O ) es un m odelo de program acin que
utiliza objetos, ligados m ediante m ensajes, para la solucin de problem as. Puede
considerarse com o una extensin natural de la program acin estructurada en un
intento de potenciar los conceptos de m odularidad y reutilizacin del cdigo.
cuentaOl.Transferencia(cuenta02);
Objetos
Un program a orientado a objetos se com pone solam ente de objetos, entendiendo
por objeto u na encapsulacin genrica de datos y de los m todos para m anipular
los. D icho de otra form a, un objeto es una entidad que tiene unos atributos parti
culares. las propiedades, y unas form as de operar sobre ellos, los mtodos.
Por ejem plo, una ventana de una aplicacin W indow s es un objeto. El color
de fondo, la anchura, la altura, etc. son propiedades. Las rutinas, lgicam ente
transparentes al usuario, que perm iten m axim izar la ventana, m inim izarla, etc. son
m todos.
Mensajes
C uando se ejecuta un program a orientado a objetos, los objetos estn recibiendo,
interpretando y respondiendo a m ensajes de otros objetos. Esto m arca una clara
diferencia con respecto a los elem entos de datos pasivos de los sistem as tradicio
nales. En la POO un m ensaje est asociado con un m todo, de tal form a que
cuando un objeto recibe un m ensaje la respuesta a ese m ensaje es ejecutar el m
todo asociado.
P o r ejem plo, cuando un usuario quiere m axim izar una ventana de una aplica
cin W indow s, lo que hace sim plem ente es pulsar el botn de la m ism a que reali
za esa accin. Eso, provoca que W indow s enve un m ensaje a la ventana para
indicar que tiene que m axim izarse. C om o respuesta a este m ensaje se ejecutar el
m todo program ado para ese fin.
Mtodos
U n m todo se im plem enta en una clase de objetos y determ ina cm o tiene que
actuar el objeto cuando recibe el m ensaje vinculado con ese m todo. A su vez, un
m todo puede tam bin enviar m ensajes a otros objetos solicitando una accin o
inform acin.
o bjeto
m e n s a je s d ato s
m to d o s
Clases
U na clase es un tipo de objetos definido por el usuario. U na clase equivale a la
generalizacin de un tipo especfico de objetos. Por ejem plo, piense en un m olde
para hacer flanes; el m olde es la clase y los flanes los objetos.
CCuenta c l i e n t e O I = new C C u e n t a O ; // n u e v a c u e n t a
A fortunadam ente no tendr que escribir todas las clases que necesite en su
program a, porque Java proporciona una biblioteca de clases estndar para realizar
las operaciones m s habituales que podam os requerir. Por ejem plo, en el captulo
anterior, vim os que la clase S y stem tena un atributo o u t que era un objeto de la
clase P rin tS tre a m que, de form a predeterm inada, est ligado al dispositivo de
salida (a la pantalla). A su vez, la clase P rin tS tre a m proporciona un m todo de
nom inado p r in tln que acepta com o argum ento una cadena de caracteres. De esta
form a, cuando el objeto o u t reciba el m ensaje p rin tln , responder ejecutando este
m todo, que enva la cadena pasada com o argum ento al dispositivo de salida.
class COrdenador
I
// ...
I
O bservam os que para declarar una clase hay que utilizar la palabra reservada
class seguida del nom bre de la clase y del cuerpo de la m ism a. El cuerpo de la
clase incluir entre { y } los atributos y los m todos u operaciones que definen su
com portam iento.
Los atributos tam bin pueden incluir inform acin sobre el estado del objeto;
por ejem plo, en el caso de un ordenador, si est encendido o apagado, si la pre
sentacin en pantalla est activa o inactiva, etc.
C A P T U L O 2: PR O G R A M A C I N O R IE N TA D A A O BJETO S 2 7
class COrdenador
1
S t r i n g Marca:
S t r in g Procesador:
Strin g Pantalla:
boolean OrdenadorEncendido;
boolean P re se n ta c i n :
II...
I
O bserve que se han definido cinco atributos: tres de ellos, M arca, Procesador
y P antalla, pueden contener una cadena de caracteres (una cadena de caracteres
es un objeto de la clase S trin g perteneciente a la biblioteca estndar). Los otros
dos atributos, O rdenadorE ncendido y P resentacin , son de tipo b o o lean (un atri
buto de tipo b o o lean puede contener un valor tr u e o false; verdadero o falso).
Debe respetar las m aysculas y las m insculas.
El com portam iento define las acciones que el objeto puede em prender. Por
ejem plo, pensando acerca de un objeto de la clase C O rdenador, esto es, de un o r
denador, algunas acciones que ste puede hacer son:
0 Ponerse en m archa
0 A pagarse
0 D esactivar la presentacin en la pantalla
0 A ctivar la presentacin en la pantalla
0 C argar una aplicacin
Para definir este com portam iento hay que crear m todos. Los m todos son
rutinas de cdigo definidas dentro de la clase, que se ejecutan en respuesta a algu
na accin tom ada desde dentro de un objeto de esa clase o desde otro objeto de la
m ism a o de otra clase. R ecuerde que los objetos se com unican m ediante m ensajes.
void EncenderOrdenadort)
I
if ( O r d e n a d o r E n c e n d i d o t r u e ) // s i e s t encendido...
S y s t e m . o u t . p r i n t l n ( " E l orden ador ya e s t en m a r c h a . " ) :
e l s e // s i no e s t e n c e n d i d o , e n c e n d e r l o .
I
OrdenadorEncendido = true:
S y s t e m . o u t . p r i n t l n t " E l o r d e n a d o r s e ha e n c e n d i d o . " ) :
void EstadoO
I
S y s t e m . o u t . p r i n t l n t " \ n E s t a d o del o r d e n a d o r : " +
" \ n M a r c a " + Marca +
"\nProcesador " + Procesador +
\ n P a n t a lla " + P a n ta lla + " \ n " ) ;
i f (OrdenadorEncendido = t r u e ) // s i el o r d e n a d o r e s t e n c e n d i d o . . .
S y s t e m . o u t . p r i n t l n ( " E l o r d e n a d o r e s t e n c e n d i d o . ):
e l s e // s i no e s t e n c e n d i d o . . .
S ystem .o ut.p r i n t l n ( " E l ordenador est apagado."):
I
En este instante, si nuestras pretensiones slo son las expuestas hasta ahora,
ya tenem os creada la clase C O rdenador. Para poder crear objetos de esta clase y
trabajar con ellos, tendrem os que escribir un program a, o bien aadir a esta clase
CA PTU LO 2: PRO G R A M A CI N O R IEN TA D A A O BJETO S 2 9
el m todo m ain. Siem pre que se trate de una aplicacin (no de un applet) es obli
gatorio que la clase que define el com ienzo de la m ism a incluya un m todo m ain.
C uando se ejecuta una clase Java com pilada que incluye un m todo m ain . ste es
lo prim ero que se ejecuta.
c l a s s COrdenador
I
S t r i n g Marca:
S t r in g Procesador;
Strin g Pantalla;
boolean OrdenadorEncendido;
boolean P r e s e n t a c i n ;
void EncenderOrdenador)
I
if ( O r d e n a d o r E n c e n d i d o = = t r u e ) // s i e s t e n c e n d i d o . . .
S y s t e m . o u t . p r i n t l n C E l o r d e n a d o r ya e s t e n c e n d i d o . " ) ;
e l s e // s i no e s t e n c e n d i d o , e n c e n d e r l o .
I
OrdenadorEncendido = true;
S y s t e m . o u t . p r i n t l n t " E l o r d e n a d o r s e ha e n c e n d i d o . );
void Estado)
I
S y s t e m . o u t . p r i n t l n ( " \ n E s t a d o del o r d e n a d o r : +
\nMarca + Marca +
"XnProcesador + Procesador +
\ n P a n t a l l a + P a n t a l l a + \ n );
i f ( O r d e n a d o r E n c e n d i d o = = t r u e ) // s i el ordenador e s t . e n c e n d i do . ..
S y stem .o ut.p r i n t l n ( " E l ordenador est e n ce n d id o.");
e l s e // s i no e s t e n c e n d i d o . . .
S y stem .o ut.p r i n t l n ( " E l ordenador est apagado."):
I
L a prim era lnea crea un objeto de la clase C O rdenador y alm acena una refe
rencia al m ism o en la variable M iO rdenador. Esta variable la utilizarem os pa
ra acceder al objeto en las siguientes lneas. A hora quizs em piece a entender
p o r qu anteriorm ente decam os que un program a orientado a objetos se com
pone solam ente de objetos.
Las tres lneas siguientes establecen los atributos del objeto referenciado por
M iO rdenador. Se puede observar que para acceder a los atributos o propieda
des del objeto se utiliza el operador punto (.). De esta form a quedan elim ina
das las am bigedades que surgiran si hubiram os creado m s de un objeto.
En las dos ltim as lneas el objeto recibe los m ensajes E ncenderO rdenador y
E stado. La respuesta a esos m ensajes es la ejecucin de los m todos respecti
vos, que fueron explicados anteriorm ente. A qu tam bin se puede observar
que para acceder a los m todos del objeto se utiliza el operador punto.
nom bre_objeto, n o m b r e jn ie m b ro
El o r d e n a d o r s e ha e n c e n d i d o .
E s t a d o del o rd e n a d o r :
M ar c a A s t
P ro c e s a d o r I n t e l Pentium
P a n t a l l a TFT
Otra form a de crear objetos de una clase y trabajar con ellos es incluir esa cla
se en el m ism o fichero fuente de una clase aplicacin, entendiendo por clase apli
cacin una que incluya el m todo m a in y cree objetos de otras clases. Por
ejem plo, volvam os al instante ju sto antes de aadir el m todo m a in a la clase
C O rdenador y aadam os una nueva clase pblica denom inada C M iO rdenador
que incluya el m todo m a in . El resultado tendr el esqueleto que se observa a
continuacin:
CA PTU LO 2: PR O G R A M A C I N O R IEN TA D A A O BJETO S 3 1
class COrdenador
I
// ...
I
En el captulo anterior aprendim os que una aplicacin est basada en una cla
se cuyo nom bre debe coincidir con el del program a fuente que la contenga, res
petando m aysculas y m insculas. Por lo tanto, guardem os el cdigo escrito en un
fichero fuente denom inado C M iO rdenador.java. F inalm ente, com pletam os el c
digo com o se observa a continuacin, y com pilam os y ejecutam os la aplicacin.
A hora es la clase C M iO rdenador la que crea un objeto de la clase C Ordenador.
El resto del proceso se desarrolla com o se explic en la versin anterior. Lgica
m ente, los resultados que se obtengan sern los m ism os que obtuvim os con la ver
sin anterior.
p u b l i c c l a s s CMiOrdenador
1
p u b l i c s t a t i c v o i d main (StringH args)
C O r d e n a d o r M i O r d e n a d o r = new C O r d e n a d o r ( ) ;
MiOrdenador.Marca = " A s t " ;
M iO rdenador.Procesador = " I n t e l Pentium";
M iO rde na do r. P a n t a l1a = "TFT ;
M i O r d e n a d o r . E n c e n d e r O r d e n a d o r t );
M i O r d e n a d o r . E s t a d o ( ):
1
1
class COrdenador
I
S t r i n g Marca;
S t r in g Procesador;
Strin g Pantalla;
boolean OrdenadorEncendido:
boolean P r e s e n t a c i n ;
void EncenderOrdenadort)
{
if ( O r d e n a d o r E n c e n d i d o = = t r u e ) // s i e s t encendido...
S y s t e m . o u t . p r i n t l n ( " E l o rd e n a d o r ya e s t encendido."):
32 JA VA : C U R SO D E PROGRAM A CIN
voi d E s t a d o t )
I
S y s t e m . o u t . p r i n t l n t " \ n E s t a d o del o r d e n a d o r : " +
" \ n M a r c a + Marca +
"\nProcesador " + Procesador +
\ n P a n t a 11 a " + P a n t a l l a + " \ n " ) :
i f ( O r d e n a d o r E n c e n d i d o t r u e ) II s i el ordenador es t encendido...
S y s t e m . o u t . p r i n t l n t " E l o r d e n a d o r e s t e n c e n d i d o . ):
e l s e // s i n o e s t e n c e n d i d o . . .
S y s t e m . o u t . p r i n t l n C E l ordenador est apagado."):
Segn lo expuesto hasta ahora, en esta nueva versin tam bin tenem os un fi
chero, el que alm acena la aplicacin, que tiene el m ism o nom bre que la clase que
incluye el m todo m a in , que es por donde se em pezar a ejecutar la aplicacin.
CARACTERSTICAS DE LA POO
Las caractersticas fundam entales de la PO O son: abstraccin, encapsulam iento,
herencia y polim orfism o.
Abstraccin
Por m edio de la abstraccin conseguim os no detenernos en los detalles concretos
de las cosas que no interesen en cada m om ento, sino generalizar y centrarse en los
aspectos que perm itan tener una visin global del problem a. Por ejem plo, el estu
dio de un ordenador podem os realizarlo a nivel de funcionam iento d e sus circuitos
electrnicos, en trm inos de corriente, tensin, etc., o a nivel de transferencia e n
tre registros, centrndose as el estudio en el flujo de inform acin entre las unida
des que lo com ponen (m em oria, unidad aritm tica, unidad de control, registros.
CA PTU LO 2: PRO G R A M A CI N O R IEN TA D A A OBJETOS 3 3
etc.), sin im portam os el com portam iento de los circuitos electrnicos que com po
nen estas unidades.
Encapsulamiento
Esta caracterstica perm ite ver un objeto com o una caja negra en la que se ha in
troducido de alguna m anera toda la inform acin relacionada con dicho objeto.
Esto nos perm itir m anipular los objetos com o unidades bsicas, perm aneciendo
oculta su estructura interna.
Herencia
La herencia perm ite el acceso autom tico a la inform acin contenida en otras cla
ses. D e esta forma, la reutilizacin del cdigo est garantizada. C on la herencia
todas las clases estn clasificadas en una jerarqua estricta. C ada clase tiene su su-
perclase (la clase superior en la jerarqua), y cada clase puede tener una o m s
subclases (las clases inferiores en la jerarqua).
j j
C la s e C la s e
C O rd e n a d o rS o b re m e s a C O rd e n a d o rP o rt til
Las clases que estn en la p aite inferior en la jerarqua se dice que heredan de
las clases que estn en la parte superior en la jerarqua.
El trm ino heredar significa que las subclases disponen de todos los m todos
y propiedades de su superclase. Este m ecanism o proporciona una form a rpida y
cm oda de extender la funcionalidad de una clase.
En Jav a cada clase slo puede tener una superclase, lo que se denom ina he
rencia sim ple. En otros lenguajes orientados a objetos, com o C++, las clases pue-
34 JA V A: CU R SO DE PROGRAM A CIN
U na interfaz es una coleccin de nom bres de m todos, sin incluir sus defini
ciones, q ue puede ser aadida a cualquier clase para proporcionarla com porta
m ientos adicionales no incluidos en los m todos propios o heredados.
Polimorfismo
Esta caracterstica perm ite im plem entar m ltiples form as de un m ism o m todo,
dependiendo cada una de ellas de la clase sobre la que se realice la im plem enta-
cin. Esto hace que se pueda acceder a una variedad de m todos distintos (todos
con el m ism o nom bre) utilizando exactam ente el m ism o m edio de acceso. M s
adelante, cuando estudie en profundidad las clases y subclases, estar en condi
ciones de entender con claridad la utilidad de esta caracterstica.
CONSTRUCTORES Y DESTRUCTORES
U n constructor es un procedim iento especial de una clase que es llam ado auto
m ticam ente siem pre que se crea un objeto de esa clase. Su funcin es iniciar el
objeto.
EJERCICIOS RESUELTOS
Para practicar con una aplicacin m s, escriba el siguiente ejem plo y pruebe los
resultados. H galo prim ero desde la lnea d e rdenes y despus con el entorno de
desarrollo integrado preferido por usted. El siguiente ejem plo m uestra una clase
para representar nm eros racionales. E sta clase puede ser til porque m uchos n
m eros no pueden ser representados exactam ente utilizando un nm ero fracciona
rio. Por ejem plo, el nm ero racional 1/3 representado com o un nm ero
CA PTU LO 2: PRO G R A M A CI N O R IEN TA D A A O BJETO S 3 5
Edicin
Abra el procesador de textos o el editor de su entorno integrado y edite la aplica
cin propuesta, com o se m uestra a continuacin:
class CRacional
I
int Numerador:
int Denominador:
void V i s u a l i z a r R a c i o n a l ()
I
S y s t e m . o u t . p r i n t l n ( N u m e r a d o r + " / " + Denominador):
I
rl.A s ig n a rD a t o s ( 2 , 5);
rl.V i suali z a rR a c io n a lO ;
CRacional r l = new C R a c i o n a l O :
r l .A s i g n a r D a t o s t 2 . 5 ) :
r l . V i s u a l i z a r R a c i o n a l ( );
EJERCICIOS PROPUESTOS
1. Aada a la aplicacin C O rdenador.java el m todo A pagarO rdenador.
2. Disee una clase C Coche que represente coches. Incluya los atributos m a rca ,
m odelo y co lo r; y los m todos que sim ulen, enviando m ensajes, las acciones de
arrancar el m otor, cam biar de velocidad, acelerar, frenar y parar el motor.
CA PTU LO 3
F.JX'cbalos/RAMA
Los corchetes [] indican que la inform acin encerrada entre ellos es opcio
nal, y los puntos suspensivos que pueden aparecer m s elem entos de la m is
ma forma. Por ejem plo, la sintaxis para definir una constante es:
final static tipo idctel = c t e l [ . i dc te 2 = cte2]...;
CARACTERES DE JAVA
El com pilador Java trata las letras m aysculas y m insculas com o caracteres
diferentes. P or ejem plo los identificadores A o y ao son diferentes.
Espacios en blanco
Los espacios en blanco en exceso son ignorados por el com pilador. P or ejem
plo, el cdigo siguiente se com porta exactam ente igual que el anterior:
Secuencias de escape
C ualquier carcter de los anteriores puede tam bin ser representado p o r una se
cuencia de escape. U na secuencia de escape est form ada p o r el carcter \ seguido
de una letra o de una com binacin d e dgitos. Son utilizadas para acciones com o
nueva lnea, tabular y para hacer referencia a caracteres no im prim ibles.
S ecuencia A S C II D efinicin
TIPOS DE DATOS
R ecuerde las operaciones aritm ticas que realizaba el program a Aritm etica.java
que vim os en un captulo anterior. Por ejem plo, una de las operaciones que reali
zbam os era la sum a de dos valores:
Para que el com pilador Java reconozca esta operacin es necesario especificar
previam ente el tipo de cada uno de los operandos que intervienen en la m ism a, as
com o el tipo del resultado. Para ello, escribirem os una lnea co m o la siguiente:
La declaracin anterior le dice al com pilador Java que datol, dato2 y resulta
do son de tipo entero (int).
Los tipos de datos en Java se clasifican en: tipos prim itivos y tipos referen-
ciados.
Tipos primitivos
Hay ocho tipos prim itivos de datos que podem os clasificar en: tipos num ricos y
el tipo b o o lean . A su vez, los tipos num ricos se clasifican en tipos enteros y ti
pos reales.
C ada tipo prim itivo tiene un rango diferente de valores positivos y negativos,
excepto el b o o lean que slo tiene dos valores: tr u e y false. El tipo de datos que
se seleccione para declarar las variables de un determ inado program a depender
del rango y tipo de valores que vayan a alm acenar cada una de ellas y de si stos
son enteros o fraccionarios.
byte
byte b = 0 :
short
short i = 0. j = 0:
int
El tipo in t se utiliza para declarar datos enteros com prendidos entre -2 1 47483648
y +2147483647. Un valor in t se define com o un dato de 32 bits de longitud, in
dependientem ente de la plataform a en la que se ejecute el cdigo byte d e Java. El
siguiente ejem plo declara e inicia tres variables , b y c, de tipo int:
i n t a = 2000:
i n t b = -30;
int c = 0xF003; / * v a l o r en h e x a d e c i m a l */
long
El tipo long se utiliza para declarar datos enteros com prendidos entre los valores
-9223372036854775808 y + 9223372036854775807. Un valor long se define
como un dato de 64 bits de longitud, independientem ente de la plataform a en la
que se ejecute el cdigo byte de Java. El siguiente ejem plo declara e inicia las va
riables a, b y c, de tipo long:
long c = 0xlF00230F; /* v a lo r en h e x a d e c i m a l */
char
c h a r c a r = 0;
Un carcter es representado internam ente por un entero, que puede ser expre
sado en decim al, hexadecim al u octal, com o verem os m s adelante.
float
El tipo flo a t se utiliza para declarar un dato en com a flotante de 32 bits en el for
m ato IE EE 754 (este form ato utiliza 1 bit para el signo, 8 bits para el exponente y
24 para la m antisa). Los datos de tipo flo a t alm acenan valores con una precisin
aproxim ada de 7 dgitos. Para especificar que una constante (un literal) es de tipo
float, hay que aadir al final de su valor la letra T o F \ El siguiente ejem plo d e
clara las variables a , b y c , de tipo real de precisin sim ple:
f l o a t a = 3.14159F;
f l o a t b = 2 . 2 e - 5 F : /* 2 . 2 e - 5 = 2 . 2 p o r 10 e l e v a d o a 5 * /
f l o a t c = 2 / 3 F : 7* 0.6666667 */
C A P T U L O 3: ELEM EN TO S DEL L EN G U A JE 4 3
double
boolean
Tipos referenciados
Hay tres clases de tipos referenciados: clases, interfaces y arrays. T odos ellos se
rn objeto de estudio en captulos posteriores.
LITERALES
Un literal es la expresin de un valor de un tipo prim itivo, de un tipo S trin g
(cadena de caracteres) o la expresin n u il (valor nulo o desconocido). P or ejem
plo, son literales: 5, 3.14, a , "h o la " y nuil. En realidad son valores constantes.
Literales enteros
El lenguaje Java perm ite especificar un literal entero en base 10, 8 y 16.
I [ + ] |-1 1i t e r a l _ e n t e r o [ 1 1 | L I ]
U n literal entero decim al puede tener uno o m s dgitos del 0 a 9, de los cua
les el prim ero de ellos es distinto de 0. Por ejem plo:
Un literal entero octal puede tener uno o m s dgitos del 0 a 7, precedidos por
0 (cero). Por ejem plo:
Literales reales
Un literal real est form ado p o r una p a rte entera, seguido p o r un pu n to decim al, y
una p a rte fra ccionaria. Tam bin se perm ite la notacin cientfica, en cuyo caso se
aade al valor una e o E, seguida p o r un exponente positivo o negativo.
I [ + ] | - l p a r t e - e n t e r a . p a r t e - f r a c c i o n a r ial I e | E ] I [ + ] | - l e xp on e n t e ]
17.24
17.244283
.008e3
27E-3
Tam bin se pueden utilizar los sufijos d o O para especificar explcitam ente
que se trata de una constante de tipo d o u b le . P or ejem plo:
e s p a c i o en b l a n c o
x ' le tra minscula x
\n ' r e t o r n o de c a r r o ms a v a n c e d e linea
' \u0007' pitido
'\u 0 0 1 B' c a r c t e r A S C I I Esc
E s t o e s una c o n s t a n t e d e c a r a c t e r e s "
"3.1415926"
P a s e o de P e r e d a 10. S a n t a n d e r "
/ * cadena v a c i a */
"Lenguaje V ' J a v a V " ' /* produce: Lenguaje "Java" */
46 JA V A: C U R SO D E PROGRAM A CIN
En el ejem plo siguiente el carcter Vz fuerza a que la cadena "O p u lse Entrar"
se escriba en una nueva lnea:
System.out.p rin tln ("D ista n cia : " + distancia + " Km.");
IDENTIFICADORES
Los identificadores son nom bres dados a tipos, literales, variables, clases, interfa
ces, m todos, paquetes y sentencias de un program a. L a sintaxis para form ar un
identificador es la siguiente:
I l e t r a \ _ \ $ I [ I l e t r a \ d 1 g i t o \ _ \ 11 ] . . .
Las letras pueden ser m aysculas o m insculas. Para Java una letra m ays
cula es un carcter diferente a esa m ism a letra en m inscula. Por ejem plo, los
identificadores Sum a, sum a y S UMA son diferentes.
Suma
Clculo_Nmeros_Prirnos
ordenar
Vi s u a l i z a r D a t o s
C A PTU LO 3: ELEM EN TO S D E L L EN G U A JE 4 7
PALABRAS CLAVE
Las palabras clave son identificadores predefinidos que tienen un significado es
pecial para el com pilador Java. Por lo tanto, un identificador definido por el usua
rio, no puede tener el m ism o nom bre que una palabra clave. El lenguaje Java,
tiene las siguientes palabras clave:
Las palabras clave deben escribirse siem pre en m insculas, com o estn.
COMENTARIOS
Un com entario es un m ensaje a cualquiera que lea el cdigo fuente. A adiendo
com entarios se hace m s fcil la com prensin de un program a. La finalidad de los
com entarios es explicar el cdigo fuente. Java soporta tres tipos de com entarios:
/*
* La e j e c u c i n d e l p r o g r a m a c o m i e n z a c o n e l m t od o m a n O .
* La l l a m a d a a l c o n s t r u c t o r de l a c l a s e no t i e n e l u g a r a menos
* q u e s e c r e e un o b j e t o d e l t i p o " CE 1e m e n t o s J a v a '
* en el m t o d o m a i n ( ).
*/
C om entario d e una sola lnea. E ste tipo de com entario com ienza con una do
ble barra (//) y se extiende hasta el final de la lnea. P or ejem plo:
// A g r e g a r aqu el c d i g o de i n i c i a c i n
Com entario de docum entacin. Este tipo de com entario com ienza con /** y
term ina con */. Son com entarios especiales que ja va d o c utiliza para generar la
48 JA V A: CU R SO DE PROGRAM A CIN
docum entacin acerca del program a, aunque tam bin se pueden em plear de
m anera idntica a los com entarios tradicionales.
/* *
* P u n t o de e n t r a d a principal para la aplicacin.
*
* Parmetros:
* a r g s : M a t r i z de p a r m e t r o s p a s a d o s a l a a p l i c a c i n
* a t r a v s de la l i n e a de r d e n e s .
*/
class CElementosJava
!
final static i n t c t e l - 1:
final static S tr in g cte2 = " P u l s e un a t e c l a para continuar":
void T e s t ( )
1
final double cte3 - 3.1415926:
// ...
I
II...
I
cte3 - 3.14;
En el ejem plo siguiente se declaran tres variables de tipo short, una variable
de tipo int. y dos variables de tipo S trin g :
class CE1ementosava
I
short da. mes . ao;
void T e s t ()
I
1n t c o n t a d o r - 0;
S t r i n g Nombre = Apellidos -
d1 a = 20:
Apellidos = "Ceballos";
II...
I
II ...
50 JA VA : CU R SO D E PROGRAM ACIN
El tipo, prim itivo o referenciado, determ ina los valores que puede tom ar la
variable as com o las operaciones que con ella pueden realizarse. Los operadores
sern expuestos un poco m s adelante.
En cam bio, las variables contador, N om bre y A pellidos han sido declaradas
en el bloque de cdigo correspondiente al cuerpo del m todo Test. Por lo tanto,
aplicando la definicin anterior, slo sern accesibles en este bloque. En este caso
se dice que dichas variables son locales al bloque donde han sido declaradas. Una
variable local se crea cuando se ejecuta el bloque donde se declara y se destruye
cuando finaliza la ejecucin de dicho bloque; dicho de otra form a, una variable
local se destruye cuando el flujo de ejecucin sale fuera del m bito de la variable.
U na variable local no puede ser declarada static.
class CE1ementosJava
short vari;
void T e s t ( )
1
in t var2;
System .out.p rintln(var2); II e r r o r : v a r i a b l e n o i n i c i a d a
S y s t e m . o u t . p r i n t l n ( v a r i ); // c o r r e c t o : v a r i e s i g u a l a 0
CA PTU LO 3: ELEM EN TO S DEL LENGUAJE 5 1
EXPRESIONES NUMRICAS
Una expresin es un conjunto de operandos unidos m ediante operadores para es
pecificar una operacin determ inada. T odas las expresiones cuando se evalan
retornan un valor. P o r ejem plo:
a + 1
suma + c
cantidad * p re cio
7 * M ath.sqrt(a) - b / 2 (sqrt indica raz cuadrada)
// C o n v e r s i n i m p l c i t a
b y t e b D a t o = 1; s h o r t s D a t o = 0 : i n t i D a t o = 0; long I D a t o = 0:
f l o a t f D a t o = 0 : d o u b l e d D a t o = 0:
sDato = bDato:
iDato = sDato;
IDato = iDato:
fDato = 1D a t o :
dDato = f D a t o + I D a t o - i D a t o * s D a t o / bDato;
S y s t e m . o u t . p r i n t l n ( d D a t o ) : // r e s u l t a d o : 1 . 0
Java perm ite una conversin explcita (conversin forzada) del tipo de una
expresin m ediante una construccin denom inada cast, que tiene la forma:
(tipo) expresin
C ualquier valor de un tipo entero o real puede ser convertido a o desde cual
quier tipo num rico. N o se pueden realizar conversiones entre los tipos enteros o
reales y el tipo boolean. P or ejem plo:
52 JA VA : C U R S O DE PROG RAM A CIN
// C o n v e r s i n e x p l c i t a ( c a s t )
b y t e b D a t o - 0: s h o r t s D a t o - 0: i n t i D a t o = 0: long I D a t o = 0:
f l o a t f D a t o = 0; d o u b l e d O a t o - 2:
f D a t o - ( f 1o a t I d D a t o :
1D a t o - ( 1 o n g ) f D a t o ;
i D a t o - ( i n t )1 D a t o :
sDato - ( s h o rt) iD a to :
bDato - ( b y t e M s D a t o + i D a t o - I D a t o * fD a t o / dDato):
S y s t e m . o u t . p r i n t l n ( b D a t o ) : // r e s u l t a d o : 2
f l o a t r:
r = <f l o a t ) M a t h . s q r t ( 10): // el r e s u l t a d o s e r e d o n d e a p e r d i e n d o
// p r e c i s i n y a que s q r t d e v u e l v e un
// v a l o r d e t i p o d o u b l e
OPERADORES
Los operadores son sm bolos que indican cm o son m anipulados los datos. Se
pueden clasificar en los siguientes grupos: aritm ticos, relacinales, lgicos, uni
tarios, a nivel de bits, de asignacin y operador condicional.
Operadores aritmticos
Los operadores aritm ticos los utilizam os para realizar operaciones m atem ticas y
son los siguientes:
O p erad or O p e ra c i n
+ Sum a. Los operandos pueden ser enteros o reales.
- Resta. Los operandos pueden ser enteros o reales.
* M ultiplicacin. Los operandos pueden ser enteros o reales.
/ D ivisin. Los operandos pueden ser enteros o reales. Si am bos ope
randos son enteros el resultado es entero. En el resto de los casos el
resultado es real.
% M dulo o resto de una divisin entera. L os operandos tienen que
ser enteros.
C A PTU LO 3: ELEM EN TO S D E L LEN G U A JE 5 3
1nt a - 10. b - 3.
float x = 2.0F. y;
y - x + a // El r e s u l t a d o e s 1 2 . 0 de U p o f l o a t
c - a / b // El r e s u l t a d o e s 3 de t i p o i n t
c = a X b // El r e s u l t a d o e s 1 de t i p o i n t
y = a / b // El r e s u l t a d o e s 3 de t i p o i n t . Se
// convierte a f l o a t para a s i g n a r l o a y
c <i n t ) ( x / y); // El r e s u l t a d o e s 0 . 6 6 6 6 6 6 7 de t i p o f l o a t . Se
// convierte a i n t p a r a a s i g n a r l o a c ( c = 0)
C uando en una operacin aritm tica los operandos son de diferentes tipos,
am bos son convertidos al tipo del operando de precisin m s alta. P or ejem plo,
para realizar la sum a x+a el valor del entero a es convertido a float, tipo de x. No
se m odifica a. sino que su valor es convertido a float slo para realizar la suma.
Los tipos sh o rt y byte son convertidos de m anera autom tica a int.
Operadores de relacin
Los operadores de relacin o de com paracin perm iten evaluar la igualdad y la
m agnitud. El resultado de una operacin de relacin es un valor booleano true o
false. Los operadores de relacin son los siguientes:
O p erad or O p e ra c i n ___________________________________________________
Los operandos tiene que ser de un tipo prim itivo. Por ejem plo:
i n t x = 10. y = 0:
b o o l e a n r;
r = x = y : // r = false
r = x > y: // r = true
r = x != y : // r = true
Operadores lgicos
El resultado de una operacin lgica (A N D , OR, X O R y N O T) es un valor boo-
leano verdadero o falso (tru e o false). Las expresiones que dan com o resultado
valores booleanos (vanse los operadores de relacin) pueden com binarse para
form ar expresiones booleanas utilizando los operadores lgicos indicados a con
tinuacin. Los operandos deben ser expresiones que den un resultado boolean.
O p erad or O p e ra c i n ___________________________________________________
&& o & A N D . D a com o resultado true si al evaluar cada uno de los operan-
dos el resultado es true. Si uno de ellos es false, el resultado es fal
se. Si se utiliza && (no & ) y el prim er operando es false, el
segundo operando no es evaluado.
II o I OR. El resultado es false si al evaluar cada uno de los operandos el
resultado es false. Si uno de ellos es true, el resultado es true. Si se
utiliza II (no I) y el prim er operando es true, el segundo operando
no es evaluado (el carcter I es el A S C II 124).
! N O T. El resultado de aplicar este operador es false si al evaluar su
operando el resultado es true, y true en caso contrario.
A XO R. D a com o resultado true si al evaluar cada uno de los operan-
dos el resultado de uno es true y el del otro false; en otro caso el
resultado es false.
i n t p = 10, q = 0:
boolean r:
r = p != 0 && q ! = 0: // r = f a l s e
C A PTU LO 3: ELEM EN TO S DEL LEN G U A JE 5 5
r = p ! = 0 | | q > 0 : // r - true
r - q < p && p o 10: II r - true
r !i": //si r = true. entonces r = false
Operadores unitarios
Los operadores unitarios se aplican a un solo operando y son los siguientes: !,
++ y . El operador ! ya lo hem os visto y los operadores ++ y los vere
m os m s adelante.
O p erad or O p e ra c i n _______________________________________________
C om plem ento a 1 (cam biar ceros por unos y unos por ceros). El ca
rcter ~ es el A SC II 126. El operando debe de ser de un tipo prim i
tivo entero.
C am bia de signo al operando (esto es, se calcula el com plem ento a
dos que es el com plem ente a 1 m s 1). El operando puede ser de un
_____________ tipo prim itivo entero o real.
int a = 2, b = 0. c = 0:
c = - a; // r e s u l t a d o c = -2
c = ~b: // r e s u l t a d o c = -1
O p erad or O p e ra c i n
& O peracin A N D a nivel de bits.
1 O peracin OR a nivel de bits (carcter A SCII 124).
A
O peracin X O R a nivel de bits.
D esplazam iento a la izquierda rellenando con ceros por la derecha.
D esplazam iento a la derecha rellenando con el bit de signo por la
izquierda.
> D esplazam iento a la derecha rellenando con ceros p o r la izquierda.
Operadores de asignacin
El resultado de una operacin de asignacin es el valor alm acenado en el operan
do izquierdo, lgicam ente despus de que la asignacin se ha realizado. El valor
que se asigna es convertido im plcita o explcitam ente al tipo del operando de la
izquierda (vase el apartado C onversin entre tipos de datos"). Incluim os aqu
los operadores de increm ento y decrem ento porque im plcitam ente estos operado
res realizan una asignacin sobre su operando.
O p erad or O p e ra c i n
++ Increm ento.
D ecrem ento.
= A signacin simple.
*= M ultiplicacin m s asignacin.
/= D ivisin m s asignacin.
%= M dulo m s asignacin.
+= Sum a m s asignacin.
-= R esta m s asignacin.
= D esplazam iento a izquierdas m s asignacin.
= D esplazam iento a derechas m s asignacin.
> D esplazam iento a derechas m s asignacin rellenando con ceros.
&= O peracin A N D sobre bits m s asignacin.
1= O peracin OR sobre bits m s asignacin.
A_ O peracin X O R sobre bits m s asignacin.
Los operandos tienen que ser de un tipo prim itivo. A continuacin se m ues
tran algunos ejem plos con estos operadores.
i n t x = 0, n= 1 0 . i = l :
n++: // I n c r e m e n t a e l v a l o r de n en 1.
CA PITU LO 3: ELEM ENTOS DEL L EN G U A JE 5 7
++n; / i n c r e m e n t a e l v a l o r de n en 1.
x - + +n : / I n c r e m e n t a n en 1 y a s i g n a e l r e s u l t a d o a x .
x = n++; / A s i g n a e l v a l o r de n a x y despus
/ i n c r e m e n t a n en 1.
i + = 2: / R e a l i z a la o p e r a c i n i = i + 2.
x * = n - 3: / R ea liz a la operacin x = x * ( n - 3 ) y no
/ x = x * n - 3.
n > > = 1; / R e a l i z a l a o p e r a c i n n = n >> 1 l a c u a l d e s p l a z a
/ el c o n t e n i d o de n 1 b i t a l a d e r e c h a .
Operador condicional
El operador condicional (?;), llam ado tam bin operador ternario, se utiliza en ex
presiones condicionales, que tienen la form a siguiente:
Lina expresin entre parntesis, siem pre se evala prim ero. Los parntesis tie
nen m ayor prioridad y son evaluados de m s internos a m s externos.
O p erad or A so c ia tiv id a d
O [] . izquierda a derecha
----- ! + + derecha a izquierda
new ( t i p o ) e x p r e s i n derecha a izquierda
* / X izquierda a derecha
+ - izquierda a derecha
<< > izquierda a derecha
< < = > > = instanceof izquierda a derecha
== != izquierda a derecha
& izquierda a derecha
A
izquierda a derecha
izquierda a derecha
n izquierda a derecha
II izquierda a derecha
? ; derecha a izquierda
= *= /= %= + = <<= = >= &= |= * derecha a izquierda
En Java, todos los operadores binarios excepto los de asignacin son evalua
dos de izquierda a derecha. En el siguiente ejem plo, prim ero se asigna z a y y a
continuacin y a x.
i n t x = 0 . y = 0, z = 15;
x = y = z; // r e s u l t a d o x = y = z - 15
EJERCICIOS RESUELTOS
La siguiente aplicacin utiliza objetos de una clase C E cuacion para evaluar ecua
ciones de la forma:
a x i + bx 2 +cx + d
CA PITU LO 3: ELEMENTOS D E L LEN G U A JE 5 9
El m todo Ecuacin sim plem ente asignar los valores pasados com o argu
m entos a los atributos representativos de los coeficientes de la ecuacin.
p u b lic double V a l o r P a r a ( d o u b l e x)
1
double re su lta d o :
// Real i z a r c l c u l o s
return resultado: < Valor devuelto por
el mtodo
class CEcuacion
1
II El t r m i n o de m a y o r g r a d o t i e n e e x p o n e n t e 3 f i j o
d o u b l e c 3 . c 2 . e l . cO: // c o e f i c i e n t e s
p u b l i c v o i d E c u a c i n t d o u b l e a. d o u b l e b. d o u b l e c . d o u b l e d )
I
c 3 - a ; c 2 = b; el - c ; cO=d;
60 JA V A: C U R S O DE PROGRAM A CIN
p u b lic double V a l o r P a r a ( d o u b l e x)
I
double r e s u l t a d o ;
r e s u l t a d o = c 3 * x * x * x + c 2 * x * x + c l * x + cO:
r e t u r n r e s u l t a d o ; // d e v o l v e r e l v a l o r c a l c u l a d o
double r = e c l . V a l o r P a r a ( l ) ;
S y s t e m . o u t . p r i n t l n ( r );
r = e c l .ValorP ara(1.5):
System .out.pri n t l n ( r ) ;
EJERCICIOS PROPUESTOS
1. Escriba una aplicacin que visualice en el m onitor los siguientes m ensajes:
B i e n v e n i d o a l mundo de J a v a .
P o d r s d a r s o l u c i n a much o s problemas.
CA PTU LO 3: ELEM EN TO S DEL LENGUAJE 6 1
i n t a - 10, b = 3 , c = 1 , d , e :
f l o a t x. y :
x - a / b;
c = a < b && c ;
d - a + b++;
e - + + a - b;
y = ( f l o a t ) a / b:
3. Escriba las sentencias necesarias para evaluar la siguiente ecuacin para valores
de a = 5 , b = -1.7, c = 2 y x = 10.5.
a x3+ bx2 - e x + 3
5. Decida qu tipos de datos necesita para escribir un program a que calcule la suma
y la m edia de cuatro nm eros de tipo int.
b 2 -A o c
2a
para valores d e a = l , b = 5 y c = 2.
CA PTU LO 4
ESTRUCTURA DE UN PROGRAMA
En este captulo estudiar cm o es la estructura de una program a Java. Partiendo
de un program a ejem plo sencillo analizarem os cada una de las partes que com po
nen su estructura, as tendr un m odelo para realizar sus propios program as. T am
bin verem os cm o se construye un program a a partir de varios m dulos de clase.
Por ltim o, estudiarem os los conceptos de m bito y accesibilidad de las variables.
T oda aplicacin Java est form ada por al m enos una clase que define un m
todo nom brado m a in , com o se m uestra a continuacin:
public c la s s CMiApi i c a c i o n
I
public static void main( S t r i n g f ] a rg s)
I
// e s c r i b a aqui el c d i g o que q u i e r e e j e c u t a r
I
I
30 C -22.00 F
-24 C -11.20 F
90 C 194.00 F
96 C 204.80 F
La relacin entre los grados centgrados y los grados fa h ren h eit viene dada
por la expresin grados fa h ren h eit = 9/5 * grados centgrados + 32. L os clculos
los vam os a realizar para un intervalo de - 3 0 a 100 grados centgrados con incre
m entos de 6.
class CGrados
I
prvate f lo a t gradosC; // g r a d o s centgrados
C entgradosA signar que perm ite asignar a un objeto un valor en grados cent
grados.
F ahrenheitO btener que perm ite retornar el valor grados fa h ren h eit equiva
lente a g ra d o sC grados centgrados.
C entgradosO btener que perm ite retornar el valor alm acenado en el atributo
gradosC .
Sin casi dam o s cuenta estam os abstrayendo (separando por m edio de una
operacin intelectual) los elem entos naturales que intervienen en el problem a a
resolver y construyendo objetos que los representan.
R ecordando lo visto anteriorm ente, una aplicacin Java tiene que tener un
objeto aplicacin, que aporte un m todo m a in , por donde em pezar y term inar la
ejecucin de la aplicacin, adem s de otros que consideram os necesarios. Cm o
podem os im aginar esto de una form a grfica? La figura siguiente da respuesta a
esta pregunta:
mensajes/respuestas
CentgradosAsi gnar
FahrenheitObtener
public c la ss CApGrados
[
// D e f i n i c i n de c o n s t a n t e s
final sta t ic int lim ln fe rio r - -30;
final s t a t i c i n t l i m S u p e r i o r = 10 0 :
final s t a t i c i n t i n c r e m e n t o = 6:
// A s i g n a r a l o b j e t o g r a d o s e l v a l o r en g r a d o s c e n t g r a d o s
g r a d o s . C e n t g r a d o s A s i g n a r ( g r a d o s C e n t ):
// O b t e n e r d e l o b j e t o g r a d o s l o s g r a d o s
gradosFahr = g r a d o s .FahrenheitObtener
// E s c r i b i r l a s i g u i e n t e l i n e a d e l a t a b l a
S y s t e m . o u t . p r i n t l n ( g r a d o s C e n t + C" + " \ t + gradosFahr + F " );
// S i g u i e n t e v a l o r
gradosCent += incremento:
Seguro que pensar que todo el proceso se podra haber hecho utilizando so
lam ente el objeto aplicacin, escribiendo todo el cdigo en el m todo m ain. lo
cual es cierto. Pero, lo que se pretende es q ue pueda ver de una form a clara que,
en general, un program a Java es un conjunto de objetos que se com unican entre s
m ediante m ensajes con el fin de obtener el resultado perseguido, y que la solucin
del problem a puede resultar m s sencilla cuando consiga realizar una representa
cin del problem a en base a los objetos naturales que se deducen de su enunciado.
Piense que en la realidad se enfrentar a problem as m ucho m s com plejos y, por
lo tanto, la descom posicin en objetos ser vital para resolverlos.
En el ejem plo realizado podem os observar que una aplicacin Java consta de:
Sabem os tam bin que una clase encapsula los atributos de los objetos que
describe y los m todos para m anipularlos. Pues bien, cada m todo consta de:
Los apartados que se exponen a continuacin explican brevem ente cada uno
de estos com ponentes que aparecen en la estructura de un program a Java.
ja va
J
lang
j applet
J predeterm inado
J
IO nel
J o tros paquetes
J
1 ... )
awt
J
El nivel superior se denom ina ja v a. En el siguiente nivel tenem os paquetes
com o lang. applet o io.
Por om isin una clase tiene el nivel de proteccin de paquete ; p o r ejem plo, la
clase CGrados del ejem plo anterior tiene este nivel de proteccin. En cam bio,
cuando se desea que una clase tenga proteccin pblica, hay que calificarla como
tal utilizando la palabra reservada public; la clase CApGrados del ejem plo ante
rior tiene este nivel de proteccin. O tro ejem plo: echando un vistazo a la docu
CA PTU LO 4: ESTRU C TU R A DE UN PRO G R A M A 6 9
m entacin de Java, se puede observar que la clase S y ste m del paquete ja v a .la n g
es pblica, razn por la cual se ha podido utilizar en la aplicacin C ApG rados.
Sentencia import
Una clase de un determ inado paquete puede hacer uso de otra clase de otro pa
quete de dos formas:
1. U tilizando su nom bre com pleto en todas las partes del cdigo donde haya que
referirse a ella. Por ejem plo:
j a v a . l a n g . S y s t e m . o u t . p r i n t l n ( g r a d o s F a h r );
System.out.println(gradosFahr);
C om o se puede com probar en el ejem plo anterior, im portar una clase perm ite
al program a referirse a ella m s tarde sin utilizar el nom bre del paquete. Esto es,
la sentencia im p o rt slo indica al com pilador e intrprete de Java dnde encontrar
las clases, no trae nada dentro del program a Java actual.
En el caso concreto del ejem plo expuesto, si elim inam os la sentencia im p ort,
todo seguir funcionando igual. Esto es as porque las clases del paquete ja -
v a .la n g son im portadas de m anera autom tica para todos los program as, no suce
diendo lo m ism o con el resto de los paquetes, que tienen que ser im portados
explcitam ente.
70 JA V A : C U R SO DE PROGRAM A CIN
public c la ss CApGrados
I
11...
S y s t e m . o u t . p r i n t l n g r a d o s C e n t + " C + " \ t " + g r a d o s F a h r + F ):
II ...
I
Tam bin puede im portar un paquete com pleto de clases utilizando com o co
m odn un asterisco en lugar del nom bre especfico de una clase. P or ejem plo:
import j a v a . l a n g . * : II i m p o r t a r l a s c l a s e s p b l i c a s de e s t e paquete
// a l a s que s e r e f i e r a e l c d i g o
Definiciones y declaraciones
U na declaracin introduce uno o m s identificadores en un program a. U na decla
racin es una definicin, a m enos que no haya asignacin de m em oria.
T oda variable debe ser definida antes de ser utilizada. La definicin de una
variable, declara la variable y adem s le asigna m em oria:
in t gradosCent:
f lo a t gradosFahr:
gradosCent = lim l n f e r io r :
g r a d o s F a h r = 0:
in t gradosCent = lim l n f e r io r ;
f l o a t g r a d o s F a h r = 0:
class UnaClase
I
Nivel d e la c la se D e c l a r a c i n de v a r i a b l e s (atributos)
S e n t e r ic i as
Sentencia simple
Una sentencia sim ple es la unidad ejecutable m s pequea de un program a Java.
Las sentencias controlan el flujo u orden de ejecucin. U na sentencia Java puede
formarse a partir de: una palabra clave (for, while, if ... else, etc.), expresiones,
declaraciones o llam adas a m todos. C uando se escriba una sentencia hay que te
ner en cuenta las siguientes consideraciones:
T oda sentencia sim ple term ina con un punto y com a (;).
Dos o m s sentencias pueden aparecer sobre una m ism a lnea, separadas una
de otra por un punto y com a, aunque esta form a de proceder no es aconsejable
porque va en contra de la claridad que se necesita cuando se lee el cdigo de
un program a.
Una sentencia nula consta solam ente de un punto y com a. C uando veam os la
sentencia w hile, podr ver su utilizacin.
72 JA VA : C U R SO DE PRO G R A M A CI N
grados.CentlgradosAsi gnar(gradosCent):
g r a d o s F a h r = g r a d o s .F a h r e n h e i t O b t e n e r ( );
S y s t e m . o u t . p r i n t l n t g r a d o s C e n t + " C" + "\t" + g r a d o s F a h r + " F n );
g r a d o s C e n t + = inc re me nt o:
Mtodos
Un m todo es una coleccin de sentencias que ejecutan una tarea especfica. En
Java, un m todo siem pre pertenece a una clase y su definicin nunca puede con
tener a la definicin de otro m todo; esto es. Java no perm ite m todos anidados.
Definicin de un mtodo
[ modificador] t i p o - r e s u l t a d o n o m b r e - m t o d o ( . [ l i s t a d e p a r m e t r o s])
I
d e c l a r a d o r e s de v a r i a b l e s locales:
sentencias;
[ r e t u r n [ ( ] e x p r e s i n l) ] ] :
Las variables declaradas en el cuerpo del m todo son locales a dicho m todo
y por definicin solam ente son accesibles dentro del mismo.
r e t u r n [ ( ] expresin[ ) ] :
CA PTU LO 4: ESTRU C TU R A D E UN PROGRAM A 7 3
v o i d m Escri bi r ( )
I
// ...
return:
La lista de p a rm etros de un m todo son las variables que reciben los valores
de los argum entos especificados cuando se invoca al m ism o. C onsisten en una
lista de cero, uno o m s identificadores con sus tipos, separados por com as. A
continuacin se m uestra un ejem plo:
Mtodo main
T oda aplicacin Java tiene un m todo denom inado m ain, y slo uno. Este m todo
es el punto de entrada a la aplicacin y tam bin el punto de salida. Su definicin
es com o se m uestra a continuacin:
Sabem os que las clases son plantillas para crear objetos. Pero, cm o se crea un
objeto? Para crear un objeto de una clase hay que utilizar el operador new , anlo
gam ente a com o m uestra el ejem plo siguiente:
74 JA V A: C U R SO DE PROGRAM A CIN
C G r a d o s g r a d o s = new C G r a d o s O :
En este ejem plo se observa que para crear un objeto de la clase C Grados hay
que especificar a continuacin del operador new el nom bre de la clase del objeto
seguido de parntesis. P o r qu parntesis? Es acaso C G rados un m todo? As
es. M s adelante aprender que toda clase tiene al m enos un m todo predetermi
nado especial denom inado igual que ella, que es necesario invocar para crear un
objeto; ese m todo se denom ina constructor de la clase.
O tro ejem plo; ahora con una clase de la biblioteca Java. El paquete java.util
proporciona una clase denom inada G r e g o r ia n C a le n d a r . Un objeto de esta clase
representa una fecha, incluyendo tam bin opcionalm ente la hora. El siguiente c
digo crea tres objetos de esta clase,./7*/,/7?2 y fh 3 . iniciados, el prim ero con la fe
cha y hora actual por om isin, el segundo con la fecha especificada, y el tercero
con la fecha y hora especificadas:
G r e g o r i a n C a l e n d a r f h l = new G r e g o r i a n C a l e n d a r t );
G r e g o r i a n C a l e n d a r f h 2 = new G r e g o r l a n C a l e n d a r ( 2 0 0 1 . 1. 2 1 ) :
G r e g o r i a n C a l e n d a r f h 3 = new G r e g o r i a n C a l e n d a r ( 2 0 0 1 . 1, 2 1 , 12, 30, 15):
Las sentencias anteriores son vlidas porque, com o puede com probar si lo de
sea, la clase G r e g o r ia n C a le n d a r proporciona varias form as de construir un ob
jeto : sin utilizar parm etros, con tres parm etros (ao, m es y da), con seis
parm etros (ao, m es, da, hora, m inutos y segundos), etc.
C uando se crea un nuevo objeto utilizando new. Java asigna automticam ente
la cantidad de m em oria necesaria para ubicar ese objeto. Si no hubiera suficiente
espacio de m em oria disponible, el operador new lanzar una excepcin O u tO f-
M e m o r y E r r o r cuyo estudio posponem os. D espus de saber esto quizs se pre
gunte: Q uin libera esa m em oria y cundo lo hace? La respuesta es otra vez la
m isma: Java se encarga de hacerlo en cuanto el objeto no se utilice, cosa que ocu
rre cuando ya no exista ninguna referencia al objeto. Por ejem plo, en el cdigo
que se m uestra a continuacin, la m em oria asignada a los objetos f h l , f h 2 y fh3
ser liberada cuando finalice la ejecucin del m todo m ain.
import j a v a . u t i l .*:
p u b l i c c l a s s CFechaHora
1
public static void m a in ( S t r in g [ ] args)
I
Gr e g o r i an C a l e n d a r f h l = new G r e g o r i a n C a l e n d a r ):
Gr e g o r i an C a l e n d a r f h2 = new G r e g o r i a n C a l e n d a r t 2001, 1. 21):
Gr e g o r i an C a l e n d a r f h3 = new G r e g o r i an C a l e n d a r ( 20 0 1 . 1. 21. 12. 30, 15):
// .. .
CA PTU LO 4: E ST R U C TU R A D E UN PRO G R A M A 7 5
A hora basta con que sepa que Java cuenta con una herram ienta denom inada
recolector d e basura que busca objetos que no se utilizan con el fin de destruirlos
liberando la m em oria que ocupan. M s adelante aprender sobre este m ecanism o.
m i O b j e t o . a t r i buto:
mi O b j e t o . m e t o d o ( [ a r g u m e n t o s ] );
Lgicam ente, com o pueden existir varios objetos de la m ism a clase, es nece
sario especificar de quin es el m iem bro. Si el m iem bro es a su vez un objeto, la
sintaxis se extiende siguiendo la m ism a sintaxis: objeto.m broO bjeto.m iem bro.
R ecuerde que el operador punto (.) se evala de izquierda a derecha.
g r a d o s . C e n t g r a d o s A s i g n a r ( g r a d o s C e n t ):
Es im portante asim ilar que un program a orientado a objetos slo se com pone
de objetos que se com unican m ediante m ensajes. D esde este conocim iento, no
tiene sentido pensar que un m todo se pueda invocar aisladam ente, esto es, sin
que exista un objeto para el que es invocado. Por ejem plo, si en el m todo m a in
de nuestra aplicacin ejem plo pudiram os escribir:
76 JA VA : C U R SO DE PROGRAM A CIN
CentgradosAsignar(gradosCent);
class CGrados
I
prvate f lo a t gradosC; // g r a d o s centgrados
Un m iem bro de una clase declarado p rivado puede ser accedido nicam ente
p o r lo m todos de su clase. En el ejem plo anterior se puede observar que el atri
buto gradosC es privado y es accedido por el m todo C entgrados A sig n a r.
g r a d o s . g r a d o s C = 30:
el com pilador Java m ostrara un error indicando que el m iem bro gradosC no es
accesible desde esta clase, p o r tratarse de un m iem bro privado de CGrados.
Un atributo de la clase alm acena inform acin com n a todos los objetos de
esa clase. Se define agregndole previam ente la palabra reservada static. y existe
aunque no haya objetos definidos de la clase.
class COrdenador
I
S trin g Marca:
S t r in g Procesador;
Strin g Pantalla;
s t a t i c byte Garanta;
boolean O rdenadorEncendido:
boolean P re se nta c i n ;
// ...
En el ejem plo que se m uestra a continuacin se puede observar que para esta
blecer el valor del atributo privado G aranta se ha utilizado un m todo esttico. Si
CA PTU LO 4: ESTRU C TU R A D E UN PRO G R A M A 79
public c la ss CM iAplicacion
I
public static v o i d main (Stringf] args)
1
C O r d e n a d o r .E s t a b l e c e r G a r a n t 1 a ( <b y t e )3):
)
:
class COrdenador
I
private S t r i n g Marca;
private S t r in g Procesador;
private S t r i n g P a n t a l l a ; _________________________ _ _ _
private s t a t i c byte Garanta;
private boolean OrdenadorEncendido:
private boolean P re se nta c i n :
/ / ...
El m todo E stablecerG aranta del ejem plo anterior puede acceder a G aranta
porque es un m iem bro esttico pero no podra incluir, por ejem plo, una sentencia
com o M arca = " A s t porque M arca no es static.
A hora puede com prender por qu el m todo m a in es static: para que pueda
ser invocado aunque no exista un objeto de su clase. Por ejem plo, el m todo m a in
de la clase C M iA plicacion anterior, es invocado cuando se ejecuta la aplicacin,
independientem ente de que exista un objeto de esa clase.
Referencias a objetos
Segn lo q ue hem os aprendido hasta ahora, para crear un objeto de una clase hay
que hacerlo explcitam ente utilizando el operador new. Por ejem plo:
C G r a d o s g r a d o s = new C G r a d o s O :
El operador new devuelve una referencia al nuevo objeto, que se alm acena en
una variable del tipo del objeto. En el ejem plo anterior, la referencia devuelta por
80 JA VA : C U R SO DE PROGRAM A CIN
el op erad o r new es alm acenada en la variable grados del tipo C G rados. La clase
C G rados se encuadra dentro de lo que hem os denom inado tipos referenciados.
E s p a c io d e m e m o ria
g rad o s O b je to re fe re n c ia d o
elUIUIlUlcl ^
g ra d o s C = 3 0
class CRacional
I
prvate int Numerador:
prvate int Denominador:
rl.A s ig n a rD a t o s ( 3 . 7);
rl .V isu a liza rR a cio n a l(): // s e v i s u a l i z a 3/7
r2 . V i s u a l i z a r R a c i o n a l ( ) ; // s e v i s u a l i z a 3/7
C R a c io n a l r3;
r 2 = new C R a c i o n a l O : // c r e a r un o b j e t o C R a c i o n a l
r 2 . A s i g n a r D a t o s ( 2 . 5):
r 3 = C R a c i o n a l . S u m a r ( r 1. r 2 ) : // r 3 = 3 /7 + 2/5
r 3 . V i s u a l i z a r R a c i o n a l ( ) : // s e v i s u a l i z a 2 9 / 3 5
La clase C R acional encapsula una estructura d e datos form ada por dos en te
ros: num erador y denom inador; y para acceder a esta estructura proporciona la
interfaz pblica form ada p o r los m todos:
A signarD atos que perm ite establecer el num erador y el denom inador de un
nm ero racional.
V isualiza/R acional q ue perm ite visualizar un racional en form a de quebrado.
S u m a r que devuelve el nm ero racional resultante de sum ar otros dos pasados
com o argum entos.
r l a r2, sim plem ente se cre una nueva referencia al m ism o objeto referenciado
por r l . Por lo tanto, m odificar el objeto al que se refiere r l es m odificar el objeto
al que se refiere r2 porque r l y r2 referencian el m ism o objeto.
E s p a c io d e m e m o ria
O b je to re fe re n c ia d o
N u m e ra d o r
D e n o m in a d o r
r l - new C R a c i o n a l ( ) ; II c r e a r un o b j e t o C R a c i o n a l rl
r l . A s i g n a r D a t o s ( 3 , 7);
r 2 - new C R a c i o n a l O ; // c r e a r un o b j e t o C R a c i o n a l r2
r2 .A sig n a rD a to s(2 . 5):
E s p a cio d e m e m o ria
r1 r i
3 /7 2 /5
II...
CRa cio nal r3;
r 2 = new C R a c i o n a l O : // c r e a r un o b j e t o C R a c i o n a l
r2 .A sign a rD a to s(2 , 5);
C A PTU LO 4: ESTRU C TU R A D E UN PROGRAM A 8 3
r3 = CRacio na l . S u m a r t r l . r 2 ) ; // r 3 = 3 /7 + 2 /5
r 3 . V i s u a l i z a r R a c i o n a l ( ); // s e v i s u a l i z a 2 9 / 3 5
A nalicem os el m todo Sum ar. E ste m todo tiene dos parm etros de tipo C Ra
cional. D espus de que el m todo ha sido invocado desde m ain , a y b sealan a
los m ism os objetos que r l y r2. Esto significa que los objetos pasados a los par
m etros de un m todo son siem pre referencias a dichos objetos, lo cual significa
que cualquier m odificacin que se haga a esos objetos dentro del m todo afecta al
objeto original. En cam bio, las variables de un tipo prim itivo pasan por valor, lo
cual significa que se pasa una copia, p o r lo que cualquier m odificacin que se ha
ga a esas variables dentro del m todo no afecta a la variable original.
neralm ente se alm acena cada clase en un nico fichero para favorecer su m ante
nim iento y posterior reutilizacin.
public void V i s u a l i z a r R a c i o n a l ()
I
Sy ste m .o u t.p rin tln (N u m e ra d or + /" + Denominador):
I
r l = new C R a c i o n a l ( ) ; // c r e a r un o b j e t o C R a c i o n a l
rl .AsignarD atos(2. 5):
r2 = rl
r l .A s i g n a r D a t o s ( 3 . 7):
r l .Visual iz a r R a c io n a l(): / / s e vi s u a liz a 3/7
r2 . V i s u a l i z a r R a c i o n a l (): // s e v i s u a l i z a 3/7
C uando se com pile C Aplicacion, que por om isin pertenece al paquete pre
determ inado. puesto que necesita utilizar la clase C R acional, buscar tam bin sta
en el m ism o paquete, lo que supone buscar su fichero com pilado, o en su defecto
su fichero fuente, en el directorio actual de trabajo. Por lo tanto, antes de com pilar
la aplicacin asegrese de que el fichero C R acional.class o C Racional.java est
en el m ism o directorio que C Aplicacion.java.
ACCESIBILIDAD DE VARIABLES
A unque este tem a ya ha sido tratado, realizam os ahora un resum en. Se denom ina
m bito de una variable a la parte de un program a donde dicha variable puede ser
referenciada por su nom bre. U na variable puede ser lim itada a una clase, a un
m todo, o a un bloque de cdigo correspondiente a una sentencia com puesta.
class UnaClase
V a ria b le lim itada
a u n a cla se v a r i a b l e s m i e mb r o d e la c l a s e (atributos)
una s e n t e n c i a compuesta
V a ria b le lim itada
a un bloque Variables locales
86 JA VA : C U R SO DE PROGRAM A CIN
U na variable m iem bro de una clase puede ser declarada en cualquier sitio
dentro de la clase siem pre que sea fuera de todo m todo. La variable est disponi
ble para todo el cdigo de la clase.
En general, una variable local existe y tiene valor desde su punto de declara
cin hasta el final del bloque donde est definida. C ada vez que se ejecuta el blo
que que la contiene, la variable local es nuevam ente definida, y cuando finaliza la
ejecucin del m ism o, la variable local deja de existir. Un elem ento con carcter
local es accesible solam ente dentro del bloque al que pertenece.
EJERCICIOS RESUELTOS
Con los conocim ientos que hem os adquirido hasta ahora vam os a realizar una
aplicacin sencilla para sim ular una cuenta bancaria.
U na cuenta bancaria vista com o un objeto tiene, por una parte, atributos que
definen su estado, com o Tipo d e inters y Saldo, y p o r otra, operaciones que defi
nen su com portam iento, com o E stablecer tipo d e inters. Ingresar dinero. Retirar
dinero. Sa ld o a ctual o A b o n a r intereses.
ti poDelnters = t i ;
// O p e r a c i o n e s
S y s t e m . o u t .p r in t ln ( C u e n t a O l. S a ld o A c t u a l( )):
CuentaOl. In g r e sa r D i e r o (500000):
CuentaOl.Reti ra rD in e ro 200000):
System .out.println(CuentaO l.SaldoActual()):
C u e n t a O l . A b o n a r I n t e r e s e s * ):
System .out.println(CuentaO l.SaldoActual()):
El m todo IngresarD inero acum ula la cantidad pasada com o argum ento sobre
el saldo actual.
El m todo RetirarD inero verifica si hay suficiente dinero com o para poder
retirar la cantidad solicitada. En caso negativo lo notifica y term ina; en caso posi
tivo, resta del saldo la cantidad retirada.
EJERCICIOS PROPUESTOS
1. E scriba la aplicacin C ApG rados.java y com pruebe los resultados.
3. M odifique los lm ites inferior y superior de los grados centgrados, el increm ento,
y ejecute de nuevo la aplicacin.
5. R econstruya la aplicacin C ApG rados.java para que cada clase est alm acenada
en un fichero: la clase C G rados en el fichero C G rados.java y la clase C ApG rados
en el fichero C ApG rados.java.
CA PTU LO 5
F.J.Cebalos/RA-MA
En este captulo aprender cm o leer y escribir inform acin desde sus aplica
ciones, y a trabajar con las clases utilizadas m s frecuentem ente.
T anto los datos ledos com o los resultados obtenidos sern alm acenados en
variables pertenecientes a la estructura interna de uno o m s objetos o declaradas
en algn m todo. L os datos sern ledos a travs de los m todos proporcionados
por las clases de E/S y sern asignados a las variables directam ente por ellos, o
bien utilizando una sentencia de asignacin de la form a:
d = a + b * c: //el valor de a + b * c s e a s i g n a a d
a + b * c = d: //el v a l o r de d no s e p u e d e a s i g n a r a a + * c
L os datos num ricos sern alm acenados en variables de alguno de los tipos
prim itivos expuestos en el captulo 3. Por ejem plo:
S t r i n g cadena: // c a d e n a p e r m i t e r e f e r e n c i a r un o b j e t o S t r i n g
c a d e n a = " h o l a : // e q u i v a l e a: c a d e n a = new S t r i n g f " h o l a " );
C uando se asigna un valor a una variable estam os colocando ese valor en una
localizacin de m em oria asociada con esa variable.
i n t n v a r = 10; // v a r i a b l e de un t i p o p r i m i t i v o ( i n t )
String svar = "hola": // r e f e r e n c i a a un o b j e t o de t i p o S t r i n g
E s p a cio d e m e m o ria
n var
svar
10 h ola
CA PTU LO 5: CL A SES DE U SO C O M N 9 1
n v a r - 20;
svar = "a d i s";
E s p a cio d e m e m o ria
n var
svar
20 adis
ENTRADA Y SALIDA
F recuentem ente un program a necesitar obtener inform acin desde un origen o
enviar inform acin a un destino. Por ejem plo, obtener inform acin desde, o enviar
inform acin a: un fichero en el disco, la m em oria del ordenador, otro program a,
Internet, etc.
Flujo d e s d e el origen
O rig e n
P ro g ra m a
1
D e s tin o 1
Flujo h a c ia el d es tin o
1
Entonces, para que un program a pueda obtener inform acin desde un origen
tiene que ab rir un flujo y leer la inform acin. A nlogam ente, para que un progra
ma puede en v iar inform acin a un destino tiene que abrir un flujo y escribir la
inform acin.
Los algoritm os para leer y escribir datos son siem pre m s o m enos los mis
mos:
Leer E s c r ib ir
Abrir un flu jo desde un origen A brir un flu jo hacia un destino
M ientras haya informacin Mientras haya informacin
Leer informacin Escribir informacin
Cerrar el flu jo Cerrar el flujo
D ebido a que todas las clases relacionadas con flujos pertenecen al paquete
ja v a .io de la biblioteca estndar de Java, un program a que utilice flujos de E/S
tendr que im portar este paquete:
import j a v a . i o . * ;
Las clases del paquete ja v a .io estn divididas en dos grupos distintos, ambos
derivados de la clase O b je ct del paquete ja v a .la n g . segn se m uestra en la figura
siguiente. El grupo de la izquierda ha sido diseado para trabajar con datos de tipo
byte y el de la derecha con datos de tipo char. A m bos grupos presentan clases
anlogas que tienen interfaces casi idnticas, por lo que se utilizan de la misma
manera.
Las clases som breadas son clases abstractas. U na clase abstracta no permite
que se creen objetos de ella. Su m isin es proporcionar m iem bros com unes que
sern com partidos por todas sus subclases.
C A PTU LO 5: CLA SES DE USO COM N 9 3
Flujos de entrada
La clase In p u tS tre a m es una clase abstracta que es superclase de todas las clases
que representan un flujo en el que un destino lee bytes de un origen. C uando una
aplicacin define un flujo de entrada, la aplicacin es destino de ese flujo de
bytes, y es todo lo que se necesita saber.
La prim era versin de read sim plem ente lee bytes individuales de un flujo de
entrada; concretam ente lee el siguiente byte de datos disponible. D evuelve un en
tero (int) correspondiente al valor A S C I I del carcter ledo, al nm ero de bytes
ledos si se lee una m atriz, o bien -1 cuando en un intento de leer datos se alcanza
el final del flujo (esto es, no hay m s datos).
i n t n:
n = f 1u j o E . r e a c K ):
i n t n;
b y t e [ ] b = new b y t e [ 1 2 8 ] : // m a t r i z b ' de 1 28 b y t e s
n = flujoE.read(b); // n e s e l n m e r o de b y t e s ledos
La tercera versin del m todo read lee un m xim o de len bytes a partir de la
posicin o f f de un flujo de entrada y los alm acena en una m atriz b.
C ada uno de estos m todos ha sido escrito para que bloquee la ejecucin del
program a que los invoque hasta que toda la entrada solicitada est disponible.
Flujos de salida
La clase O u tp u tS tre a m es una clase abstracta que es superclase de todas las cla
ses que representan un flujo en el que un origen escribe bytes en un destino.
C uando una aplicacin define un flujo de salida, la aplicacin es origen de ese
flujo de bytes (es la q ue enva los bytes), y es todo lo que se necesita saber.
public v o i d w r i t e ( i n t b) t h r o w s I O E x c e p t i o n
public v o i d w r i t e ( b y t e [ ] b) t h r o w s I O E x c e p t i o n
public v o i d w r i t e ( b y t e [ ] b, i n t off, i n t len) t h r o w s IOException
La prim era versin de w rite sim plem ente escribe el byte especificado en un
flujo de salida. Puesto que su parm etro es de tipo int, lo que se escribe es el valor
correspondiente a los 8 bits m enos significativos, el resto son ignorados.
Por ejem plo, suponiendo que tenem os definido un objeto Jlu jo S (flujo de sali
da) de alguna subclase de O u tp u tS tre a m , el siguiente cdigo escribe el byte es
pecificado en el destino vinculado con JlujoS:
int n;
II...
flujoS.w ri t e (n ) ;
La segunda versin del m todo w rite escribe los bytes alm acenados en la
m atriz b en un flujo de salida (m s adelante, dedicarem os un captulo a explicar
las m atrices de datos).
La tercera versin del m todo w rite escribe un m xim o de len bytes de una
m atriz b a partir de su posicin off. en un flujo de salida.
C ada uno de estos m todos ha sido escrito para que bloquee la ejecucin del
program a que los invoque hasta que toda la salida solicitada haya sido escrita.
Excepciones
Cuando durante la ejecucin de un program a ocurre un error que im pide su conti
nuacin, por ejem plo, una entrada incorrecta de datos o una divisin por cero. Ja
va lanza una excepcin, que cuando no se captura da lugar a un m ensaje acerca de
lo ocurrido y detiene su ejecucin (las excepciones se lanzan, no ocurren). Ahora,
si lo q ue deseam os es que la ejecucin del program a no se detenga, habr que
capturarla y m anejarla adecuadam ente en un intento de reanudar la ejecucin.
Puesto que en Java hay m uchas clases de excepciones, un m todo puede indi
car los tipos de excepciones que posiblem ente puede lanzar. Por ejem plo, puede
observar que los m todos read y w rite que acabam os de exponer lanzan excep
ciones del tipo IO E x c e p tio n . Entonces, cuando utilicem os alguno de esos m to
dos hay que escribir el cdigo necesario para capturar las posibles excepciones
que pueden lanzar. E sto es algo a lo que nos obliga el com pilador Java, del m ism o
m odo que l verifica si una variable ha sido iniciada antes de ser utilizada, o si el
nm ero y tipo de argum entos utilizados con un m todo son correctos, con la nica
intencin de m inim izar los posibles errores que puedan ocurrir.
Para capturar una excepcin hay que hacer dos cosas: una, poner a prueba el
cdigo que puede lanzar excepciones dentro de un bloque try; y dos, m anejar la
excepcin cuando se lance, en un bloque catch. Por ejem plo:
try
1
// C d i g o que p u e d e l a n z a r una e x c e p c i n
n = f 1u j o E . r e a d ( ) : II p u e d e l a n z a r una e x c e p c i n IOException
I
c a t c h ( I O E x c e p t i o n e)
I
// M a n e j a r una e x c e p c i n d e l a c l a s e I O E x c e p t i o n
S y s t e m . o u t . p r in t 1n ( " E r r o r : " + e . g e t M e s s a g e ( ));
1
Esto es todo lo que necesita saber por ahora para poder utilizar los mtodos
involucrados en la E/S que lancen excepciones. M s adelante, dedicarem os un ca
ptulo al estudio de excepciones.
System .out. R eferencia a la salida estndar del sistem a, que norm alm ente es
el m onitor. Se utiliza para m ostrar datos al usuario.
System .err. R eferencia a la salida estndar de error del sistem a, que normal
m ente es el m onitor. Se utiliza para m ostrar m ensajes de error al usuario.
i n t n:
n = S y s t e m . i n . r e a d t ); // e n t r a d a p o r t e c l a d o : A
System .out.p rintln (n): // s a l i d a p o r m o n i t o r : 65
b y t e b:
b = ( b y t e ) S y s t e m . i n . r e a d ) : // e n t r a d a p o r t e c l a d o : A
System .out.p rin tln (b): // s a l i d a p o r m o n i t o r : 65
El valor devuelto por el m todo read tam bin puede ser convertido explci
tam ente al tipo c h a r para m anipular caracteres:
c h a r c;
c = ( c h a r ) S y s t e m . i n . r e a d ( ) ; // e n t r a d a p o r t e c l a d o : A
System .out.p rin tln (c): // s a l i d a p o r m o n i t o r : A
Q u otros m todos podem os utilizar con estos flujos? Para dar respuesta a
esta pregunta prim ero tendrem os que investigar de qu clases son estos objetos y
despus, analizar esas clases. A veriguar de qu clases son estos objetos es una ta
rea sim ple; basta con revisar la inform acin de la biblioteca de Java, o bien utili
zar un o bjeto C lass com o se indica en el apartado siguiente.
CA PTU LO 5: C L A SES DE USO COM N 9 7
De los m todos a los que nos hem os referido, nos interesa ahora ge tC lass. Pa
ra invocar este m todo puede hacerlo as:
Class ObjetoClass - c u a l q u i e r O b j e t o . g e t C l a s s ( );
import j a v a . i o . * :
class ClaseDeUnObj
I
public static void m a in (S trin g [] args)
I
int n:
try
I
S y s t e m . o u t . p r i n t ( " D a t o : );
n = S y s t e m . i n . r e a d ( ) ; // l e e r un c a r c t e r d e s d e e l t e c l a d o
S y s t e m . o u t . p r i n t l n t ( c h a r ) n ) ; // v i s u a l i z a r e l c a r c t e r
// I n v e s t i g a m o s
C l a s s O b j e t o C l a s s ; // o b j e t o C l a s s
O b j e t o C l a s s = S y s t e m . i n . g e t C l a s s ( ):
S y s t e m . o u t . p r i n t l n ( " C l a s e de i n : " + O b j e t o C l a s s .getNamet)):
O b j e t o C l a s s = S y s t e m . o u t . g e t C l a s s t ):
S y s t e m . o u t . p r i n t 1n ( C 1 a s e d e o u t : " + O b j e t o C l a s s . g e t N a m e ( ) ) :
O b j e t o C l a s s = S y s t e m . e r r . g e t C l a s s );
S y s t e m . o u t . p r i n t l n ( C l a s e de e r r : " + O b j e t o C l a s s . g e t N a m e ( )) :
I
c a t c h ( I O E x c e p t i o n e)
I
S y s t e m . e r r . p r i n t l n t E r r o r : " + e .g e t M e s sa g e ));
98 JA V A: C U R SO DE PROGRAM ACIN
Dato: 1
1
C l a s e de i n : c la s s java. io.BufferedlnputStream
C l a s e de o u t : c la ss j a v a . io.PrintStream
C l a s e de e r r : class java.io.PrintStream
BufferedlnputStream
L a clase anloga a B u ffe re d ln p u tS tre a m , pero que perm ite trabajar con ca
racteres es B u ffe re d R e a d e r. clase derivada de R e ad e r.
BufferedReader
} ( Flujo \ r x
__________ I F |ui | L O rig en
s u b y a c e n te r
V J V J
B u f f e r e d R e a d e r f l u j o E = new B u f f e r e d R e a d e r C i s r ):
El cdigo anterior indica que el flu jo E dirigir todas las invocaciones de sus
m todos al flujo subyacente isr, este flujo, en el caso de que el origen sea el tecla
d o (dispositivo vinculado con Syste m .in ), deber convertir los bytes ledos del te
clado en caracteres. D e esta form a flu jo E podr sum inistrar un flujo de caracteres
al program a destino de los datos. Para ello hay que definir el flujo que hem os de
nom inado isr as:
InputStreamReader i s r = new I n p u t S t r e a m R e a d e r ( S y s t e m . i n ) :
c a ra c te re s bytes
C om o ejem plo, vam os a realizar una aplicacin que lea una lnea de texto in
troducida a travs del teclado y la visualice en la pantalla.
import j a v a . i o . * ;
public c la ss LeerUnaCadena
I
public static void main( S t r i n g [ ] a rg s)
I
// D e f i n i r un f l u j o de c a r a c t e r e s d e e n t r a d a : f l u j o E
I n p u t S t r e a m R e a d e r i s r = new I n p u t S t r e a m R e a d e r C S y s t e m . i n ) :
B u f f e r e d R e a d e r f l u j o E = new B u f f e r e d R e a d e r t i s r ) :
// D e f i n i r una r e f e r e n c i a a l f l u j o e s t n d a r de s a l i d a : f l u j o S
PrintStream f lu j o S = System.out;
S t r i n g s d a t o ; // v a r i a b l e p a r a a l m a c e n a r una l i n e a de t e x t o
try
I
f l u j o S . p r i n t ( " I n t r o d u z c a un t e x t o : " > :
s d a t o = f 1u j o E . r e a d L i n e ( ) : // l e e r u n a l i n e a de t e x t o
flu joS.println(sdato); // e s c r i b i r l a l i n e a l e d a
I
catch (IOException ignorada) I I
)
I
PrintStream
p r i n t ( t i p o a r g u m e n t o ):
p r i n t l n ([tipo a r g u m e n t o ] ) ;
Los m todos p rin t y p r in tln son esencialm ente los m ism os; am bos escriben
su argum ento en el flujo de salida. La nica diferencia entre ellos es que println
aade un carcter 'W (avance a la lnea siguiente) al final de su salida, y print
no. En otras palabras, la siguiente sentencia:
Los argum entos para p r in t y p rin tln pueden ser de cualquier tipo prim itivo o
referenciado: O bject, S trin g . char[], int, long. float, double, y boolean. En adi
cin, hay u na versin extra de p rin tln que no tiene argum entos y lo que hace es
escrib ir un carcter Vi, lo que se traduce en un avance a la lnea siguiente.
C om o ejem plo, la siguiente aplicacin utiliza p rin tln para escribir datos de
varios tipos en la salida estndar.
public c la s s TestTiposDatos
I
// T i p o s de d a t o s
pu b lic s t a t ic void m a in (S trin g [] args)
I
S t r i n g sCadena = " L e n g u a j e J a v a ;
c h a r [ ] c M a t r i z C a r s = I ' a ' , ' b ' , c I : // m a t r i z d e c a r a c t e r e s
i n t d a t o _ i n t = 4;
long dato_lon g = Long.MIN_VALUE: // m n i m o v a l o r l o n g
f l o a t d a t o _ f l o a t = F l o a t . M A X _ V A L U E ; // mxi mo v a l o r f l o a t
double dato_double = M ath.Pl; // 3 . 1 4 1 5 9 2 6
boolean dato_boolean = true:
System .out.println(sCadena);
S y s t e m . o u t . p r i n t l n ( c M a t r i z C a r s ):
S y s t e m . o u t . p r i n t l n ( d a t o _ i n t ):
System .out.println(dato_long):
S y s t e m . o u t . p r i n t l n ( d a t o _ f 1o a t ):
System .out.println(dato_double);
S y s t e m . o u t . p r i n t l n ( d a t o _ b o o 1e a n );
L enguaje Java
abe
4
-9223372036854775808
3 . 4028235E38
3.141592653589793
true
102 JA V A: C U R SO D E PROGRAM A CIN
P r i n t W r i t e r f l u j o S = new P r i n t W r i t e r ( S y s t e m . o u t ) :
i n t d a t o _ i n t = 4;
f 1 u j o S . p r i n t l n ( d a t o _ i n t ) : f 1u j o S . f 1 u s h ( ) ;
En la figura anterior se pueden observar en color gris las clases com entadas
en este captulo; las coloreadas en gris m s oscuro son clases abstractas (una lnea
discontinua indica que esa clase no se deriva directam ente de O b ject; esto es, en
tre O b je c t y la clase hay otras clases que no tienen inters para el tem a que esta
mos tratando).
D espus de analizar la jerarq u a de clases para, entre otras cosas, llegar a ver
la procedencia de los flujos in y out, se deduce que para leer del flujo in slo se
dispone de m todos que proporcionan un carcter, o bien una m atriz de caracte
res; para leer una cadena de caracteres del flujo in y alm acenarla en un objeto
S t r in g lo tenem os que hacer desde un flujo de la clase B u ffe re d R e a d e r; y para
escribir en el flujo o u t tenem os los m todos proporcionados por la clase P r in t S -
tream , o bien P rin tW r ite r. que perm iten escribir cualquier valor de cualquier ti
po prim itivo o referenciado.
Evidentem ente, cualquier operacin aritm tica requiere de valores num ricos;
pero, segn lo expuesto, en el m ejor de los casos slo se puede obtener una cade
na de bytes. El cdigo siguiente pertenece a la aplicacin LeerU naC adena reali
zado anteriorm ente:
f l u j o S . p r i n t ( " I n t r o d u z c a un t e x t o : "):
s d a t o = f l u j o E . r e a d L i n e ( ) : // l e e r una l n e a de t e x t o
El cdigo anterior perm ite leer del flujo in una cadena de caracteres que ser
alm acenada en el objeto sdato de tipo S trin g . Por ejem plo, si cuando se ejecute el
m todo re a d L in e se teclea el dato 45 6 , estos dgitos sern alm acenados en sdato
com o una cadena de caracteres. A hora bien, para que esa cadena de tres caracteres
pueda ser utilizada en una expresin aritm tica, tiene que adquirir la categora de
valor num rico, lo que im plica convertirla a un valor de alguno de los tipos pri
m itivos. Esto puede hacerse utilizando los m todos proporcionados por las clases
que encapsulan los tipos prim itivos.
A tributo Descripcin
M IN J V A L U E V alor m s pequeo de tipo int.
M AXJVALUE V alor m s grande de tipo int.
M todo Descripcin
d o u b lc V a lu e O D evuelve el objeto In te g e r com o un valor double.
flo a tV a lu e O D evuelve el objeto In te ge r com o un valor float.
in tV a lu e O D evuelve el objeto In te ge r com o un valor int.
lo n g V a lu e O D evuelve el objeto In te ge r com o un valor long.
p a rse ln t(S trin g ) C onvierte una cadena a un valor int.
to Strin g(in t) C onvierte un valor int en una cadena (objeto Strin g).
v a lu e O f(S trin g ) C rea un objeto In te ge r a partir de una cadena.
Atributo D escripcin
M IN J V A L U E V alor m s pequeo de tipo float.
M AXJVALUE V alor m s grande de tipo float.
NaN N o es un N m ero; de tipo float.
N E G A T IV E _ IN F IN IT Y V alor infinito negativo de tipo float.
P O S IT IV E J N F IN IT Y V alor infinito positivo de tipo float.
De acuerdo con lo expuesto, para obtener, por ejem plo, un entero a partir de
una cadena de caracteres proporcionada por re a d L in e habr que ejecutar los si
guientes pasos:
I n p u t S t r e a m R e a d e r i s r = new I n p u t S t r e a m R e a d e r ( S y s t e m . i n ) ;
B u f f e r e d R e a d e r f l u j o E = new B u f f e r e d R e a d e r ( i s r ) ;
C A PTU LO 5: CL A SES DE USO COM N 10 5
S tr in g sdato; // v a r i a b l e p a r a a l m a c e n a r una c a d e n a
int dato_int; // v a r i a b l e p a r a a l m a c e n a r un e n t e r o
try
I
s d a t o = f l u j o E . r e a d L i n e ( ) : // l e e r una c a d e n a de c a r a c t e r e s
d a t o _ i n t = I n t e g e r . p a r s e l n t ( s d a t o ) : // c o n v e r t i r a e n t e r o
I
catch (IOException ignorada) I I
En el ejem plo anterior se observa que una vez leda la cadena sd a to , que se
supone es una cadena vlida para ser convertida en un entero, se invoca al m todo
esttico p a rse ln t para convertir el objeto S t r in g en un dato de tipo int.
A nlogam ente, para convertir una cadena de bytes que representa un nm ero
con punto decim al, en un valor de tipo float, el cdigo sera el siguiente:
s d a t o = f 1u j o E . r e a d L i n e ( ) ; // l e e r una c a d e n a de c a r a c t e r e s
F l o a t f = new F 1 o a t ( s d a t o ) ; II c r e a r un o b j e t o F l o a t
f l o a t d a t o _ f l o a t = f . f l o a t V a l u e ( ): // o b t e n e r e l v a l o r f l o a t
Segn lo expuesto, podem os escribir un m todo dato que lea una cadena de
caracteres desde el teclado, la alm acene en un objeto S t r in g y devuelva com o re
sultado dicho objeto.
S t r i ng d a t . o ( )
I
S t r in g sdato = " " :
try
I
// D e f i n i r un f l u j o de c a r a c t e r e s d e e n t r a d a : f l u j o E
I n p u t S t r e a m R e a d e r i s r = new I n p u t S t r e a m R e a d e r ( S y s t e m . i n ) ;
B u f f e r e d R e a d e r f l u j o E = new B u f f e r e d R e a d e r i s r );
// L e e r . La e n t r a d a f i n a l i z a al p u l s a r l a t e c l a E n t r a r
s d a t o = f l u j o E . r e a d L i n e ( ):
I
catchIOException e)
I
S y ste m .e rr.p rin tln C 'E rro r: " + e.getM essage()):
1
return sdato; // d e v o l v e r e l dato tecleado
1 0 6 JA V A: C U R S O D E PROGRAM A CIN
int datolnt()
I
String sdato = dato (): // i n v o c a al m t o d o d a t o
return I n t e g e r . p a r s e l n t ( s d a t o ) ; // c o n v i e r t e s d a t o en un i n t
I
int datolntt)
I
try
I
return I n t e g e r . p a r s e l n t ( d a t o ( )):
1
c a t c h ( N u m b e r F o r m a t E x c e p t i o n e)
I
return Integer.MIN_VALUE; II v a l o r ms p e q u e o de t i p o int
A nlogam ente, podem os escribir otros m todos para convertir una cadena
vlida, devuelta por el m todo dato, en otros tipos de datos prim itivos. Agrupe
mos todos estos m todos en una clase denom inada Leer.
Clase Leer
El objetivo es escribir una clase L eer que incluya com o m iem bros, adems de los
m todos que hem os venido im plem entando anteriorm ente, otros m todos, de ma
CA PTU LO 5: C L A S E S DE U SO C O M N 107
era que todos ju n to s proporcionen una interfaz que cualquier program a puede
utilizar para obtener del teclado datos de cualquier tipo prim itivo. El cdigo que
define esta clase se m uestra a continuacin.
import j a v a . i o . * :
En la clase Leer, se puede observar que todos los m todos, adem s de pbli
cos, se han declarado static con el fin de que puedan ser invocados all donde se
necesiten, sin necesidad de que exista un objeto de la clase. R ecuerde que la sin
taxis para invocar a un m todo de una clase es:
Una vez escrita la clase Leer, podem os utilizarla com o soporte para otras
aplicaciones. C om o ejem plo, vam os a escribir una aplicacin que lea un dato de
cada uno de los tipos contem plados en L eer y m uestre despus los valores ledos.
C A PTU LO 5: CL A SES DE USO C O M N 109
R ecuerde que para que la clase aplicacin que vam os a escribir pueda utilizar la
clase Leer, deben estar am bas en la m ism a carpeta de trabajo.
// U t i l i z a l a c l a s e L e e r q u e d e b e d e e s t a r al macenada
// en l a mi s ma c a r p e t a
S y s t e m . o u t . p r i n t ( " D a t o s h o r t : ):
d a t o _ s h o r t = L e e r . d a t o S h o r t t ):
S y s t e m . o u t . p r i n t ( " D a t o i n t : );
d a t o _ i n t = L e e r . d a t o l n t t ):
S y s t e m . o u t . p r i n t C D a t o l ong : ):
d a t o _ l o n g = L e e r . d a t o L o n g );
System.out.print"Dato float: "):
d a t o _ f l o a t = L e e r . d a t o F l o a t t ):
S y s t e m . o u t . p r i n t " D a t o double: " ) :
d a t o _ d o u b l e - L e e r . d a t o D o u b l e ( ):
System.out.println(dato_short):
System.out.println(dato_int):
System.out.println(dato _ lo ng);
System.out.println(dato_float);
System.out.println(dato_double):
D espus del trabajo realizado, ya tenem os una form a de leer datos num ricos
introducidos a travs del teclado. Esto nos perm itir escribir diversas aplicaciones
que requieren de este proceso. A dem s, sabem os tam bin cm o convertir nm e
ros a cadenas de caracteres y viceversa.
Variable CLASSPATH
C uando en el cdigo fuente de un program a se hace referencia a una clase que no
pertenece a un paquete que se pueda im portar, com o ocurre con la clase Leer, Ja
va busca por ella en el directorio actual si la variable C LA SSP A TH no ha sido es
tablecida. En o tro caso busca en las rutas especificadas p o r esta variable.
CLASSPATH=c: . ; \ j d k 1 . 3 \ m i s C l a s e s
El ejem plo anterior indica a Java que busque las clases a las que haga referen
cia un determ inado program a, adem s de en los paquetes im portados, en la car
peta actual de trabajo (.) o en la carpeta jdkl.S^m isC lases.
Recuerde que cuando el m todo read intenta leer y se encuentra con el final
del flujo, retorna la constante -1 . A nlogam ente, cuando el m todo re a d L in e in
tenta leer del flujo y se encuentra con el final del m ism o, retom a la constante nuil.
Para aclarar lo expuesto, el siguiente ejem plo solicita del teclado un dato precio.
Entonces, si al m ensaje P recio: respondem os escribiendo una cantidad, la varia
ble precio alm acenar ese valor, pero si respondem os pulsando las teclas C trl+Z
(carcter fin de fichero), deber alm acenar el valor N a N de tipo float.
i mpor t j a v a . i o . * ;
S t r i n g sdato:
f l o a t pre cio = 0.0F:
try
I
f l u j o S . p r i n t ( " P r e c i o : ):
s d a t o - f l u j o E . r e a d l i n e ( ):
precio - (sdato != n u i l )
? ( new F 1 o a t ( s d a t o ) ) . f l o a t V a l u e ( )
: Float.NaN:
I
catch (lOException ignorada)! 1
flujoS.println(precio):
f l u j o S . p r i n t l n ( " C o n t i n u a la a p l i c a c i n " ) :
C uando ejecute esta aplicacin puede proceder de cualquiera de las dos for
m as siguientes:
P re c i o: 123.45
123.45
Continua la a p l i c a c i n
1 1 2 JA V A: C U R SO DE PRO G R A M A CI N
F l o a t f - new F l o a t ( s d a t o ) :
precio - f.flo a tV a lu e O :
CARACTERES \r\n
C uando se estn introduciendo datos a travs del teclado y pulsam os la tecla En
tra r se introducen tam bin los caracteres W t . correspondientes a los caracteres
ASCII CR L F (C R es el A SCII 13 y L F es el A SC II 10). M ientras que en la salida
Vi produce un C R+ LF, en la entrada se corresponde con un L F \ esto es. una ex
presin Java com o V i' = = 10 dara com o resultado true.
Por ejem plo, suponiendo definidos los flujos flu jo E y flu jo S igual que en el
ejem plo anterior, el cdigo siguiente lee un carcter:
char opcin:
try
I
f 1u j o S . p r i n t ( " O p c i n (a, b o c) : ):
o p c i n - ( c h a r ) f 1u j o E . r e a d ( ) :
1
catch (IOException ignorada)! 1
b [ E n tr a r ]
CA PTU LO 5: CLASES DE USO C O M N 1 13
| b 1 \ r | \n | | | | | |
y despus de la lectura:
1 \ r | \n |
ya que read lee un solo carcter. Estos caracteres sobrantes pueden ocasionarnos
problem as si a continuacin se ejecuta otra sentencia de entrada que adm ita datos
que sean caracteres. Por ejem plo:
char opcin;
S t r i n g sdato:
try
I
f l u j o S . p r i n t ( "Opci n (a, b o c ) : "):
o p c i n = ( c h a r ) f l u j o E . r e a d ( );
Si ejecutam os esta aplicacin y tecleam os, por ejem plo, com o opcin b segui
da de la pulsacin de la tecla Entrar, se producir el siguiente resultado:
El m todo sk ip perm ite saltar n caracteres en el flujo de entrada para que no estn
presentes en la prxim a operacin de lectura; y el m todo a v a ila b le devuelve el
nm ero de caracteres que hay disponibles en el flujo de entrada. Por ejem plo:
char opcin:
int ncars;
S t r i n g sdato:
try
I
f l u j o S . p r i n t ( " O p c i n (a. b o c ) : ");
o p c i n = ( c h a r ) f l u j o E . r e a d ( ):
n c a r s - f 1 u j o E . a v a i 1
a b l e ( ) : / / c a r a c t e r e s d i s p o n i b l e s
f l u j o E . s k i p ( n c a r s ) : / / s a l t a r l o s c a r a c t e r e s C R L F
Un buffer se lim pia autom ticam ente cuando est lleno, cuando se cierra el
flujo, o bien cuando el program a finaliza norm alm ente.
MTODOS MATEMTICOS
La biblioteca de clases de Java incluye una clase llam ada M a t h en su paquete ja-
va.lang, la cual define un conjunto de operaciones m atem ticas de uso com n que
pueden ser utilizadas por cualquier program a.
La tabla siguiente resum e los m iem bros de la clase M a t h . T odos los miem
bros de esta clase son static para que puedan ser invocados sin necesidad de defi
nir un objeto de la clase.
M todo Descripcin
static double E V alor del nm ero e (base del logaritm o nepe-
riano o natural).
CA PTU LO 5: CLASES DE USO C O M N 1 15
EJERCICIOS RESUELTOS
1. R ealizar una aplicacin que d com o resultado los intereses producidos y el capi
tal total acum ulado de una cantidad c, invertida a un inters r durante t das.
c* r* t
7 = 360*100
siendo:
/ = Total de intereses producidos.
c = C apital.
r = T asa de inters nom inal en tanto por ciento.
/ = Perodo de clculo en das.
Prim ero definim os las variables que vam os a u tilizar en los clculos.
C onocidos los datos, realizam os los clculos. N os piden los intereses produci
dos y el capital acum ulado. Los intereses producidos los obtenem os aplicando
directam ente la frm ula. El capital acum ulado es el capital inicial m s los in
tereses producidos.
in te re se s = c * r * t / (360 * 100):
capital = c + intereses:
ENTRADA PROCESO S A L ID A |
// La c l a s e L e e r d e b e e s t a r en a l g u n a c a r p e t a de l a s especificadas
// p o r l a v a r i a b l e de e n t o r n o C L A S S P A T H .
public class CIntereses
I
public static void m a in ( S trin g [] args)
I
d o u b l e c. i n t e r e s e s , c a p i t a l :
f l o a t r;
i n t t:
System.out.print("Capital invertido: "):
c = L e e r . d a t o D o u b l e );
S y s t e m . o u t . p r i n t \ n A un % a n u a l d e l : );
r = L e e r . d a t o F l o a t );
S y s t e m . o u t . p r i n t "\nDurante cuntos d as : ");
t = L e e r . d a t o l n t );
i n te re s e s = c * r * t / (360 * 100):
capi ta l = c + i n t e r e s e s :
ax2 + bx + c = O
- b y l b : 4 a c
1 18 JAVA: C U R SO DE PROGRAM A CIN
d o u b l e a. b, c. d. xl, x2:
System.out.print("Coeficiente a: ) : a - L e e r , d a t o D o u b l e ( );
System.out.print"Coeficiente b: " ) : b = L e e r . d a t o D o u b l e ( ):
System.out.print("Coeficiente c: " ) : c - L e e r . d a t o D o u b l e ( );
N os piden calcular las races reales. Para que existan races reales tiene que
cum plirse que b2-4 a c > 0; si no, las races son com plejas conjugadas. E nton
ces, si hay races reales las calculam os; en otro caso, salim os de la aplicacin.
Para salir de una aplicacin, en general para salir de un proceso sin hacer na
da m s. Java proporciona la sentencia re tu rn .
d = b * b - 4 * a * c :
i f (d < 0)
I
// S i d e s menor q u e 0
System.out.println"Las races son c o m p l e j a s . " ) ;
r e t u r n : // s a l i r
I
II S i d e s ma y o r o i g u a l que 0
System.out.println"Las races reales son:"):
d = Math.sqrt(d):
x l = ( - b + d) / ( 2 * a ) :
x2 = ( - b - d) / ( 2 * a ) :
/ / L a c l a s e L e e r d e b e e s t a r en a l g u n a c a r p e t a de l a s e s p e c i f i c a d a s
// p o r l a v a r i a b l e d e e n t o r n o C L AS S P A T H.
pu b li c c l a s s CEcuacion
I
public s t a t i c void m a in (S trin g [] args)
i
d o u b l e a. b. c, d, x l . x2:
System.out.print("Coeficiente a: " ) : a = L e e r . d a t o D o u b l e ( ):
System, out . p r i n t C C o e f i c i e n t e b: ): b = L e e r . d a t o O o u b l e ( ):
S y s t e m . o u t .p r i n t ( " C o e f i c i e n t e c : ) ; c - L e e r , d a t o O o u b l e ( ):
d - b * b - 4 * a * c ;
i f ( d < 0)
// S i d e s me n o r que 0
System.out.println"Las races son co m pl ej a s . ") ;
r e t u r n : // s a l i r
I
// S i d e s ma y o r o i g u a l q u e 0
S y s t e m . . o u t . p r i n t l n ( L a s r a c e s r e a l e s s o n : );
d - Math.sqrt(d);
x l - ( - b + d) / ( 2 * a ) ;
x 2 - ( - b - d) / ( 2 * a ) ;
S y s t e m . o u t . p r i n t l n C ' x l = " + x l + " . x2 = " + x 2 ) ;
EJERCICIOS PROPUESTOS
1. Realizar una aplicacin que calcule el volum en de una esfera, que viene dado por
la frmula:
4 3
v =-n r
2. R ealizar una aplicacin que pregunte el nom bre y el ao de nacim iento y d com o
resultado:
H o l a n o mb r e , en e l ao 2030 t e n d r s n aos
char c a r i = A , c a r 2 - 65, c a r 3 = 0:
SENTENCIAS DE CONTROL
C ada m todo de las aplicaciones que hem os hecho hasta ahora, era un conjunto de
sentencias q ue se ejecutaban en el orden en el que se haban escrito, entendiendo
por sentencia una secuencia de expresiones que especifica una o varias operacio
nes. Pero esto no es siem pre as; seguro que en algn m om ento nos ha surgido la
necesidad de ejecutar unas sentencias u otras en funcin de unos criterios especi
ficados p o r nosotros. Por ejem plo, en el captulo anterior, cuando calculbam os
las races de una ecuacin de segundo grado, vim os que en funcin del valor del
discrim inante las races podan ser reales o com plejas. En un caso com o ste, sur
ge la necesidad de que sea el propio program a el que tom e la decisin, en funcin
del valor del discrim inante, de si lo que tiene que calcular son dos races reales o
dos races com plejas conjugadas.
En este captulo aprender a escribir cdigo para que un program a tom e deci
siones y para que sea capaz de ejecutar bloques de sentencias repetidas veces.
SENTENCIA if
La sentencia if perm ite a un program a tom ar una decisin para ejecutar una ac
cin u otra, basndose en el resultado verdadero o falso de una expresin. La sin
taxis para utilizar esta sentencia es la siguiente:
122 JA VA : C U R SO D E PROGRAM A CIN
if ( condicin)
s e nt e n c i a 1;
[ e l se
s e nt e n c i a 2];
1. Se evala la condicin.
A continuacin se exponen algunos ejem plos para que vea de una form a sen
cilla cm o se utiliza la sentencia if.
if ( x ! = 0)
b = a / x;
b = b + 1:
i f ( a < b ) c = c + 1;
// s i g u i e n t e l i n e a d e l p r o g r a ma
En este otro ejem plo, la condicin viene im puesta por una expresin a < b. Si
al evaluar la condicin se cum ple que a es m enor que b, entonces se ejecuta la
sentencia c = c + I. En otro caso, esto es, si a es m ayor o igual que b, se contina
en la lnea siguiente, ignorndose la sentencia c = c + 1.
C A PTU LO 6: SEN TEN CIA S D E C O N TR O L 12 3
if (a ! - 0 U b ! - 0)
x 1;
// s i g u i e n t e l i n e a d e l p r o g r a ma
En el ejem plo siguiente, si se cum ple que a es igual a b*5, se ejecutan las
sentencias x = 4 y a = a + x . En otro caso, se ejecuta la sentencia b = 0. En am
bos casos, la ejecucin contina en la siguiente lnea de program a.
if (a b * 5)
I
x 4;
a - a + x;
I
else
b = 0;
// s i g u i e n t e lnea del p r o g r a ma
if (a - b * 5)
// ...
a - b * 5:
i f (a)
// ...
a = b * 5:
i f ( a ! 0)
II...
que equivale a:
if ((a - b * 5) ! - 0)
II ...
1 2 4 JA V A : C U R SO D li PROGRAM A CIN
ANIDAMIENTO DE SENTENCIAS if
O bservando el form ato general de la sentencia if cabe una pregunta: cm o sen
tencia / o sentencia 2 se puede escribir otra sentencia if? La respuesta es s. Esto
es, las sentencias i f ... else pueden estar anidadas. Por ejem plo:
if ( c o n d i c i n 1)
I
if ( c o n d i c i n 2)
s en t e n c i a :
I
else
s e nt e n c i a 2:
En el ejem plo anterior las llaves definen perfectam ente que la clusula else
est em parejada con el p rim er if. Q u sucede si quitam os las llaves?
if (c o n d i c i n 1)
i f (c o n d i c i n 2)
s e n t e nc i a 1;
else
s en t e n c i a 2;
i f (a > b)
flujoS.printlna + " e s mayor que " + b ) ;
el s e i f ( a < b)
flujoS.printlna + e s me n o r que " + b ):
el se
flujoS.printlna + " es i g u a l a " + b):
// s i g u i e n t e l i n e a de l programa
Es im portante observar que una vez que se ejecuta una accin com o resultado
de haber evaluado las condiciones im puestas, la ejecucin del program a contina
en la siguiente lnea a la estructura a que dan lugar las sentencias i f ... else anida
das. En el ejem plo anterior si se cum ple que a es m ayor que b, se escribe el m en
saje correspondiente y se contina en la siguiente lnea del program a.
i f (a - 0)
i f ib != 0)
s ** s + b:
el se
s = s + a:
// s i g u i e n t e l i n e a del programa
i f (a 0)
1 2 6 JA V A: CU R SO DE PRO G R A M A CI N
if ( b ! - 0)
s = s + b;
I
el se
s = s + a;
// s i g u i e n t e l n e a del programa
// La c l a s e L e e r d e b e e s t a r en a l g u n a c a r p e t a de l a s especificadas
// p o r l a v a r i a b l e de e n t o r n o C L A S S PA TH .
//
public c la ss C Menor
I
// M e n o r d e t r e s n m e r o s a. b y c
// L e e r l o s v a l o r e s de a .b y c
S y s t e m . o u t . p r i n t ( "a : "); a = L e e r . d a t o F l o a t ( );
System .out.print("b : ') ; b = L e e r . d a t o F l o a t ( );
System .out,print("c : "); c - L e e r . d a t o F l o a t ( );
// O b t e n e r e l menor
i f ( a < b)
i f (a < c)
me n o r = a;
el se
menor = c ;
el se
i f (b < c)
me n o r = b;
el se
menor = c;
S y s t e m . o u t . p r i n t l n " M e n o r = " + menor):
ESTRUCTURA else if
La estructura presentada a continuacin, aparece con bastante frecuencia y es por
lo que se le da un tratam iento por separado. E sta estructura es consecuencia de las
sentencias if anidadas. Su form ato general es:
CA PTU LO 6: SEN TEN CIA S DE CO N TRO L 127
if ( c on d i c i n 1 )
s en t e n c i a 1:
e l s e i f ( c o n d i c i n 2)
s en t e n c i a 2:
e l s e i f ( c o n d i c i n 3)
s en t e n c i a 3;
el se
s e n t e n c i a n;
P o r ejem plo, al efectuar una com pra en un cierto alm acn, si adquirim os ms
de 100 unidades de un m ism o artculo, nos hacen un descuento de un 4 0 %; entre
25 y 100 un 2 0 %; entre 10 y 24 un 10 % ; y no hay descuento para una adquisi
cin de m enos de 10 unidades. Se pide calcular el im porte a pagar. La solucin se
presentar de la siguiente forma:
Cdigo a r t c u l o 111
Cantidad comprada 100
Precio u n it a r i o 1 00
D e s c u e n t o ....................... 2 0 . 0 %
T o t a l .............................. 8 0 0 0 . 0
En la solucin presentada com o ejem plo, se puede observar que com o la can
tidad com prada est entre 25 y 100, el descuento aplicado es de un 20% .
Prim ero definim os las variables que vam os a utilizar en los clculos.
i n t a r , cc:
f l o a t pu. d e s c ;
a r = L e e r . d a t o l n t ):
S y s t e m . o u t . p r i n t ( " C a n t i d a d comprada "):
c c = L e e r , d a t o I n t ( ):
S y s t e m . o u t . p r i n t ( " P r e c i o u n i t a r i o ............ ");
pu - L e e r . d a t o F l o a t ):
if ( c c > 100)
desc - 4 0 F ; I I descuento 40%
e l s e i f ( c c > - 25)
desc = 2 0 F ; // d e s c u e n t o 20%
e l s e i f ( c c > - 10)
desc = 10F : // d e s c u e n t o 10%
el se
desc = 0.0F; // d e s c u e n t o 0%
S y s t e m , o u t . p r i n t l n( D e s c u e n t o ........................ + d e s c + " % " ) :
S y s t e m . o u t . p r i n t l n( " T o t a l ................................ " +
cc * pu * (1 - d e s c / 1 0 0 ) ) :
Se puede observar que las condiciones se han establecido segn los descuen
tos de m ayor a m enor. C om o ejercicio, piense o pruebe que ocurrira si establece
las condiciones segn los descuentos de m enor a m ayor. La aplicacin com pleta
se m uestra a continuacin.
// La c l a s e L e e r d e b e e s t a r en a l g u n a c a r p e t a de l a s especificadas
// p o r l a v a r i a b l e de e n t o r n o C L A S S P A T H .
//
public class CDescuento
(
public static void m a in (S trin g [] args)
I
i n t a r . cc:
f l o a t pu. d e s c :
if (cc >1 0 0 )
desc = 40 F ; // d e s c u e n t o 40%
el s e i f ( c c > - 25)
desc = 20F; // d e s c u e n t o 20%
else i f ( c c > - 10)
desc = 10F ; // d e s c u e n t o 10%
CA PTU LO 6: SEN TEN CIA S DE C O N TR O L 129
el se
desc - 0.0F; // d e s c u e n t o 0%
S y s t e m , o u t . p r i n t l n( " D e s c u e n t o ............. " + d e s c +
S y s t e m . o u t . p r i n t l n t " T o t a l ................................ " +
c c * pu * (1 - d e s c / 1 0 0 ) ) :
SENTENCIA switch
La sentencia sw itch perm ite ejecutar una de varias acciones, en funcin del valor
de una expresin. Es una sentencia especial para decisiones m ltiples. La sintaxis
para utilizar esta sentencia es:
switch (e x p r e s i n )
c a se e x p r e s i n - c o n s t a n t e 1:
[ s e n t e n c i a 1;]
[case e x p r e s i n - c o n s t a n t e 2 : ]
[ s e n t e n c ia 2:]
[case e x p r e s i n - c o n s t a n t e 3 :]
[ s e n t e n c i a 3;]
[default: ]
[sentencia n:]
1
switch (m)
i n t n = 0, k = 2; // d e c l a r a c i n no p e r m i t i d a
c a s e 7:
/ aracin permitida
while ( i < m )
n += ( k + i ) * 3:
i++:
break;
c a s e 13:
// . . .
break:
// . . .
i n t n - 0, k 2 ; ~
s w i t c h (m)
1
I I ...
I
Para ilustrar la sentencia sw itch , vam os a realizar un program a que lea una
fecha representada por dos enteros, m es y ao, y d com o resultado los das co
rrespondientes al m es. Esto es:
I n t r o d u c i r mes ( # # ) y a o ( # # # # ) : 5 2 0 0 2
El mes 5 d e l a o 2 0 0 2 t i e n e 31 d i a s
Prim ero definim os las variables que vam os a utilizar en los clculos.
i n t d a s = 0. mes - 0. a o = 0:
CA PTU LO 6: SEN TEN CIA S D E C O N TR O L 131
S y s t e m , o u t . p r i n t C M e s ( # # ) : " ) : mes - L e e r . d a t o l n t );
S y s t e m , o u t . p r i n U " A o (////////): " ) : a o - L e e r . d a t o I n t ( ):
switch ( mes )
1
c a s e 1: c a s e 3: c a s e 5: c a s e 7: c a s e 8 : c a s e 1 0 : c a s e 12:
d a s - 31:
break;
c a s e 4: c a s e 6: c a s e 9: c a s e 11:
d a s - 30:
break:
c a s e 2:
// E s e l a o b i s i e s t o ?
i f ( ( a o % 4 0 ) && ( a o % 100 ! - 0 ) || ( a o % 4 0 0 - - 0))
d i a s - 29:
else
d a s - 28:
break;
default:
S y s t e m . o u t . p r i n t l n ( " \ n E l mes no e s v l i d o ):
break;
I
C uando una constante coincida con el valor de mes, se ejecutan las sentencias
especificadas a continuacin de la m ism a, siguiendo la ejecucin del progra
ma por los bloques de las siguientes clusulas case, a no ser que se tom e una
accin explcita para abandonar el bloque de la sentencia sw itch. sta es pre
cisam ente la funcin de la sentencia b re a k al final de cada bloque case.
// La c l a s e L e e r d e b e e s t a r en a l g u n a c a r p e t a d e las especificadas
// p o r l a v a r i a b l e de e n t o r n o C L A S S P A T H .
//
public class CDiasMes
I
// D i a s correspondientes a un mes de un a o da do
switch ( mes )
i
c a s e 1: // e n e r o
c a s e 3: II ma r z o
c a s e 5: II mayo
c a s e 7: II j u l i o
c a s e 8: // a g o s t o
c a s e 10: // o c t u b r e
c a s e 12: 1/ d i c i embre
d a s = 31:
break:
c a s e 4: II a b r i 1
c a s e 6: II j u n i o
c a s e 9: II s e p t i e m b r e
c a s e 11: II n o v i e m b r e
d i a s = 30:
break:
c a s e 2: II f e b r e r o
// E s e l a o b i s i e s t o ?
i f ( ( a o % 4 0 ) && ( a o % 1 00 ! = 0 ) || ( a o % TOO 0))
d a s = 29;
el se
d i a s - 28:
break;
default:
S y s t e m . o u t . p r i n t l n ( \ n E l mes no e s v l i d o " ) :
break:
1
if ( mes > = 1 && mes < = 12)
S y s t e m . o u t . p r i n t l n " \ n E l mes " + mes + " d e l a o " + a o +
tie n e + d ias + " das"):
E l que las clusulas case estn una a continuacin de otra o una debajo de
otra no es m s que una cuestin de estilo, ya que Java interpreta cada carcter
CA PTU LO 6: SEN TEN CIA S DE CO N TRO L 133
nueva lnea com o un espacio en blanco; esto es, el cdigo al que llega el com pila
dor es el m ism o en cualquier caso.
SENTENCIA while
La sentencia w hile ejecuta una sentencia, sim ple o com puesta, cero o m s veces,
dependiendo del valor de una expresin booleana. Su sintaxis es:
while ( condicin)
sentencia:
Por ejem plo, el siguiente cdigo, que podr ser incluido en cualquier aplica
cin, solicita obligatoriam ente una de las dos respuestas posibles: s/n (s o no).
char car = 1\ 0 :
try
I
S y s t e m . o u t . p r i n t t " V n D e s e a c o n t i n u a r s / n ( s o n o ) );
w h i l e ( ( c a r - ( c h a r ) S y s t e m . i n . r e a d ( ) ) ! - s ' && c a r ! = n )
i
// S a l t a r l o s c a r a c t e r e s d i s p o n i b l e s en e l f l u j o de e n t r a d a
S y s t e m . i n . s k i p ( S y s t e m . i n . a va i 1 a b l e ( ) ) ;
S y s t e m . o u t . p r i n t t " \ n D e s e a c o n t i n u a r s / n ( s o no) " ) ;
catch(IOException ignorada) (I
La diferencia de este ejem plo con respecto al anterior es que ahora la condi
cin incluye la lectura de la variable ca r, que se ejecuta prim ero p o r estar entre
parntesis. A continuacin se com para ca r con los caracteres V y V .
El siguiente ejem plo, que visualiza el cdigo A SCII de cada uno de los ca
racteres de una cadena de texto introducida por el teclado, da lugar a un bucle in
finito, porque la condicin es siem pre cierta (valor true). Para salir del bucle infi
nito tiene que pulsar las teclas Ctrl+C.
i mpor t j a v a . i o . *:
try
I
S y s t e m . o u t . p r i n t t " I n t r o d u z c a una c a d e n a de t e x t o : "):
w h i l e ( t r u e ) // c o n d i c i n s i e m p r e c i e r t a
C A PTU LO 6: SEN TEN CIA S DE CO N TRO L 135
c a r - ( c h a r ) S y s t e m . i n . r e a d ( ) : // l e e r e l s i g u i e n t e c a r c t e r
i f ( c a r ! = \ r * && c a r !=* ' \ n ' )
S y s t e m . o u t . p r i n t l n ( " E l c d i g o A S C I I de " + c a r +
" es " + ( i n t l c a r ) :
// S i no h a y d a t o s d i s p o n i b l e s , s o l i c i t a r l o s
i f ( S y s t e m . i n . a v a i 1a b l e ( ) - - 0 )
S y s t e m . o u t . p r in t t " Introduzca texto: "):
I
I
catch(IOException ignorada) II
I n t r o d u z c a una c a d e n a de t e x t o : afEntrar]
El c d i g o A S C I I de a e s 97
I n t r o d u z c a una c a d e n a d e t e x t o :
El resultado obtenido perm ite observar que el bucle w hile se est ejecutando
sin pausa m ientras hay caracteres en el flujo de entrada. C uando dicho flujo queda
vaco y se ejecuta el m todo read de nuevo, la ejecucin se detiene a la espera de
nuevos datos.
M odifiquem os ahora el ejem plo anterior con el objetivo de elim inar el bucle
infinito. Esto se puede hacer incluyendo en el w hile una condicin de term ina
cin; por ejem plo, leer datos hasta alcanzar la m arca de fin de fichero. Recuerde
que para el flujo estndar de entrada, esta m arca se produce cuando se pulsan las
teclas C trl+ D en U N IX , o bien C trl+ Z en aplicaciones W indow s de consola, y
que cuando read lee una m arca de fin de fichero, devuelve el valor -1.
1 3 6 JA V A: C U R SO DE PROGRAM A CIN
i mport j a v a . i o . * ;
catch(IOException ignorada) II
I n t r o d u z c a una c a d e n a de t e x t o .
Para t e r m i n a r p u l s e C t r l + z
hola[Entrar]
El c d i go A S C I I de h es 104
El c d i go A S C I I de 0 es 111
El c d i go A S C I I de 1 es 1 08
El c d i go A S C I I de a es 97
ad i s [ E n t r a r ]
El c d i g o A S C I I de 3 es 97
El c d i go A S C I I de d e s 100
El c d i go A S C I I de i e s 105
El c d i go A S C I I de e s 162
El c d i go A S C I I de s es 115
[ C t r l ] [z]
Bucles anidados
C uando se incluye una sentencia w h ile dentro de otra sentencia while, en general
una sentencia while, do, o f o r dentro de otra de ellas, estam os en el caso de bu
cles anidados. Por ejem plo:
CA PITU LO 6: SEN TEN CIA S DE CONT ROL 137
Para i = 1: j = 1. j - 2, j = 3. j = 4.
Para i - 2: j = 1. j - 2. j = 3. j - 4.
Para i 3: j = 1. j 2. j =3. j =4.
E ste resultado dem uestra que el bucle exterior se ejecute tres veces, y por ca
da una de stas, el bucle interior se ejecuta a su vez cuatro veces. Es as com o se
ejecutan los bucles anidados: por cada iteracin del bucle externo, el interno se
ejecuta hasta finalizar todas sus iteraciones.
O bserve tam bin que cada vez que finaliza la ejecucin de la sentencia w hile
interior, avanzam os a una nueva lnea, increm entam os el valor de i en una unidad
e iniciam os de nuevo j al valor 1.
r = x2 + y 2
l X Y
5 3 4
13 5 12
10 6 8
50 30 40
138 JA V A: C U R SO D E PROGRAM A CIN
Prim ero definim os las variables que vam os a utilizar en los clculos.
1 n t x - l . y - l . z - 0 :
z = ( i n t ) M a t h . s q r t ( x * x + y * y ) ; // z e s una v a r i a b l e e n t e r a
i f (z * z == x * x + y * y) // l a r a i z c u a d r a d a f u e e x a c t a ?
System.out. p r i n t l n t z + " \ t " + x + " \ t " + y ) :
while (x <= 5 0 )
1
// C a l c u l a r z . Como z e s un e n t e r o , a l m a c e n a
// l a p a r t e e n t e r a de l a r a z c u a d r a d a
z = (int)M ath.sqrt(x * x + y * y):
w h i l e ( y < = 5 0 && z < = 5 0 )
I
// S i l a r a i z c u a d r a d a a n t e r i o r f u e e x a c t a .
// e s c r i b i r z , x e y
i f ( z * z = = x * x + y * y )
System.out.printlnz + " \ t " + x + " \ t " + y):
CA PTU LO 6: SEN TEN CIA S DE C O N TR O L 139
y = y + 1:
z = (int)Math.sqrt(x * x + y * y);
I
x = x + l ; y = x :
)
do
s e n te n c ia -,
wh i l e ( c o n d i c i n );
Por ejem plo, el siguiente cdigo obliga al usuario a introducir un valor positivo:
d o u b l e n:
do // e j e c u t a r las sentencias siguientes
[
S y s t e m . o u t . p r i n t ( " N me r o : ):
11 = L e e r . d a t o D o u b l e ):
I
while ( n < 0 ): // m i e n t r a s n s ea me n o r q u e 0
ejecuta una estructura w h ile puede suceder que el bloque de sentencias no se eje
cute, lo que ocurrir siem pre que la condicin sea inicialm ente falsa.
rM =
abs(r ru , ) <
Prim ero definim os las variables que vam os a utilizar en los clculos.
double n; // nmer o
double aprox: // aproxi maci n a la r a z cuadrada
double antaprox: // a n t e r io r aproximacin a la r a iz cuadrada
double epsilon: // c o e f i c i e n t e de e r r o r
System.out.printt"Nmero: "):
n = L e e r . d a t o D o u b l e ( );
S y s t e m . o u t . p r i n t C R a i z cuadrada aproximada: ");
a p r o x = L e e r . d a t o D o u b l e ( );
S y s t e m . o u t . p r i n t " C o e f i c i e n t e de e r r o r : " ) ;
e p s i l o n - L e e r , d a t o D o u b l e ( ):
do
1
ant aprox = aprox:
aprox = (n/antaprox + antaprox) / 2;
1
while (Math.abstaprox - antaprox) >= e p s i l o n ) :
CA PTU LO 6: SEN TEN CIA S DE CO N TRO L 141
Al aplicar la frm ula p o r prim era vez, la variable antaprox contiene el valor
aproxim ado a la raz cuadrada que hem os introducido a travs del teclado. Pa
ra sucesivas veces, antaprox contendr la ltim a aproxim acin calculada.
do
I
System.out.print"Nmero: ):
n = L e e r . d a t o D o u b l e t ):
I
w h i 1e ( n < = 0 ):
do
I
S y s t e m . o u t . p r i n t " R a z cuadrada aproximada: ):
a p r o x = L e e r . d a t o D o u b l e ):
I
w h i 1e ( a p r o x < = 0 ):
do
I
S y s t e m . o u t . p r i n t ( " C o e f i c i e n t e de e r r o r : ");
e p s i l o n = L e e r . d a t o D o u b l e ( ):
I
while ( epsilon < = 0 );
142 JA V A: C U R SO DE PRO G R A M A CI N
do
(
antaprox - aprox:
aprox = (n/antaprox + antaprox) / 2:
I
'w hile (M a t h . a b s a p ro x - a nta p ro x) >= e p s i l o n ) :
S y s t e m . o u t . p r i n t l n " L a r a z c u a d r a d a de " + n + " es + aprox):
Nmer o: 10
Raz cuadrada aproximada: 1
C o e f i c i e n t e de e r r o r : l e - 4
La r a i z c u a d r a d a de 1 0 . 0 e s 3 . 1 6
SENTENCIA for
La sentencia fo r perm ite ejecutar una sentencia sim ple o com puesta, repetida
m ente un nm ero de veces conocido. Su sintaxis es la siguiente:
fo r ( [ v l= e l [ , v2=*e2]. . . ] ; [ c o n d i c i n ] ; [ p r o g r e s i n - c o n d i c i n ' ] )
sentencia;
v i , v2, .... representan variables de control que sern iniciadas con los valores
de las expresiones e l , e2, ...;
condicin es una expresin booleana que si se om ite, se supone verdadera;
progresin-condicin es una o m s expresiones separadas p o r com as cuyos
valores evolucionan en el sentido de que se cum pla la condicin para finalizar
la ejecucin de la sentencia for;
sentencia es una sentencia sim ple o com puesta.
2. Se evala la condicin:
a) Si el resultado es true (verdadero), se ejecuta el bloque de sentencias, se
evala la expresin que da lugar a la progresin de la condicin y se vuel
ve al punto 2.
b) Si el resultado es false (falso), la ejecucin de la sentencia fo r se da por fi
nalizada y se p asa el control a la siguiente sentencia del program a.
C A PTU LO 6: SEN TEN CIA S DE CO N TRO L 143
in t i :
f o r ( i - 1 ; i < - 100 ; i + + )
S y s t e m . o u t . p r i n t ( i + " ):
El siguiente ejem plo im prim e los m ltiplos de 7 que hay entre 7 y 112. Se
puede observar que, en este caso, la variable se ha declarado e iniciado en la pro
pia sentencia f o r (esto no se puede hacer en una sentencia w hile; las variables que
intervienen en la condicin de una sentencia w hile deben hab er sido declaradas e
iniciadas antes de que se procese la condicin p o r prim era vez).
f o r ( i n t k - 7 ; k < = 112 : k + - 7)
System .out.print(k + ') :
int f , c :
f o r ( f = 3 . c - 6 : f + c < 40 : f + + . c + = 2)
System .out.p rin tln t"f = " + f + "\t c - " + c);
E ste otro ejem plo que ve a continuacin, im prim e los valores desde 1 hasta 10
con increm entos de 0.5.
f o r ( f l o a t i - 1 : i < = 10 : i + - 0 . 5)
System .out.print(i + " ");
El siguiente ejem plo im prim e las letras del abecedario en orden inverso.
char car:
f o r ( c a r = ' z ' ; c a r >= ' a ' : c a r - - )
S y s t e m . o u t . p r i n t ( c a r + " ):
for (::)
I
s e n t e n c i as;
I
1 4 4 JA V A : C U R SO D E PRO G R A M A CI N
P o s i c i n del a lfil:
fila 3
c o l u mn a 4
B * B N B * B N
N B * B * B N B
B N B * B N B N
N B * B * B N B
B * B N B * B N
* B N B N B * B
B N B N B N B *
N B N B N B N B
Prim ero definim os las variables que vam os a utilizar en los clculos.
int f a l f i l , c a l f i l ; // p o s i c i n i n i c i a l del a l f i l
int f i l a , c o l u m n a : II p o s i c i n a c t u a l del a l f i l
// P i n t a r e l t a b l e r o de a j e d r e z
i f ( ( f i l a + c o l u mn a f a l f i l + c a l f i l ) ||
( f i l a - c o l u mn a = - f a l f i l - c a l f i l ) )
System .out.print{"* "):
e l s e i f ( ( f i l a + col umna) X 2 0)
System.out.print("B "):
el se
S y s t e m . o u t . p r i n t C N ):
// P i n t a r e l t a b l e r o de a j e d r e z
f o r ( f i l a = 1: f i l a < = 8 ; f i l a + + )
I
for ( c o l u m n a = 1; c o l u mn a < = 8 ; columna++)
1
if ( ( f i l a + c o l u mn a = = f a l f i l + c a l f i l ) ||
( f i l a - col umna = = f a l f i l - c a l f i l ) )
System.out.p r i n t ( " * ");
e l s e i f ( ( f i l a + col umna) % 2 = 0)
System.out.print"B ");
el se
System.out.print("N ");
I
S y s t e m . o u t . p r i n t l n ); II c a m b i a r de f i l a
1 4 6 JA V A: C U R SO DE PRO G R A M A CI N
SENTENCIA break
while ( y <= 5 0 )
I
// S i l a r a i z c u a d r a d a anterior fue exacta.
// e s c r i b i r z . x e y
if ( z * z = = x * x + y * y )
System.out.printlnCz + "\t" + x + "\t" + y):
y - y + 1:
z - ( int)Math.sqrt(x * x + y * y):
del b u c l e
SENTENCIA continu
La sentencia con tinu obliga a ejecutar la siguiente iteracin del bucle while, do,
0 for, en el que est contenida. Su sintaxis es:
continu:
C om o ejem plo, vea la siguiente aplicacin que im prim e todos los nm eros
entre 1 y 100 q ue son m ltiplos de 5.
Ejecute este program a y observe que cada vez que se ejecuta la sentencia co n
tinu, se inicia la ejecucin del bloque de sentencias de fo r para un nuevo valor
de n.
ETIQUETAS
C on las sentencias b re a k y con tin u se puede tam bin utilizar una etiqueta para
indicar dnde se debe reanudar la ejecucin (quiero advertir que el uso de etique
tas es una m ala prctica en program acin, p o r lo que debe reducirse a casos ex
cepcionales). Segn lo explicado anteriorm ente, cuando se utiliza b re a k en bucles
anidados, perm ite finalizar la ejecucin del bucle donde est incluida, continuan
do la ejecucin en el bucle exterior m s cercano; y continu, inicia una nueva ite
racin del bucle donde est incluida. P ues bien, utilizando una etiqueta con b re a k
o con con tin u se puede reanudar la ejecucin en un bucle m s externo. La eti
queta, finalizada con dos puntos, d eb e escribirse ju sto antes de la sentencia while,
do, o for. P o r ejem plo:
salir:
f o r ( x - 1 : x < - 5 ; x + + )
I
f o r ( y = 1 : y < - 5 ; y + + )
I
f o r ( z = 1 ; z < - 5 : z + + )
I
i f ( ( x * y + z ) % 11 = 0 )
1
S y s t e m . o u t . p r i n t l n t x + " * " + y + " + " + z +
" e s m l t i p l o d e 11 ) ;
b r e a k salir:
I
I
I
I
S y s t e m . o u t . p r i n t l n t " C o n t i n a l a e j e c u c i n " ) ;
2 3+5
* e s m l t i p l o d e 11
C o n t i n a l a e j e c u c i n
2 * 3 + 5 es ml t i p i o de 11
3 * 2 + 5 es ml t i pl 0 de 11
4 * 2 + 3 es ml t i pl 0 de 11
5 * 2 + 1 es ml t i p i o de 11
C o n t i l l a 1a ejecucin
Los resultados m ostrados indican que ahora, cada vez que se cum ple la condi
cin. con tinu hace que se reanude la ejecucin para la siguiente iteracin del bu
cle m s externo (para el siguiente valor de x).
La inform acin dada por el m ensaje anterior, adem s del tipo de excepcin,
especifica que ha ocurrido una divisin por cero en la lnea 9 del m todo m a in de
la clase Test.
S y s t e m . o u t . p r i n t l n C S e i n i c i a l a a p l i c a c i n ):
datol++;
d a t o 3 = d a t o l / d a t o 2:
dato2++:
II O t r a s s e n t e n c ia s
S y s t e m . o u t .p rin t ln ( d a t o l + + dato2 + + dato3);
I
CA PTU LO 6: SEN TEN CIA S DE C O N TR O L 149
Se i n i c i a l a a p l i c a c i n
E r r o r : / by z e r o
1 0 1
EJERCICIOS RESUELTOS
1. R ealizar un program a que calcule las races de la ecuacin:
ax2 + bx + c = O
1 5 0 JA V A: C U R S O DE PROGRAM A CIN
- b j b 2 - 4 ac
x + yj, * - yj
Indicar con literales apropiados los datos a introducir, as com o los resultados
obtenidos.
Prim ero definim os las variables que vam os a utilizar en los clculos.
double a. b. c : // c o e f i c i e n t e s de l a e c u a c i n
double d; II discriminante
double r e . i m; // p a r t e r e a l e i m a g i n a r i a de l a r a z
System.out.print"a =" ) ; a = L e e r . d a t o D o u b l e ( );
System.out.print"b - "): b = L e e r . d a t o O o u b l e ):
System.out.print"c = "): c = L e e r . d a t o D o u b l e ):
If (a 0 && b 0)
System.out.printlnCLa e c u a c i n e s d e g e n e r a d a " );
el se i f (a - - 0)
System.out.printlnCLa nica raz es: " + -c/b):
else
I
// E v a l u a r l a frmula. C l c u l o de d. r e e im
C A PTU LO 6: SEN TEN CIA S DE C O N TR O L 151
if (d > - 0)
I
// Imprimir las races reales
I
el s e
I
// I mprimir las races complejas conjugadas
b -Jb : - 4 a c
C lculo d e --------
2a la
^ re im
re - -b / (2 * a ) :
d - b * b - 4 * a * c :
im - M a t h . s q r t ( M a t h . a b s ( d ) ) / ( 2 * a);
S y s t e m . o u t . p r i n t l n " R a c e s r e a l e s : ):
S y s t e m . o u t . p r i n t l n ( ( r e + i m ) + , " + ( r e - i m) ) :
S y s t e m . o u t . p r i n t l n " C o e f i c i e n t e s a, b y c de l a e c u a c i n : ):
System.out.printa = ) : a = L e e r . d a t o D o u b l e ( ):
System.out.p r i n t b = ) ; b = L e e r . d a t o D o u b l e ( ):
System.out.print"c = " ) ; c = L e e r . d a t o D o u b l e ( ):
152 JA V A: C U R SO DF. PROGRAM A CIN
S y s t e m . o u t . p r i n t l n );
if ( a - 0 && b 0)
S y s t e m . o u t . p r i n t l n ( " L a e c u a c i n es d e g e n e r a d a " ) :
e l s e i f ( a = = 0)
S y s t e m . o u t . p r i n t l n La n i c a r a i z e s : " + - c / b ):
el s e
I
re - -b / ( 2 * a) ;
d - b * b - 4 * a * c ;
im = M a t h . s q r t ( M a t h . a b s d ) ) / (2 * a):
if (d > = 0 )
I
System.out.printlni"Races rea les:");
System .out.p rin tln ((re +im ) + ". " + (re-im)):
1
el se
1
S y s t e m . o u t . p r i n t l n i " R a l c e s c o m p l e j a s : );
S y s t e m . o u t .p r i n t l n i re + " + " + M a t h . a b s ( i m ) + " j );
System .out.p rin tln re + " - " + Math.absim) + j"):
I
I
Nmer o d e p a l a b r a s con 4 v o c a l e s d i s t i n t a s : 3
i n t np = 0 : // n me r o de p a l a b r a s c o n 4 v o c a l e s distintas
i n t a = 0 . e = 0 . i = 0. o = 0. u 0:
char car:
fi n a l char eof = ( c h a r )-1:
C A P T U L O 6: SEN TEN CIA S DE C O N T R O L 15 3
S y s t e m . o u t . p r i n t l n C I n t r o d u c i r texto. " +
"Para f i n a l i z a r puls ar C t r l + z . \ n " ) :
while ( ( c a r = ( c h a r ) S y s t e m . i n . r e a d ( )) ! - eof)
I
/*
S i e l c a r c t e r l e d o e s una ' a ' h a c e r a - 1
S i e l c a r c t e r l e d o e s una ' e ' h a c e r e - 1
S i e l c a r c t e r l e d o e s una ' i ' h a c e r i - 1
S i e l c a r c t e r l e d o e s una o h a c e r o - 1
S i e l c a r c t e r l e i d o e s una u ' h a c e r u - 1
S i e l c a r c t e r l e i d o e s un e s p a c i o en b l a n c o .
un \ t o un \ n , a c a b a mo s d e l e e r una p a l a b r a . E n t o n c e s .
s i a + e + i + o + u > = 4 . i n c r e m e n t a r e l c o n t a d o r de p a l a b r a s
de c u a t r o v o c a l e s d i f e r e n t e s y p o n e r a. e. i . o y u de
nuevo a c e r o .
*/
I // fin del while
if ( ( a + e + i + o + u ) >-4) np++;
i mpor t j a v a . i o . * :
// L e e r . c l a s s d e b e e s t a r en l a c a r p e t a especificada p o r CLASSPATH
//
public class CPalabras
I
// C o n t a r el n me r o de p a l a b r a s en un t e x t o
II c o n 4 o ms v o c a l e s d i f e r e n t e s
public s t a t i c void m a i n ( S t r i n g [] args)
I
i n t np - 0 : // n me r o d e p a l a b r a s c o n 4 v o c a l e s d i s t i n t a s
i n t a = 0. e - 0. i = 0. o = 0 , u = 0:
char car;
fi nal char eof = ( c h a r ) - l:
1 5 4 JA V A: C U R S O D E PRO G R A M A CI N
try
I
S y s te m . o u t .p rin tln ( " I n tr o d u c ir texto. " +
" P a r a f i n a l i z a r p u l s a r C t r l + z . \ n " );
w h i l e ( ( c a r = ( c h a r ) S y s t e m . i n . r e a d ( )) != eo f)
switch (car)
ii
c a s e A : case ' a : c a s e ' :
a = 1:
break:
case ' E ' : case e' : case ' ' :
e = 1:
break;
case ' I ' : case i ' : case ' i ':
i = 1:
break:
c a s e O : c a s e ' o ' : c a s e ' :
o = l:
break:
c a s e U : c a s e u' : c a s e :
u = 1:
break:
default:
i f ( c a r ' )
1
i f ( ( a + e + i + o + u) >
a - e = i - 0
D
II
o
c
r
if (car \ n ' )
i f ( ( a + e + i + 0 + u) >
a = e = i = 0 - u = 0:
I // f i n d e l s w i t c h
) // f i n d e l w h i l e
i f ( (a + e + i + o + u) >= 4 ) np++:
S y s t e m . o u t . p r i n t l n " \ n \ n N m e r o de p a l a b r a s c o n +
"4 v o c a l e s d i s t i n t a s : " + np);
I
catch(lOException ignorada) I)
1
I
i mport j a v a . i o . * ;
// L e e r . c l a s s debe e s t a r en l a c a r p e t a especificada p o r CLASSPATH
II
public cla ss CContarPalabras
I
// C o n t a r c a r a c t e r e s , p a l a b r a s y l n e a s en un t e x t o
public s t a t ic void m ain(S tring [] args)
I
final char eof = ( c h a r ) - l;
char car:
bo o l e a n pal abr a = f a l s e :
i n t n c a r a c t e r e s = 0, n p a l a b r a s = 0. n l i n e a s = 0:
try
I
S y s te m . o u t .p rin tln ( " Intr o d u cir texto. +
" P u l s e [ E n t r a r ] d e s p u s de c a d a l i n e a . " ) :
System.out.println"Para f i n a li z a r pulsar C t r l + z . \ n "):
while ( ( c a r = ( c h a r ) S y s t e m . i n .r e a d ( )) != eof)
I
// [ E n t r a r ] = C R L F = \ r \ n
i f ( c a r = = * \ r ) c o n t i n u : // l e s i g u e un \ n
ncaracteres++; // c o n t a d o r de c a r a c t e r e s
II E l i m i n a r b l a n c o s , t a b u l a d o r e s y f i n a l e s de l i n e a
II e n t r e p a l a b r a s
i f ( c a r = ' || c a r \ n || c a r = = \ t )
palabra = false:
e l s e i f ( p a l a b r a ) // c o m i e n z a una p a l a b r a
I
npalabras++; // c o n t a d o r de p a l a b r a s
palabra = true:
I
if (car == ' \ n ' ) II f i n a l i z a una l i n e a
nlineas++: // c o n t a d o r de l i n e a s
I
S y s t e m . o u t . p r i n t l n ! ):
1 5 6 JA V A: C U R SO DE PRO G R A M A CI N
n i i n e a s ) ;
I
catchIOException ignorada) II
1. s uma r
2. r e s t a r
3. m u l t i p l i c a r
4. d i v i d i r
5. s a l i r
S e l e c c i o n e la o pera ci n deseada: 3
D a t o 1: 2 . S
D a t o 2: 10
Resultado - 25.0
P u l s e [ E n t r a r ] para c o n t i n u a r
Prim ero definim os las variables y los prototipos de las funciones que van a
intervenir en el program a.
d o u b l e d a t o l = 0. d a t o 2 = 0 . resultado - 0:
i n t o p e r a c i n = 0:
o p e r a c i n = m e n ( ):
static i n t men()
I
i n t op:
do
I
S y s t e m . o u t . p r i n t l n ( " N t l . s u m a r ):
C A P TULO 6: SEN TEN CIA S DE C O N T R O L 157
if (operacin ! = 5)
I
// L e e r d a t o s
System.out.print"Dato 1: ); d a t o l = L e e r . d a t o D o u b l e ( ):
System.out.printCDato 2: "); d a t o 2 = L e e r . d a t o D o u b l e ( ):
// R e a l i z a r la operacin
I
el s e
break; // s a l i r
switch (operacin)
[
c a s e 1:
resultado = datol + dato2:
break;
c a s e 2:
r e s u l t a d o = d a t o l - dato2:
break:
c a s e 3:
r e s u l t a d o = d at o l * dato2;
break:
c a s e 4:
r e s u l t a d o = da to l / dato2;
break:
I
// E s c r i b i r e l r e s u l t a d o
System.out.printlni"Resultado = " + resultado):
// H a c e r una p a u s a
S y s t e m . o u t . p r i n t l n i " P u l se [ E n t r a r ] para c o n t i n u a r " ) ;
S y s t e m . i n . r e a d ):
158 JA VA: C U R SO DE PRO G R A M A CI N
Las operaciones descritas form arn parte de un bucle infinito form ado p o r una
sentencia w h ile con el fin de poder encadenar distintas operaciones.
while (true)
I
// s e n t e n c i a s
i mpor t j a v a . i o . * ;
// L e e r . c l a s s d e b e e s t a r en l a carpeta especificada p o r CLASSPATH
//
public class CCalculadora
I
// S i m u l a c i n de una c a l c u l a d o r a
s t a t i c i n t men()
1
int op:
do
I
S y s t e m . o u t . p r i n t l n ( " \ t l . s u m a r " );
S y s t e m . o u t . p r i n t l n " \ t 2. r e s t a r " ) :
S y s t e m . o u t . p r i n t l n " \ t 3 . m u t i p l i c a r " );
S y s t e m . o u t . p r i n t l n " \ t 4 . d i v i d i r ):
System.out.println("\t5. sa lir"):
S y s t e m . o u t .p r i n t "\nSeleccione la operacin deseada: "):
op - L e e r . d a t o l n t ):
1
while ( o p < 1 || o p > 5 ) :
r e t u r n op:
try
I
while (true)
I
o p e r a c i n = m e n );
i f ( o p e r a c i n ! - S)
I
// L e e r d a t o s
S y s t e m . o u t . p r i n t " D a t o 1: '): d a t o l - L e e r . d a t o D o u b l e ( ):
S y s t e m . o u t . p r i n t " D a t o 2: ); d a t o 2 = L e e r . d a t o D o u b l e ( ):
C A P T U L O 6: SEN TEN CIA S D E C O N T R O L 159
/ / L i m p i a r e l b u f f e r d e l f l u j o d e e n t r a d a
S y s t e m . i n . s k i p ( S y s t e m . i n . a v a i 1 a b l e ( ) ) ;
// R e a l i z a r l a o p e r a c i n
switch (operacin)
I
c a s e 1:
resultado = datol + dato2:
break;
c a s e 2:
resultado = datol - dato2;
break;
c a s e 3:
resultado = datol * dato2:
break;
c a s e 4:
resultado = datol / dato2;
break;
I
// E s c r i b i r e l r e s u l t a d o
System.out.println"Resultado - * + resultado):
// H a c e r una p a u s a
S y s t e m . o u t . p r i n t l n " P u l se [ E n t r a r ] para c o n t i n u a r " ) ;
S y s t e m . i n . r e a d );
// L i m p i a r e l b u f f e r d e l f l u j o de e n t r a d a
S y s t e m . i n . s k i p ( S y s t e m . i n . a va i 1 a b l e ( ) ) ;
I
el se
break;
catchIOException ignorada) II
EJERCICIOS PROPUESTOS
1. R ealizar un program a que calcule e im prim a la sum a de los m ltiplos de 5 com
prendidos entre dos valores a y b. El program a no perm itir introducir valores ne
gativos para a y b, y verificar que a es m enor que b. Si a es m ayor que b, inter
cam biar estos valores.
da d e l m es de axo
1
2 3 2
3 4 5 4 3
4 5 6 7 6 5 4
5 6 7 8 9 8 7 6 5
6 7 8 9 0 1 0 9 8 7 6
7 8 9 0 1 2 3 2 1 0 9 8 7
8 9 0 1 2 3 4 S 4 3 2 1 0 9 8
9 0 1 2 3 4 5 6 7 6 5 4 3 2 1 0 9
1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1
3 4 5 6 7 8 9 0 1 0 9 8 / 6 5 4 3
2 3 ...........................................................................
6. Un centro num rico es un nm ero que separa una lista de nm eros enteros
(com enzando en 1) en dos grupos de nm eros, cuyas sum as son iguales. El prim er
centro num rico es el 6, el cual separa la lista (1 a 8) en los grupos: (1, 2, 3, 4, 5)
CA PTU LO 6: SEN TEN CIA S DE C O N TR O L 161
y (7, 8) cu y as sum as son am bas iguales a 15. El segundo centro num rico es el 35,
el cual separa la lista (1 a 49) en los grupos: (1 a 34) y (36 a 49) cuyas sum as son
am bas iguales a 595. E scribir un program a que calcule los centros num ricos en
tre 1 y n.
7. R ealizar un program a que solicite un texto (suponer que los caracteres que form an
el texto son slo letras, espacios en blanco, com as y el punto com o final del texto)
y a continuacin lo escriba m odificado de form a que, a la A le corresponda la K, a
la B la L, ... , a la O la Y, a la P la Z, a la Q la A , ... y a la Z la J, e igual para las
letras m insculas. S uponga que la entrada no excede de una lnea y que finaliza
con un punto.
Al realizar este program a tenga en cuenta que el tipo c h a r es un tipo entero, por
lo tanto las afirm aciones en los ejem plos siguientes son correctas:
MATRICES
H asta ahora slo hem os tenido que trabajar con algunas variables en cada uno de
los program as que hem os realizado. Sin em bargo, en m s de una ocasin tendre
m os que m anipular conjuntos m s grandes de valores. P or ejem plo, p ara calcular
la tem peratura m edia del m es de agosto necesitarem os conocer los 31 valores c o
rrespondientes a la tem peratura m edia de cada da. En este caso, podram os utili
zar una variable para introducir los 31 valores, uno cada vez, y acum ular la suma
en otra variable. Pero qu ocurrir con los valores que vayam os introduciendo?
que cuando tecleem os el segundo valor, el prim ero se perder; cuando tecleem os
el tercero, el segundo se perder, y as sucesivam ente. C uando hayam os introdu
cido todos los valores podrem os calcular la m edia, pero las tem peraturas corres
pondientes a cada da se habrn perdido. Q u podram os hacer para alm acenar
todos esos valores? Pues, podram os utilizar 31 variables diferentes; pero qu pa
sara si fueran 100 o m s valores los que tuviram os que registrar? A dem s de ser
muy laborioso el definir cada una de las variables, el cdigo se vera enorm e
m ente increm entado.
matriz m
i i i i i i i i i
En general, la representacin de las m atrices se hace m ediante variables sus
critas o de subndices y pueden tener una o varias dim ensiones (subndices). A las
m atrices de una dim ensin se les llam a tam bin listas y a los de dos dim ensiones,
tablas.
v = [a 0 , a , , a 2,
00 ()\ a 02 a oj a,0/1
a i0 a il a !2 ax
m-
P o r ejem plo, supongam os que tenem os una m atriz unidim ensional de enteros
llam ada m, la cual contiene 10 elem entos. Estos elem entos se identificarn de la
siguiente forma:
matriz m
A
O bserve que los subndices son enteros consecutivos, y que el p rim er subndi
ce vale 0. Un subndice puede ser cualquier expresin entera positiva.
CA PITU LO 7: M A TRICES I65
A s m ism o, una m atriz de dos dim ensiones se representa m ediante una varia
ble con dos subndices (filas, colum nas); una m atriz de tres dim ensiones se repre
senta m ediante una variable con tres subndices etc. El nm ero m xim o de
dim ensiones o el nm ero m xim o de elem entos, dentro de los lm ites establecidos
por el com pilador, para una m atriz depende de la m em oria disponible.
En Java, cada elem ento de una m atriz unidim ensional es de un tipo prim itivo,
o bien una referencia a un objeto; y cada elem ento de una m atriz m ultidim ensio-
nal es, a su vez, una referencia a otra m atriz. A continuacin se estudia todo esto
detalladam ente.
Para crear y utilizar una m atriz hay que realizar tres operaciones: declararla,
crearla e iniciarla.
t ' p o [ ] nombre;
tipo n o m b r e l ] ;
donde tip o indica el tipo de los elem entos de la m atriz, que pueden ser de cual
quier tipo prim itivo o referenciado; y nom bre es un identificador que nom bra a la
m atriz. Los corchetes m odifican la definicin norm al del identificador para que
sea interpretado por el com pilador com o una m atriz.
i n t [ ] m:
f l o a t [ ] temperatura:
COrdenador[] ordenador: // C O r d e n a d o r e s una c l a s e d e o b j e t o s
1 6 6 JA V A: C U R SO D E PROGRAM A CIN
L a prim era lnea declara una m atriz de elem entos de tipo in t; la segunda, una
m atriz de elem entos de tipo flo at; y la tercera una m atriz de objetos C O rdenador.
i n t m [ ] :
f l o a t t e mp e r a t u r a [ ] :
COrdenador o r d e n a d o r [ ] // C O r d e n a d o r e s una c l a s e de o b j e t o s
donde nom bre es el nom bre de la m atriz previam ente declarada; tipo es el tipo de
los elem entos de la m atriz; y tam ao es una expresin entera positiva m enor o
igual que la precisin de un int, que especifica el nm ero de elem entos.
El hecho de utilizar el operador n ew significa que Java im plem ento las m atri
ces com o objetos, por lo tanto sern tratadas com o cualquier otro objeto.
Las siguientes lneas de cdigo crean las m atrices declaradas en el ejem plo
anterior:
m - n e w i n t [ 1 0 ] :
t e m p e r a t u r a = n e w f 1 o a t [ 3 1 3 :
o r d e n a d o r = n e w C 0 r d e n a d o r [ 2 5 ] ;
La prim era lnea crea una m atriz identificada p o r m con 10 elem entos de tipo
in t; es decir, puede alm acenar 10 valores enteros; el p rim er elem ento es m [0] (se
lee: m sub-cero), el segundo m i l ] , ..., y el ltim o m [9]. L a segunda crea una m a
triz tem peratura de 31 elem entos de tipo flo at. Y la tercera crea una m atriz orde
n a d o r de 25 elem entos, cada uno de los cuales puede referenciar a un objeto
C O rdenador. U na m atriz de objetos es una m atriz de referencias a dichos objetos.
CA PTU LO 7: M A TRICES 167
Es bastante com n declarar y crear la m atriz en una m ism a lnea. E sto puede
hacerse as:
tipoli n o m b r e = new t i p o t a m a o ] ;
tipo n o m b r e n - new t i po [t a m a o ] ;
i n t [ ] m = new i n t [ 1 0 ] :
f l o a t [ ] t e m p e r a t u r a - new f l o a t [ 3 1 ] ;
C O r d e n a d o r [ ] o r d e n a d o r = new C 0 r d e n a d o r [ 2 5 ] :
C uando se crea una m atriz, el tam ao de la m ism a puede ser tam bin especi
ficado durante la ejecucin a travs de una variable a la que se asignar com o va
lor el nm ero de elem entos requeridos. Por ejem plo, la ltim a lnea de cdigo del
ejem plo siguiente crea una m atriz con el nm ero de elem entos especificados por
la variable n E lem entos:
i n t nElementos:
S y s t e m . o u t . p r i n t " N m e r o d e e l e m e n t o s de l a m a t r i z : "):
n E l e m e n t o s = L e e r . d a t o l n t );
i n t [ ] m = new i n t [ n E l e m e n t o s ] ;
Si deseam os iniciar una m atriz con otros valores diferentes a los predeterm i
nados, podem os hacerlo de la siguiente form a:
E l ejem plo anterior crea una m atriz tem peratura de tipo float con tantos ele
m entos com o valores se hayan especificado entre llaves.
Para acceder al valor de un elem ento de una m atriz se utiliza el nom bre de la m a
triz, seguido de un subndice entre corchetes. Esto es, un elem ento de una m atriz
168 JA VA : C U R S O DE PROGRAM A CIN
i n t [ ] m = new i n t [ 1 0 0 ] :
int k = 0 . a = 0 :
11...
a - m [ 1] + m [ 9 9 ] ;
k = 50:
m[ k]++;
m [k+l] = m [k];
O bserve que para referenciar un elem ento de una m atriz se puede em plear
com o subndice una constante, una variable o una expresin de tipo entero. El
subndice especifica la posicin del elem ento dentro de la m atriz. La prim era po
sicin es la 0.
Si se intenta acceder a un elem ento con un subndice m enor que cero o m ayor
que el nm ero de elem entos de la m atriz m enos uno, Java lanzar una excepcin
de tipo A r r a y ln d e x O u tO fB o u n d s E x c e p t io n . indicando que el subndice est
fuera de los lm ites establecidos cuando se cre la m atriz. Por ejem plo, cuando se
ejecute la ltim a lnea de cdigo del ejem plo siguiente Java lanzar una excep
cin, puesto que intenta asignar el valor del elem ento de subndice 99 al elem ento
de subndice 100, que est fuera del rango 0 a 99 vlido.
i n t [ ] m = new i n t [ 1 0 0 ] ;
i n t k = 0 . a = 0 :
11...
k - 99:
m [k + l] = m [k ]:
int n = m.length; // n me r o de e l e m e n t o s de l a m a t r i z n
Por ejem plo, el cdigo expuesto a continuacin crea una m atriz m 2 que es una
copia de o tra m atriz existente m i. D espus pregunta si m i es igual a m 2\ el resul
tado ser false puesto que m i y m 2 se refieren a m atrices diferentes.
i n t [ ] mi = 110. 2 0 , 3 0 . 4 0 . 5 0 1 :
i n t [ ] m2 = ( i n t [ ] ) m l . e l o n e ( ) ; // m2 e s un a c o p i a de mi
i f ( m i . e q u a l s m 2 ) ) // e q u i v a l e a: i f (mi = m2)
S y s t e m . o u t . p r i n t l n ( " m i y m2 s e r e f i e r e n a l a misma m a t r i z " ) :
el se
S y s t e m . o u t . p r i n t l n " m i y m2 s e r e f i e r e n a m a t r i c e s d i f e r e n t e s " ) :
Nmero de e l e m e n t o s d e l a m a t r i z : 10
I n t r o d u c i r l o s v a l o r e s de l a m a t r i z .
m [0]= 1
m[1 ] - 2
m [2]- 3
1 23 . . .
F i n del proceso.
Para ello, en prim er lugar definim os la variable nE lem entos para fijar el n
m ero de elem entos de la m atriz, cream os la m atriz m con ese nm ero de elem en
tos y definim os el subndice i para acceder a los elem entos de dicha matriz.
in t nElementos:
n E l e m e n t o s = L e e r . d a t o l n t ):
i n t [ ] m = new i n t f n E l e m e n t o s ] : // c r e a r la m atriz m
i n t i - 0 : // s u b n d i c e
// L e e r . c l a s s d e b e e s t a r en l a c a r p e t a especificada p o r C LA S S P A T H
p u b lic c la s s CMatrizUnidim ensional
I
// C r e a c i n d e una m a t r i z u n i d i m e n s i o n a l
public s t a t ic void m a in (S trin g [] args)
(
i n t nElementos:
S y s t e m . o u t . p r i n t ( " N m e r o de e l e m e n t o s de l a m a t r i z : " ) :
n E l e m e n t o s - L e e r , d a t o I n t ( );
i n t [ ] m = new i n t [ n E l e m e n t o s ] ; // c r e a r l a m a t r i z m
in t i = 0 ; / / subndice
// V i s u a l i z a r l o s e l e m e n t o s de l a m atriz
S y s t e m . o u t . p r i n t l n t );
f o r (i = 0: i < nElementos: i++)
System.out.p r i nt(m[i ] + " ");
System .out.p r i n t l n ( " \ n \ n F in del proceso.'
int nAlumnos; // n me r o de a l u m n o s
do
I
S y s t e m . o u t . p r i n t " N m e r o de a l u m n o s : "):
n A l u m n o s = L e e r . d a t o l n t );
I
w h i le (nAlumnos < 1);
f 1o a t C ] n o t a = new f 1o a t t n A l u m n o s ] : // c r e a r l a m a t r i z nota
i n t i - 0: // s u b n d i c e
f l o a t suma = 0 F ; // suma t o t a l de l a s n o t a s m e d i a s
El paso siguiente ser alm acenar en la m atriz las notas introducidas a travs
del teclado.
f o r ( i - 0; i < n o t a . l e n g t h : i++)
suma + - n o t a [ i ] :
S y s te m .o u t .p r in tln ("\n\nNota media de l curso: " + suma / n A l u m n o s ) :
// L e e r . c l a s s d e b e e s t a r en l a c a r p e t a especificada p o r C LA S S P A T H
pu blic c la s s CMatrizUnidim ensional
I
// T r a b a j a r c o n una m a t r i z u n i d i m e n s i o n a l
pu b lic s t a t ic void m a in (S trin g [] args)
I
int nAlumnos: // n me r o de a l u m n o s ( v a l o r no n e g a t i v o )
do
1
S y s t e m . o u t . p r i n t " N m e r o de a l u m n o s : "):
n A l u m n o s = L e e r . d a t o l n t ( ):
I
w hile (nAlumnos < 1);
f 1o a t [ ] n o t a = new f l o a t [ n A l u m n o s ] ; // c r e a r l a m a t r i z n o t a
int i = 0 ; // s u b n d i c e
f l o a t suma = 0 F : // suma t o t a l d e l a s n o t a s m e d i a s
S y s t e m . o u t . p r i n t n ( " I n t r o d u c i r l a s n o t a s medias del c u r s o . " ) :
17 2 JA V A: C U R S O DE PROGRAM A CIN
// S u m a r l a s n o t a s m e d i a s
f o r ( i = 0; i < n o t a . l e n g t h : i++)
suma + = n o t a [ i ] :
// V i s u a l i z a r l a n o t a m e d i a d e l c u r s o
S y s t e m . o u t . p r i n t l n " \ n \ n N o t a media del c u r s o : + suma / nA l umn o s ) :
1
I
Matrices asociativas
C uando el ndice de una m atriz se corresponde con un dato, se dice que la m atriz
es asociativa (por ejem plo, una m atriz d(asM es[13) que alm acene en el elem ento
de ndice 1 los das del m es 1, en el de ndice 2 los das del m es 2 y as sucesiva
m ente; ignoram os el elem ento de ndice 0). En estos casos, la solucin del pro
blem a resultar m s fcil si utilizam os esa coincidencia. P or ejem plo, vam os a
realizar un program a que cuente el nm ero de veces que aparece cada una de las
letras de un texto introducido por el teclado y a continuacin im prim a el resulta
do. Para hacer el ejem plo sencillo, vam os a suponer que el texto slo contiene le
tras m insculas del alfabeto ingls (no hay ni letras acentuadas, ni la 11, ni la ).
La solucin podra ser de la form a siguiente:
I n t r o d u c i r un t e x t o .
Para f i n a l i z a r p u l s a r [Ctrl]fz]
a b c d e f g h i j k l m n o p q r s t u v w x y z
9 1 1 3 5 0 0 0 9 0 0 6 4 6 3 0 0 1 II 2 2 0 0 0 1 1
C A PTU LO 7: MATRICES 173
da com o resultado 26. R ecuerde que cada carcter tiene asociado un valor entero
(cdigo A SC II) que es el que utiliza la m quina internam ente para m anipularlo.
A s p o r ejem plo la z tiene asociado el entero 122. la V el 97. etc. Segn esto, la
evaluacin de la expresin a n te rio re s: 122 - 97 + 1 = 2 6 .
i n t [ ] c - new i n t [ 2 5 6 ] : // l a t a b l a A S C I I t i e n e 2 5 6 c a r a c t e r e s
char car - ' a ' : // c a r t i e n e a s i g n a d o e l e n t e r o 9 7
c [ * a *] - 10:
c[car] = 10:
c a r = ( c h a r ) S y s t e m . i n . r e a d ( ):
c[car]++:
Pero qu pasa con los elem entos c0] a c [ 9 6 ] l Segn hem os planteado el
problem a inicial quedaran sin utilizar (el enunciado deca: con qu frecuencia
aparecen los caracteres de la 'a ' a la 'z')- Esto, aunque no presenta ningn pro
blem a. se puede evitar as:
Para ca r igual a a ' se tratara del elem ento c[0] y para ca r igual a 'z ' se trata
ra del elem ento c[25J. D e esta form a podem os definir una m atriz de enteros ju s
tam ente con un nm ero de elem entos igual al nm ero de caracteres de la 'a ' a la
Y (26 caracteres segn la tabla ASCII). El prim er elem ento ser el contador de
'a ', el segundo el de b \ y a s sucesivam ente.
Un contador es una variable que inicialm ente vale cero (suponiendo que la
cuenta em pieza desde uno) y que despus se increm enta en una unidad cada vez
que ocurre el suceso que se desea contar.
i mpor t j a v a . i o . * ;
// L e e r . c l a s s d e b e e s t a r en l a c a r p e t a especificada p o r CLASSPATH
public class CMatrizAsociativa
I
// F r e c u e n c i a con la que a p a r e c e n l a s l e t r a s en un t e x t o ,
public static void m a in(S tring [] args)
I
// C r e a r l a m a t r i z c c o n z ' - ' a ' + l e l e m e n t o s .
// J a v a i n i c i a l o s e l e m e n t o s de l a m a t r i z a c e r o ,
i n t [ ] c = new i n t [ ' z - a + l ] ;
c h a r c a r : // s u b n d i c e
f i n a l char eof = ( c h a r ) - l ;
// E n t r a d a de d a t o s y c l c u l o de l a t a b l a de f r e c u e n c i a s
S y s t e m . o u t . p r i n t l n ( " I n t r o d u c i r un t e x t o . ):
S y s t e m . o u t . p r i n t l n ( P a r a f i n a l i z a r p u l s a r [ C t r l ] [ z ] \ n " );
try
I
// L e e r e l s i g u i e n t e c a r c t e r d e l t e x t o y c o n t a b i l i z a r l o
while (( c a r = ( c h a r ) S y s t e m . i n . r e a d ( )) != eof)
I
// S i el c a r c t e r l e d o e s t e n t r e l a a y la z '
// i n c r e m e n t a r e l c o n t a d o r c o r r e s p o n d i e n t e
i f ( c a r >= ' a && c a r < = z' )
c[car - 'a']++:
c a t c h ( I O E x c e p t i o n i g n o r a d a ) I)
// M o s t r a r l a t a b l a de f r e c u e n c i a s
S y s t e m . o u t . p r i n t l n " \ n " );
// V i s u a l i z a r una c a b e c e r a " a b e . . . "
f o r ( c a r = ' a ' : c a r < = z ' : c a r + + )
System .out.print" " + car):
S y s t e m . o u t . p r i n t l n " \ n ................................................................... +
" "):
CA PTU LO 7: M A TRICES 175
CADENAS DE CARACTERES
L as cadenas de caracteres en Java son objetos de la clase S tr in g . C uando expusi
mos los literales en el captulo 3 vim os que cada vez que en un program a se utili
za un literal de caracteres, Java crea de form a autom tica un objeto S t r in g con el
v alor del literal. Por ejem plo, la lnea de cdigo siguiente visualiza el literal Fin
del proceso., para lo cual. Java previam ente lo convierte en un objeto S trin g :
B sicam ente, una cadena de caracteres se alm acena com o una m atriz unidi
m ensional de elem entos de tipo c h a r:
char[] c a d e n a = new c h a r f l O ] ;
Igual q ue suceda con las m atrices num ricas, una m atriz unidim ensional de
caracteres puede ser iniciada en el m om ento de su definicin. Por ejem plo:
Este ejem plo define cadena com o una m atriz de caracteres con cuatro ele
m entos (cadenafO J a cadena[3]) y asigna al prim er elem ento el carcter a , al
segundo el carcter b \ al tercero el carcter c y al cuarto el carcter d \
Puesto que cada carcter es un entero, el ejem plo anterior podra escribirse
tam bin as:
C ada carcter tiene asociado un entero entre 0 y 65535 (cdigo U nicode). Por
ejem plo, a la 'a ' le corresponde el valor 97, a la 7 / el valor 98, etc. (recuerde que
los prim eros 128 cdigos U nicode coinciden con los prim eros 128 cdigos ASCII
y A NSI: captulo 3, tipo c h a r).
La llam ada a p r in tln perm ite visualizar la cadena. Se visualizan todos los c a
racteres hasta finalizar la m atriz, incluidos los nulos ( \0 )-
c h a r [ ] c a d e n a = n e w c h a r [ 4 0 ] : // m a t r i z d e 4 0 c a r a c t e r e s
int i = 0 . car:
try
I
S y s t e m . o u t .p r i n t " I n t r o d u c i r un texto: "):
while ( ( c a r - S y s t e m . i n .r e a d ( )) !- ' \ r && i< c a d e n a . l e n g t h )
I
cadenafi] - (charlear;
i++;
I
S y s t e m . o u t .p r i n t l n ( " T e x t o i n t r o d u c i d o : " + cadena);
S y s t e m . o u t . p r i n t l n ( " L o n g i t u d del t e x t o : " + i):
S y s t e m . o u t . p r i n t l n ( " D i m e n s i n d e la m a t r i z : " + c a d e n a .l e n g t h ) :
I
catch(IOException ignorada) II
El ejem plo anterior define la variable cadena com o una m atriz de caracteres
de longitud 40. Despus establece un bucle para leer los caracteres que se tecleen
hasta que se pulse la tecla Entrar. C ada carcter ledo se alm acena en la siguiente
posicin libre de la m atriz cadena. Finalm ente se escribe el contenido de cadena,
el nm ero de caracteres alm acenados, y la dim ensin de la m atriz. Se puede o b
servar que el valor dado por el atributo length no es el nm ero de caractere
m acenado en cadena, sino la dim ensin de la m atriz.
O bserve que el bucle utilizado para leer los caracteres tecleados, podra ha
berse escrito tam bin as:
CA PTU LO 7: M A TRICES 177
En el captulo 5 vim os tam bin otra form a de leer una cadena de caracteres.
C onsiste en leer una lnea de texto de un flujo de la clase B u ffe re d R e a d e r. co
nectado al flujo in. utilizando el m todo re a d L in e , y alm acenarla en un objeto
S trin g. El m todo re a d L in e lee hasta encontrar el carcter V \ Vi o los caracte
res W i introducidos al pulsar la tecla E n tra n estos caracteres son ledos pero no
alm acenados, sim plem ente son interpretados com o delim itadores. Por ejem plo:
// D e f i n i r un f l u j o de c a r a c t e r e s de e n t r a d a : f l u j o E
I n p u t S t r e a m R e a d e r i s r = new I n p u t S t r e a m R e a d e r ( S y s t e m . i n ):
B u f f e r e d R e a d e r f l u j o E = new B u f f e r e d R e a d e r ( i s r ) ;
El ejem plo anterior d efine en prim er lugar un flujo de entrada, flu jo E , del cual
se podrn leer lneas de texto. D espus, define una referencia, flu jo S , al flujo de
salida estndar; esto perm itir utilizar la referencia flu jo S en lugar de System .out.
Finalm ente lee una lnea de texto introducida a travs del teclado. C on esa infor
m acin, el m todo r e a d L in e crea un objeto y devuelve una referencia al m ism o
que es alm acenada en cadena. F inalm ente, la llam ada a p rin tln perm ite visualizar
el objeto Strin g.
char[] c a d e n a = new c h a r [ 4 0 ] : // m a t r i z de 4 0 c a r a c t e r e s
// . . .
String scadena - new S t r i n g ( c a d e n a ) ;
178 JA V A: CU R SO DE PRO G R A M A CI N
E s c r i b a una c a d e n a d e c a r a c t e r e s :
Hola qu t a l ?
C a r c t e r - ' H \ c d i g o A S C I I = 72
C a r c t e r = ' o ' . c d i g o A S C I I = 111
O bservar que. el m todo p rin tln visualiza un elem ento de tipo c h a r com o un
carcter; p o r lo tanto, para visualizar su valor A SC II es necesario convertirlo ex
plcitam ente a in t. El program a com pleto se m uestra a continuacin.
import j a v a . i o . * :
public c la ss CValorAscii
I
// E x a m i n a r una c a d e n a de c a r a c t e r e s a l m a c e n a d a en un a m a t r i z
p u b lic s t a t ic void m a in (S trin g [] args)
1
c h a r [ ] cadena - new c h a r [ 8 0 ] // m a t r i z de c a r a c t e r e s
i n t c a r , i - 0; // un c a r c t e r y e l s u b n d i c e p a r a l a matriz
try
1
S y s t e m . o u t . p r i n t n ( " E s c r i b a una c a d e n a d e c a r a c t e r e s : ):
w h i l e ( ( c a r - S y s t e m . i n . r e a d ( ) ) ! = ' \ r ' && i < c a d e n a . l e n g t h )
cadena[i++] = (char)car;
// E x a m i n a r l a m a t r i z de c a r a c t e r e s
i - 0;
do
1________________________________________________________________
System.out.println("Carcter - * + cadena[i] +
", c d i g o ASCII - " + ( i n t ) c a d e n a [11):
i++:
I
while (i < c a d e n a . 1 e n g t h && c a d e n a [ i ] != '\0 ')
I
catch(IOException ignorada) (I
CA PTU LO 7: M A TRICES 179
cadena H H | o 1 I | a | 1 i. | q 1 u | 1 t | a | I | ? \0 \TT
O bservar que el bucle utilizado para exam inar la cadena, para i igual a 0 ac
cede al prim er elem ento de la m atriz, p ara i igual a 1 al segundo, y as hasta lle
gar al final de la m atriz o hasta encontrar un carcter nulo ( \0 ) que indica el final
de los caracteres tecleados.
En el siguiente ejem plo se trata de escribir un program a que lea una lnea de
la entrada estndar y la alm acene en una m atriz de caracteres. A continuacin,
utilizando un m todo, deseam os convertir los caracteres escritos en m insculas, a
m aysculas.
Si observa la tabla ASCII en los apndices de este libro, com probar que los
caracteres 'A '...... * Z \ a V estn consecutivos y en orden ascendente de su
cdigo (valores 65 a 122). Entonces, pasar un carcter de m insculas a m ayscu
las supone restar al v alor entero (cdigo A SC II) asociado con el carcter, la dife
rencia entre los cdigos de ese carcter en m inscula y el m ism o en m ayscula.
Por ejem plo, la diferencia a - 'A es 9 7 - 32 = 65, y es la m ism a que 'b '- 'B ', que
c - 'C ', etc. C om o ayuda relacionada con lo expuesto, puede repasar los concep
tos que se expusieron en el apartado "M atrices asociativas expuesto anterior
m ente en este m ism o captulo.
El m todo que realice esta operacin recibir com o parm etro la m atriz de ca
racteres que contiene el texto a convertir. Si el m todo se llam a M inusculasM a-
yusculas y la m atriz cadena, la llam ada ser as:
import j a v a , i o . * ;
p u b 1 i c e l a s s CCadenas
I
// C o n v e r t i r una c a d e n a a M a y s c u l a s
s t a t i c void M in u sc u la sM a y u sc u la s(c h a r[] str)
I
i nt i = 0. desp = ' a ' - ' A ' :
f o r ( i = 0 ; i < s t r . 1e n g t h && s t r [ i ] ! = \ 0 : 1+ + )
i f ( s t r [ i ] > = a && s t r f i ] < = z )
s t r [ i ] = ( c h a r ) { s t r t i ] - desp);
try
I
S y s t e m . o u t . p r i n t l n ( " E s c r i b a una c a d e n a de c a r a c t e r e s : );
w h i l e ( ( c a r = S y s t e m . i n . r e a d ( ) ) ! = \ r ' && i < c a d e n a . 1 e n g t h )
cadena[i++] = (char)car;
// C o n v e r t i r m i n s c u l a s a m a y s c u l a s
M i n u s c u l a s M a y u s c u l a s t c a d e n a ) ; // l l a m a r a l m t o d o
S y s t e m . o u t . p r i n t l n ( c a d e n a );
I
catch(IOException ignorada) II
Clase String
String(String valor)
En el captulo 4 hicim os un breve com entario acerca de que toda clase tiene al
m enos un m todo predeterm inado especial denom inado igual que ella, que es ne
cesario invocar para crear un objeto; se trata del constructor de la clase, del cual
aprenderem os m s en un captulo posterior. Segn esto, S t r in g es el constructor
de la clase S tr in g . A nteriorm ente, trabajando con cadenas de caracteres, vim os
cm o u tilizar este constructor para crear un objeto S t r in g a partir de una matriz
de caracteres. Pero en la m ayora de los casos lo utilizarem os para crear un objeto
S t r in g a partir de un literal o a partir de otro S trin g . P or ejem plo, cada una de las
lneas siguientes crea un S trin g . D ejam os para un prxim o captulo las diferen
cias que hay entre utilizar u na u otra forma, puesto que no repercuten en el cdigo
que escribim os debido a que los S t r in g son objetos no m odificables.
18 2 JA V A: C U R SO DE PROGRAM A CIN
String toString()
Este m todo devuelve el propio objeto S t r in g que recibe el m ensaje to S trin g. Por
ejem plo, el siguiente cdigo copia la referencia s tr l en s t r l (no crea un objeto
nuevo referenciado p o r str2, a partir de s tr l) . El resultado es que las dos variables,
s tr l y str2, perm iten acceder al m ism o o bjeto S trin g.
S tr in g s t r l = "abe". str2;
s t r 2 = s t r l . t o S t r i n g ( ) ; // e q u i v a l e a str2 = strl
S t r in g s t r l = "abe", s t r 2 - "Abe":
i f ( s t r l . c o m p a r e T o ( s t r 2 ) < 0)
S y s t e m . o u t . p r i n t l n ( s t r l ):
S t r i n g strtemp;
in t resultado:
if ( resultado > 0 )
s t r t e m p = " m a y o r que " ;
else i f ( resultado < 0 )
s t r t e m p = " m e n o r que
el se
strtemp = "ig u a l a ";
Sy ste m .o u t.p rin tln t s t r l + " es " + strtemp + s t r 2 ):
1
184 JA V A: C U R SO DE PROGRAM A CIN
int iength()
String toLowerCase()
Este m todo convierte a m insculas las letras m aysculas del objeto S t r in g que
recibe el m ensaje to L o w e rC a se . El resultado es un nuevo objeto S t r in g en mi
nsculas.
String tollpperCase()
E ste m todo convierte a m aysculas las letras m insculas del objeto S t r in g que
recibe el m ensaje to U p p e rC a se . El resultado es un nuevo objeto S t r in g en ma
ysculas.
String trim()
Este m todo devuelve un valor true si el su fijo especificado coincide con el final
del objeto S t r in g que recibe el m ensaje e n d sW ith . Un poco m s adelante se
m uestra un ejem plo.
CA PTU LO 7: M A TRICES 185
El siguiente ejem plo, elim ina los espacios en blanco que haya al principio y al
final de s t r l , verifica si s tr I finaliza con gh y en caso afirm ativo obtiene de s tr l
una subcadena str2 igual a s tr l m enos el sufijo g h .
S t r i n g s t r l - " abcdefgh , s t r 2 =
s t r l = s t r l . t r i m t ):
i f ( s t r l . e n d s W i t h ( " g h ))
s t r 2 = s t r l . s u b s t r i n g ( 0 . s t r l .1e n g th ( ) - " g h " .1e n g t h ( )):
Este m todo devuelve el ndice de la prim era ocurrencia del carcter especificado
por c a r en el objeto S t r in g que recibe el m ensaje in d ex O f. Si ca r no existe el
m todo in d e x O f devuelve el valor -1. Puede com enzar la bsqueda por el final en
lugar de hacerlo p o r el principio utilizando el m todo la stln d e x O f.
E ste m todo devuelve un nuevo S t r in g resultado de reem plazar todas las ocurren
cias ca r p o r n u evoC ar en el objeto S t r in g que recibe el m ensaje replace. Si el ca
rcter ca r no existiera, entonces se devuelve el objeto S t r in g original.
186 JA VA : C U R S O DE PROGRAM A CIN
E ste m todo devuelve un nuevo S t r in g creado a partir del dato pasado com o ar
gum ento. P uesto que el m todo es static no necesita ser invocado para un objeto
S trin g. El argum ento puede ser de los tipos boolean, ch ar. char[], int, long,
float, d ouble y Object.
d o u b le pi = M a t h . P I :
S t r i n g s t r l = S t r i n g . v a l u e O f ( p i );
char[] toCharArray()
Este m todo devuelve una m atriz de caracteres creada a partir del objeto S t r in g
que recibe el m ensaje to C h a r A r r a y .
S t r i ng s t r = " a b c d e " :
c h a r [ ] mear = s t r . t o C h a r A r r a y t ) ;
byteQ getBytes()
E ste m todo devuelve una m atriz de bytes creada a partir del objeto S t r in g que
recibe el m ensaje getBytes.
Clase StringBuffer
D el estudio de la clase S t r in g sabem os que un objeto de esta clase no es m odifi-
cable. Se puede observar y com probar que los m todos que actan sobre un ob
je to S t r in g con la intencin de m odificarlo, no lo m odifican, sino que devuelven
un objeto nuevo con las m odificaciones solicitadas. En cam bio, un objeto S t r in g
B u ffe r es un objeto m odificable tanto en contenido com o en tamao.
StringBuffer(/arg/)
Este m todo perm ite crear un objeto de la clase S tr in g B u ffe r . El siguiente ejem
plo m uestra las tres form as posibles de invocar a este mtodo:
S t r i n g B u f f e r s t r b l = new S t r in g B u f f e r ();
S t r i n g B u f f e r s t r b 2 = new S t r in g B u f f e r (80);
S t r i n g B u f f e r s t r b 3 = new S t r i n g B u f f e r ( ' ' a b c d e );
System.out.pri n t l n ( s t r b l + + s t r b l . 1e n g t h ( ) + + s t r b l . c a p a c i t y ( ) ) :
System.out.println(strb2 + + s t r b 2 . i e n g t h ( )+ " + s t r b 2 . c a p a c i t y ( )):
C A P T U L O 7: M A TRICES 187
0 16
0 80
a b c d e 5 21
int length()
int capacity()
StringBuffer append(tipo x)
Este m todo elim ina los caracteres que hay entre las posiciones p l y p 2 - 1 del
objeto S t r in g B u ff e r que recibe el m ensaje delete. El valor p 2 debe ser m ayor que
p l . Si p l es igual que p 2 . no se efectuar ningn cam bio y si es m ayor Java lanza
r una excepcin.
Partiendo del ejem plo anterior, el siguiente ejem plo elim ina la subcadena
A bril del objeto strb y aade en su m ism a posicin la cadena M ayo , El re
sultado ser M es de M ayo del ao 2002 .
S t r i n g B u f f e r s t r b = new S t r i n g B u f f e r ( " M e s de d e l a o ):
s t r b . i n s e r t t 7. " A b r i l " ) ;
strb.append(2002):
s t r b . d e l e t e t 7. 1 3 ) :
s t r b . i n s e r t ( 7 . " M a y o ):
Este m todo reem plaza los caracteres que hay entre las posiciones p l y p 2 - 1 del
objeto S t r in g B u f fe r que recibe el m ensaje replace, por los caracteres especifica
dos por str. La longitud y la capacidad del objeto resultante sern ajustadas auto
m ticam ente al valor requerido. El valor p 2 debe ser m ayor que p l . Si p l es igual
que p 2 , la operacin se convierte en una insercin, y si es m ayor Java lanzar una
excepcin. Segn lo expuesto, el ejem plo anterior, puede escribirse tam bin as:
StringBuffer reverse()
Este m todo reem plaza la cadena alm acenada en el objeto S t r in g B u f f e r que reci
be el m ensaje reverse, por la m ism a cadena pero invertida.
CA PTU LO 7: M A TRICES 189
String toString()
Clase StringTokenizer
E sta clase, perteneciente al paquete java.u til, perm ite dividir una cadena de ca
racteres en una serie de elem entos delim itados por unos determ inados caracteres.
De form a predeterm inada los delim itadores son: el espacio en blanco, el tabulador
horizontal (\t), el carcter nueva lnea (\n), el retorno de carro (\r) y el avance de
pgina (\f).
S t r i n g T o k e n i z e r cadena:
c a d e n a = new S t r i n g T o k e n i z e r " u n o , dos. tres y cuatro"):
1 9 0 JA V A: CU R SO DE PROGRAM A CIN
Para obtener los elem entos de la cadena separados por los delim itadores, en
este caso predeterm inados, utilizarem os los m todos h a s M o r e T o k e n s para saber
si hay m s elem entos en la cadena, y n e x tT o ke n para obtener el siguiente ele
m ento. Por ejem plo:
w h i 1e ( c a d e n a . h a s M o r e T o k e n s ( ) )
System .out.printlntcadena.nextTokenO);
un o,
dos.
tres
y
cuatro
uno
dos
tres
y
cuatro
A hora el resultado ser el siguiente (las lneas som breadas corresponden a los
delim itadores):
CA PITU LO 7: M A TRICES 191
tres
cuatro
U na m atriz m ultidim ensional, com o su nom bre indica, es una m atriz de dos o
m s dim ensiones. Java no soporta m atrices m ultidim ensionales, pero se puede lo
g rar la m ism a funcionalidad declarando m atrices de m atrices; las cuales, a su vez,
192 JA V A: C U R SO D E PROGRAM A CIN
pueden tam bin contener m atrices, y as sucesivam ente, hasta llegar a obtener el
nm ero de dim ensiones deseadas.
Por ejem plo, en el caso de las tem peraturas podram os definir una m atriz de
12 elem entos para que cada uno de ellos alm acenara una referencia a una matriz
unidim ensional de 31 elem entos; y en el caso de los nom bres podram os definir
u na m atriz de n elem entos para que cada uno d e ellos alm acenara una referencia a
una m atriz unidim ensional de m caracteres (un nom bre). L as figuras m ostradas en
los siguientes apartados le ayudarn a com prender lo expuesto.
t/po[][]... n o m b r e _ m a t r i z = new t i p o e x p r - ] ] [ e x p r - 2 ] . . . ;
donde tipo es un tipo prim itivo entero o real. El nm ero de elem entos de una ma
triz m ultidim ensional es el producto de las dim ensiones indicadas por expr-1,
e x p r -2 ,... Por ejem plo, la lnea de cdigo siguiente crea una m atriz de dos dim en
siones con 2x3 = 6 elem entos de tipo int:
i n t [ ] [ ] m = n e w i n t [ 2 ] [ 3 ] ;
A partir de la lnea de cdigo anterior. Java crea una m atriz unidim ensional m
con 2 elem entos m /0 ] y m [ l] que son referencias a o tras dos m atrices unidim en
sionales de 3 elem entos. G rficam ente podem os im aginarlo as:
m a triz m mo m,
mo mu m t2 fila 1
i n t [ ) [ ] m = new i n t [ 2 ] [ 3 ] ;
System .out.println(m .length); // r e s u l t a d o : 2
S y s t e m . o u t . p r i n t l n ( m [ 0 ] . 1 e n g t h ); // r e s u l t a d o : 3
S y s t e m . o u t . p r i n t l n ( m [ 1 ] . 1 e n g t h ); // r e s u l t a d o : 3
CA PTU LO 7: MATRICES 193
D esde nuestro punto de vista, cuando se trate de m atrices de dos dim ensiones,
es m s fcil pensar en ellas com o si de una tabla d e / filas p o r c colum nas se trata
ra. Por ejem plo:
matriz m col 0 col 1 col 2
fila 0 moo mot mo2
fila 1 mo mu mi2
Para acceder a los elem entos de la m atriz m, puesto que se trata de una matriz
de dos dim ensiones, utilizarem os dos subndices, el prim ero indicar la fila y el
segundo la colum na donde se localiza el elem ento, segn se puede observar en la
figura anterior. Por ejem plo, la prim era sentencia del ejem plo siguiente asigna el
valor x al elem ento que est en la fila 1, colum na 2; y la segunda, asigna el valor
de este elem ento al elem ento m[OJ[ 1 .
m [l][2] - x:
m [0 ][1 ] - m [1 ] [ 2 ] :
Nmero de f i l a s de la m a t r i z : 2
Nmero de c o lu m n a s de l a m a t r i z : 2
Introducir l o s v a l o r e s de l a m a t r i z
m[ 0 D[ 0 ] - 2
m [ 0 ] [ 1] = S
m[1] [ 0 ] - 3
m[1 ] [ 1] = 6
Suma de l a f i l a 0: 7 . 0
Suma de l a f i l a 1: 9 . 0
F i n del proceso
En prim er lugar definim os las variables que alm acenarn el nm ero de filas y
de colum nas de la m atriz, y a continuacin leem os esos valores del teclado, dese
chando cualquier valor negativo.
do
I
S y s t e m . o u t . p r i n t ( " N m e r o de c o l u m n a s de l a m a t r i z : ");
n c o l s = L e e r , d a t o I n t ( );
I
while (ncols < 1): // no p e r m i t i r un v a l o r negativo
f l o a t [ ] [ ] m = new f l o a t [ n f i 1 a s ] [ n c o l s ] : // c r e a r l a m a t r i z m
i n t f i l a = 0 , c o l = 0: // s u b n d i c e s
f l o a t s u m a f i l a = 0: // suma de l o s e l e m e n t o s de una f i l a
// L e e r . c l a s s d e b e e s t a r en l a c a r p e t a especificada p o r C LA S S P A T H
p u b lic c la s s CM atrizM ultidim ensional
I
// C r e a c i n de una m a t r i z m u l t i d i m e n s i o n a l .
// Suma de l a s f i l a s d e una m a t r i z de d o s d i m e n s i o n e s ,
pu blic s t a t i c void main( S t r i n g [ ] args)
I
int n f ila s . ncols: // f i l a s y c o l u m n a s de l a m atriz
CA PTU LO 7: M A TRICES 195
do
I
S y s t e m . o u t . p r i n t ( " N m e r o de f i l a s de l a m atriz: "):
n f i l a s - L e e r . d a t o l n t t ):
I
w hile (nfilas < 1): // no p e r m i t i r un v a l o r negativo
do
I
S y s t e m . o u t . p r i n t t " N m e r o de c o l u m n a s de l a m atriz: "):
n c o l s = L e e r . d a t o l n t );
I
w hile (ncols < 1): // no p e r m i t i r un v a l o r negativo
f l o a t [ ] [ ] m = new f l o a t [ n f i 1 a s ] [ n c o l s ] ; II c r e a r l a m a t r i z m
i n t f i l a = 0. c o l = 0 : // s u b n d i c e s
f l o a t s u m a f i l a = 0: // suma de l o s e l e m e n t o s de una f i l a
// V i s u a l i z a r l a suma de c a d a fila de l a m a t r i z
S y s t e m . o u t . p r i n t l n ( );
f o r ( f i l a = 0: f i l a < n f i l a s ; fila++)
I
s u m a f i l a - 0;
f o r ( c o l - 0; c o l < n c o l s ; c o l + + )
s u m a f i l a + - m [ f i 1 a ] [ c o l 3:
S eguram ente habr pensado que la sum a de cada fila se poda haber hecho
sim ultneam ente a la lectura tal com o se indica a continuacin.
m C f 11 a ] [ c o l ] = L e e r . d a t o F l o a t ( );
s u m a fila += m [ f i l a ] [ c o l ];
I
S y s t e m . o u t . p r i n t l n " S u m a de l a fila " + fila + " + suma f i l a ) :
I
Nmero de f i l a s de l a m a t r i z : 2
Nmero de c o l u m n a s de l a m a t r i z : 2
Introducir l o s v a l o r e s de l a m a t r i z .
m[0][0) - 2
m [ 0 ] [ 1) - 5
Suma de l a f i l a 0: 7.0
m [l][0] - 3
m[1 ] [ 1] - 6
Suma de l a f i l a 1: 9 . 0
F in del proceso.
Con este ltim o planteam iento, una solucin para escribir los resultados al fi
nal sera alm acenarlos en una m atriz unidim ensional y m ostrar posteriorm ente la
m atriz. E ste trabajo se deja com o ejercicio para el lector.
H aciendo un estudio anlogo al realizado para las m atrices num ricas m ulti
dim ensionales, la definicin de una m atriz de cadenas de caracteres puede hacerse
de la form a siguiente:
Por ejem plo, la lnea de cdigo siguiente crea una m atriz de cadenas de ca
racteres de F filas por C caracteres m xim o por cada fila.
char[][] m - new c h a r [ F ] [ C ] :
A partir de la lnea de cdigo anterior, Java crea una m atriz unidim ensional m
con los elem entos, m [0], m [ l ] m [F -IJ, que son referencias a otras tantas m a
C A PTU LO 7: M A TRICES 197
mp
mi
m2
m3
Para acceder a los elem entos de la m atriz m , puesto que se trata de una m atriz
de cadenas de caracteres, utilizarem os slo el prim er subndice, el que indica la
fila. Slo utilizarem os dos subndices cuando sea necesario acceder a un carcter
individual. P o r ejem plo, la prim era sentencia del ejem plo siguiente crea una m a
triz de cadenas de caracteres. La segunda asigna una cadena de caracteres a m [0]
desde el teclado; la cadena tendr nC arsP orF ila caracteres com o m xim o y ser
alm acenada a p artir de la posicin 0 de m [0]. Y la tercera sentencia, reem plaza el
ltim o carcter ledo en m [0] p o r \ 0 \ puesto que re a d devuelve el nm ero de ca
racteres ledos.
c h a r [ ] [ ] nombre = new c h a r [ n F i 1 a s ] [ n C a r s P o r F i 1 a ] :
n C a r s L e i d o s = f l u j o E . r e a d ( m [ 0 ] . 0 , n C a r s P o r F i 1 a );
nom bre[0][nCarsLeidos-l] = \ 0 :
Es im portante que asim ile que m [0J, m [l], etc. son cadenas de caracteres y
que, por ejem plo, m [l][3 ] es un carcter; el que est en la fila 1, colum na 3.
Nmero de f i l a s d e l a m a t r i z : 10
Nmero de c a r a c t e r e s p o r f i l a : 40
19 8 JA V A: CU R SO DE PROGRAM ACIN
E s c r i b a l o s n o m b r e s que d e s e a i n t r o d u c i r .
Puede f i n a l i z a r p u l s a n d o l a s t e c l a s [ C t r l ] [ Z ] .
N o m b r e [ 0 ] : Ma d e l Carmen
Nombre[l]: F ra n cisco
Nombre[2]: J a v i e r
Nombre[3]: [C trlD [Z ]
D e s e a v i s u a l i z a r el c o n t e n i d o d e l a m a t r i z ? ( s / n ) : S
Ms d e l Carmen
F ra n c i seo
Javier
import j a v a . i o . * :
// U t i l i z a L e e r . c l a s s q u e e s t en C L A S S P A T H = c : \ j d k l . 3 \ m i s C l a s e s
pu blic c la s s CMatrizlCadenas
I
public static void m a i n ( S t r i n g [ ] arg s)
I
try
I
// D e f i n i r un f l u j o de c a r a c t e r e s d e e n t r a d a : f l u j o E
I n p u t S t r e a m R e a d e r i s r = new I n p u t S t r e a m R e a d e r ( S y s t e m . i n ) ;
B u f f e r e d R e a d e r f l u j o E = new B u f f e r e d R e a d e r i s r ):
// D e f i n i r una r e f e r e n c i a a l f l u j o e s t n d a r de s a l i d a : f l u j o S
PrintStream flu jo S = System.out;
i n t nF i l a s = 0 . n C a r s P o r F i l a = 0;
i n t f i l a = 0, n C a r s L e i d o s - 0. e o f = - 1 ;
do
I
S y s t e m . o u t . p r i n t ( " N m e r o de f i l a s de l a m a t r i z : ");
n F i l a s = L e e r , d a t o I n t ( ):
1
while (nFilas < 1); // no p e r m i t i r un v a l o r negativo
CA PTU LO 7: M A TRICES 199
do , ,
q f,} \.j,y j , i l / . t l i f V , :i I
S y s t e m . o u t . p r i n t " N m e r o de c a r a c t e r e s por f i l a : ");
nCarsPorFila = Lee r.d atoln t);
j
w hile (nCarsPorFila < 1); // no p e r m i t i r un v a l o r n e g a t i v o
// M a t r i z de c a d e n a s de c a r a c t e r e s
e h a r [ ] [ ] nombre - new c h a r [ n F i l a s ] [ n C a r s P o r F i 1 a ] :
O bserve la sentencia:
r e s p u e s t a = ( ( f 1u j o E . r e a d L i n e ( ) ) . t o L o w e r C a s e ( ) ) . c h a r A t 0 ):
Es equivalente a:
S t r i n g s = f 1u j o E . r e a d L i n e ( ) ; II l e e r una l i n e a de t e x t o
s = s . t o L o w e r C a s e ( ): // c o n v e r t i r e l t e x t o a m a y s c u l a s
respuesta = s.ch a rA t(O ); // o b t e n e r e l p r i m e r c a r c t e r l e d o
L eem os las cadenas de caracteres. Para poder leer una cadena, necesitam os
definir una m atriz de caracteres que vam os a denom inar unN om bre. Esta ser
una m atriz unidim ensional de longitud 81 caracteres, por ejem plo.
// A a d i r e l nombre l e d o a l a m a t r i z nombre
n o m b r e f f i l a ] = new c h a r [ n C a r s L e i d o s - 2 ] : // men os CR LF
f o r ( i n t i = 0 : i < n C a r s l e i d o s - 2: i + + )
n o m b r e t f i 1a ] [ i ] = u n N o m b r e f i ] : // c o p i a r
unNombre J \r \n
L a sentencia nom bre fila I = new char[nC arsLeidos-2] asigna para cada valor
de fila un espacio de m em oria de nC arsLeidos-2 caracteres (en la figura: fila
O .fila / . f i l a 2, etc.), para copiar la cadena leda a travs de unN om bre. Re
cuerde que el m todo re a d devuelve el nm ero de caracteres ledos.
import j a v a . i o . * ;
// U t i l i z a L e e r . c l a s s que e s t en C l A S S P A T H = c : \ j d k l . 3 \ m i s C l a s e s
p u b lic c l a s s CMatriz2Cadenas
1
public static void m a in (S trin g [] args)
(
try
I
// D e f i n i r un f l u j o de c a r a c t e r e s de e n t r a d a : f l u j o E
I n p u t S t r e a m R e a d e r i s r = new I n p u t S t r e a m R e a d e r ( S y s t e m . i n ) ;
B u f f e r e d R e a d e r f l u j o E = new B u f f e r e d R e a d e r ( i s r );
// D e f i n i r una r e f e r e n c i a al f l u j o e s t n d a r de s a l i d a : flujoS
PrintStream f l u j o S = System.out;
i n t n F i l a s = 0. n C a r s P o r F i l a = 8 1 ;
i n t f i l a = 0, n C a r s L e i d o s = 0 , e o f = - 1 ;
c h a r [ ] unNombre new c h a r n C a r s P o r F i 1 a ] ;
do
[
S y s t e m . o u t . p r i n t t " N m e r o de f i l a s de l a m atriz: ");
n F i l a s = L e e r . d a t o l n t );
I
w hile (nFilas < 1): // no p e r m i t i r un v a l o r n e g a t i v o
// M a t r i z de c a d e n a s de c a r a c t e r e s
c h a r n n nombre = new c h a r [ n F i l a s ] [ ] :
flujoS.print("\n.\n");
n F i l a s = f i l a ; , II n mero de f i l a s l i d a s
// . . .
// c o n t i n a i g u a l q u e en l a v e r s i n a n t e r i o r
I
catch (IQException ignorada) I I
C A P T U L O 7: M A TRICES 2 0 3
Para com probar lo expuesto, vam os a resolver el program a anterior p ero utili
zando una m atriz de objetos S tr in g . El proceso que seguirem os es el siguiente:
C ada elem ento de esta m atriz ser iniciado p o r Java con el v alor nuil, indi
cando as que la m atriz inicialm ente no referencia a ningn objeto S trin g;
esto es, la m atriz est vaca.
L eem os las cadenas de caracteres. Para poder leer una cadena, utilizarem os el
m todo re ad Lin e . R ecuerde que este m todo perm ite leer una cadena de ca
racteres hasta encontrar un carcter V , \w* o 'W ' (estos caracteres son le
dos pero no alm acenados) y devuelve una referencia a un objeto S t r in g que
alm acena la inform acin leda; referencia que asignarem os al siguiente ele
m ento vaco de la m atriz nom bre. E ste proceso lo repetirem os para cada uno
de los nom bres que leam os. R ecuerde tam bin que si el m todo re a d L in e in
tenta leer del flujo y se encuentra con el final del m ism o, retom ar la cons
tante nuil.
Una vez ledos todos los nom bres deseados los visualizam os si la respuesta a
la peticin de realizar este proceso es afirm ativa.
import j a v a . i o . * :
// U t i l i z a L e e r . c l a s s que e s t en C L A S S P A T H - c : \ j d k l . 3 \ m i s C l a s e s
public c la ss CMatriz3Cadenas
I
public static void m a in (S trin g [] args)
I
try
1
// D e f i n i r un f l u j o de c a r a c t e r e s de e n t r a d a : f l u j o E
I n p u t S t r e a m R e a d e r i s r - new I n p u t S t r e a m R e a d e r ( S y s t e m , i n ) ;
B u f f e r e d R e a d e r f l u j o E = new B u f f e r e d R e a d e r ( i s r ):
// D e f i n i r una r e f e r e n c i a a l f l u j o e s t n d a r de s a l i d a : flujoS
PrintStream f lu j o S - System.out:
i n t nFi l a s = . fila - 0:
do
I
S y s t e m . o u t . p r i n t ( " N m e r o de f i l a s de l a m a t r i z : );
n F i l a s = L e e r . d a t o l n t ):
I
w hile (nFilas < 1): // no p e r m i t i r un v a l o r n e g a t i v o
// M a t r i z de c a d e n a s de c a r a c t e r e s
S t r i n g E ] n o mb r e - new S t r i n g [ n F i 1 a s ] ;
S t r i n g B u f f e r f ] no mb r e - new S t r i n g B u f f e r [ n F i l a s ] ;
S t r i n g s N o mb r e ;
EJERCICIOS RESUELTOS
1. R ealizar un program a que lea una lista de valores introducida por el teclado. A
continuacin, y sobre la lista, buscar los valores m xim o y m nim o, y escribirlos.
in t nElementos; II n m e r o de e l e m e n t o s ( v a l o r no n e g a t i v o )
do
S y s t e m . o u t . p r i n t ( " N m e r o de v a l o r e s que d es ea introducir: ):
n E l e m e n t o s = L e e r . d a t o l n t );
I
w hile (nElementos < 1):
El cdigo anterior establece un bucle p ara leer datos hasta com pletar la m a
triz. Si p o r cualquier circunstancia se decide term inar la entrada d e datos antes
que se com plete la m atriz, pulsando, p o r ejem plo, la tecla E ntrar, el m todo
datoF loat devolver el valor N a N . Para detectar si esto ha ocurrido debem os
utilizar el m todo is N a N de la clase Flo at. Se trata d e un m todo static que
devuelve tru e si su argum ento se corresponde con un dato no num rico, y
false en otro caso.
vi f'j ion fionohoT im aioli.v ou alan i.
max = mi n = d a t o [ 0 ] :
f o r ( i = 0; i < nE lem entos: i++)
1
if ( d a t o [ i ] > max)
max = d a t o [ i ] :
i f < d a t o [ i ] < min)
mi n = d a t o [ i ] ;
)
S y s t e m . o u t . p r i n t l n t " \ n V a l o r m xi mo : " + ma x ) ;
Syste,m,,out. p r i n t l n t " V a l o r m n i m o : + m i n ) ;
// L e e r . c l a s s d e b e e s t a r en l a carpeta especificada p o r CL AS S PA TH
p u b lic c l a s s CValoresMaxMin
I
// O b t e n e r e l m xi mo y e l m n i m o de un c o n j u n t o de v a l o r e s
pu b lic s t a t ic void m a in ( S t r in g [ ] args)
I
int nElementos: // n me r o de e l e m e n t o s (valor no n e g a t i v o )
do
[
S y s t e m . o u t . p r i n t t " N m e r o de v a l o r e s que d e s e a introducir: ");
n E l e m e n t o s - L e e r . d a t o l n t t ):
1
while (nElem entos < 1):
f l o a t [ ] d a t o = new f l o a t [ n E l e m e n t o s ] ; // c r e a r l a m a t r i z d a t o
i n t i = 0: // s u b n d i c e
f l o a t max. m i n ; // v a l o r m xi mo y v a l o r m n i m o
// O b t e n e r l o s v a l o r e s m xi mo y m n i m o
i f (nE lem en to s > 0)
I
max = mi n = d a t o [ 0 ] ;
f o r ( i = 0: i < n E l e m e n t o s : i++)
I
if ( d a t o [ i ] > max)
max - da t OC i
i f ( d a t o [ i ] < min)
min - d a t o i ] ; : :.n
. 1 . , - o'-'., ; , , :' ;.! ,1):) W--.f,,
// E s c r i b i r l o s r e s u l t a d o s
S y s t e m . o u t . p r i :r t t l n ( " \ n V a l o r m xi mo : " + ma x ) :
S y s t e m . o u t . p r i n t l n ( " V a l o r minimo: " + min ):
1
el se
S y s t e m . o u t . p r i n t l n \ n N o h a y d a t o s . ):
208 JAVA: C U R SO D E PROGRAM A CIN
2. Escribir un program a que d com o resultado la frecuencia con la que aparece cada
una de las parejas de letras adyacentes de un texto introducido por el teclado. No
se har diferencia entre m aysculas y m insculas. El resultado se presentar en
form a de tabla, de la m anera siguiente:
a b c d e f ... z
a 0 4 0 2 1 0 ... 1
b 8 0 0 0 3 1 ... 0
c
d
e
f
Por ejem plo, la tabla anterior dice que la pareja de letras a b ha aparecido 4
veces. La tabla resultante contem pla todas las parejas posibles de letras, desde la
a a hasta la zz.
L as parejas de letras adyacentes de hola que tal" son: ho, ol, la, a blanco no
se contabiliza por estar el carcter espacio en blanco fuera del rango a - z ,
blanco q no se contabiliza por la m ism a razn, qu, etc.
if ( ( c a r a n t > = ' a ' && c a r a n t < = ' z ' ) && (c a r> = a ' && c a r < = ' z ' ) )
t a b l a t c a r a n t - a ' ] [ c a r - ' a ' ] + + :
import j a v a . i o . * :
II L e e r . c l a s s d e b e e s t a r en l a carpeta especificada p o r C LA S S P A T H
p u b lic c l a s s CFrecuencia
I
// T a b l a de f r e c u e n c i a s de l e t r a s a d y a c e n t e s en un t e x t o ,
pu b lic s t a t ic void m a in (S trin g [] args)
I
// C r e a r l a m a t r i z t a b l a c o n ' z - ' a ' + l p o r z ' - ' a ' + l elementos.
// J a v a i n i c i a l o s e l e m e n t o s de l a m a t r i z a c e r o .
i n t [ ] [ ] t a b l a = new i n t [ z - a ' + 1 ] [ z - a ' + 1 ] :
c h a r f . c; // s u b n d i c e s
char car; // c a r c t e r a c t u a l
char carant = // c a r c t e r a n t e r i o r
f in a l char eof = ( c h a r ) - l:
// E n t r a d a d e d a t o s y c l c u l o de l a t a b l a de f r e c u e n c i a s
S y s t e m . o u t . p r i n t l n ( " I n t r o d u c i r un t e x t o . " ) :
System .out.printlnt"Para f in a liz a r pulsar [ C t r l ] [ z ] \ n " ) :
try
1
// L e e r e l s i g u i e n t e c a r c t e r d e l t e x t o
w h ile ( ( c a r = ( c h a r ) S y s t e m . i n .r e a d ( )) ! - eof)
I
// C o n v e r t i r el c a r c t e r a m i n s c u l a s s i procede
if ( c a r > = ' A ' && c a r < = Z ) c a r + = ( ' a ' 'A ') :
// S i el c a r c t e r l e d o e s t e n t r e la a y la z '
// in cre m e n t a r el c o n t a d o r c o r r e s p o n d i e n t e
if ( ( c a r a n t > = ' a && c a r a n t < = ' z ' ) && ( c a r > = a && c a r < = z ) )
ta bla[caran t - a ][c a r - a ']+ + :
carant = car;
catch U O E x c e p t i o n ig n o ra d a ) II
// M o s t r a r l a t a b l a d e f r e c u e n c i a s
System .out.p rintln("\n"):
II V i s u a l i z a r una c a b e c e r a " a b e . . .
System .out.print "):
f o r (c = ' a : c <= z ' : c++)
System .out.p r i n U " " + c);
S y s t e m . o u t . p r i n t 1 n ( );
// V i s u a l i z a r l a t a b l a de f r e c u e n c i a s
f o r ( f - a : f <= z : f + + )
I
S y s t e m . o u t . p r i n t ( f ):
f o r ( c = a ' ; c < = z ' : c + + )
S y s t e m . o u t . p r i n t ( " " + t a b 1a [ f - a ' ] [ c - 'a '] ) :
S y s t e m . o u t . p r i n t l n ( );
210 JA VA : C U R SO D E PROGRAM A CIN
a b c d e f ... z
a 0 4 0 2 1 0 ... 1
b 8 0 0 0 3 1 ... 0
c
d
e
f
EJERCICIOS PROPUESTOS
1. Se desea realizar un histogram a con los pesos de los alum nos de un determ inado
curso.
Peso Nmero de a l u m n o s
21 **
22 ****
23 * * * * * * * * * * * * * * *
24 * * * * * *
El nm ero de asteriscos se corresponde con el nm ero de alum nos del peso espe
cificado.
3. Realizar un program a que lea una cadena de caracteres y la alm acene en una m a
triz. A continuacin, utilizando un m todo, deber convertir los caracteres escritos
en m aysculas a m insculas. Finalm ente im prim ir el resultado.
16 12 99 95 18 87 10
es 18, porque este valor es m enor q ue 99, 95 y 87 (m itad de los nm eros) y m ayor
que 16, 12 y 10 (otra m itad).
5. E scribir un program a que utilice un m todo para leer una lnea de la entrada y d
com o resultado la lnea leda y su longitud o nm ero de caracteres.
import j a v a . i o . * :
public c la ss Test
1 mi - i; n-> ,
public static void V isualizar(byte car)
I
int i = 0. bitr
f o r ( i = 7 : i >= 0 : i - )
I
b i t = ( ( c a r & (1 << i ) ) ! = 0) ? 1 : 0:
System .out.p rin t(bit):
I !! i v.-
S y s t e m . o u t . p r i n t l n ( ):
8. Para alm acenar una m atriz bidim ensional que generalm ente tiene m uchos ele
m entos nulos (m atriz sparse) se puede utilizar una m atriz unidim ensional en la
que slo se guardarn los elem entos no nulos precedidos por sus ndices, fila y
colum na, lo que redunda en un aprovecham iento de espacio. P or ejem plo, la m a
triz:
6 0 0 0 4
0 5 0 0 2
2 0 0 0 0
0 0 7 0 0
fila
0 0 0 8 0
columna
|0 10 1 6 1 0 4 4 1 1 5 1 4 2 2 0 2 3 2 | 7 |4 3 8
Se pide:
a) Escribir un m todo que lea una m atriz bidim ensional por filas y la alm acene
en una m atriz m unidim ensional. El prototipo de este m todo ser:
b) Escribir un m todo que perm ita representar en pantalla la m atriz bidim ensio
nal por filas y colum nas. El prototipo de este m todo ser:
Los parm etros / y c se corresponden con la fila y la colum na del elem ento
q ue se visualiza. El valor del elem ento que se visualiza se obtiene, lgica
m ente de la m atriz unidim ensional creada en el apartado a, as: buscam os pol
los ndices / y c; si se encuentran, el m todo Visualizar devuelve el valor al
m acenado justam ente a continuacin; si no se encuentran, entonces devuelve
un cero.
E scrib ir un program a que, utilizando el m todo C rearM atrizU ni, cree una
m atriz unidim ensional a partir de una supuesta m atriz sparse bidim ensional y
a continuacin, utilizando el m todo Visualizar, m uestre en pantalla la matriz
bidim ensional.
CA PTU LO 8
& F.J. Ceballos/RA-MA
METODOS
En los captulos anteriores aprendim os lo que es un program a, cm o escribirlo y
qu hacer para que el ordenador lo ejecute y m uestre los resultados perseguidos;
adquirim os conocim ientos generales acerca de la program acin orientada a obje
tos; aprendim os acerca de los elem entos que aporta Java; analizam os cm o era la
estructura de una program a Java; aprendim os a leer datos desde el teclado y a vi
sualizar resultados sobre el m onitor; estudiam os las estructuras de control; y
aprendim os a trabajar con m atrices.
En este captulo, utilizando los conocim ientos adquiridos hasta ahora, vamos
a centram os en cuestiones m s especficas com o pasar argum entos a m todos, es
cribir m todos que devuelvan m atrices, copiar m atrices, pasar argum entos en la
lnea de rdenes, im prim ir resultados con form ato, clasificar los elem entos de una
m atriz, o bien buscar un elem ento en una m atriz, entre otras cosas.
rior. A lgunos de los m todos de la biblioteca Java tam bin tienen parm etros que
son m atrices de caracteres, p o r ejem plo re a d . P ero no hem os estudiado nada
anlogo en el caso de m atrices num ricas, lo cual es lgico porque m ientras una
cadena de caracteres, por ejem plo nom bre , es un objeto que m anejam os habi
tualm ente com o tal, no sucede lo m ism o con una m atriz num rica, donde cual
quier operacin p asa p o r el acceso individual a sus elem entos.
Para aclarar lo expuesto, el siguiente ejem plo im plem enta un m todo con un
parm etro de tipo d o u b le[][], que perm ite m ultiplicar p o r 2 los elem entos de una
m atriz num rica de dos dim ensiones pasada com o argum ento.
Mu t i p l i c a r P o r D o s M a t r i z 2 D ( m ) :
II V i s u a l i z a r l a m a t r i z p o r f i l a s
f o r ( i n t f = 0: f < m . l e n g t h : f + + )
1
f o r ( i n t c = 0; c < m [ 0 ] . l e n g t h ; c++)
System .out.print(m [f][c] + " "):
S y s t e m . o u t . p r i n t l n ):
main a c c e d e MultiplicarPorDosMatriz2D
a la m a triz a a c c e d e a la m atriz
tra v s d e m a tra v s d e x
m lx0 I m Ix, |
*! 10 | 20 | 30 |
40 | 50 60 fila 1
La aplicacin siguiente im plem enta un m todo que tiene un parm etro de tipo
d o u b le[][] y perm ite copiar una m atriz num rica bidim ensional pasada com o ar
gum ento, en otra m atriz. El m todo devuelve com o resultado la copia realizada.
f o r ( i n t f = 0; f < x . l e n g t h ; f + + )
f o r ( i n t c = 0: c < x [ 0 ] . l e n g t h : c++)
z [ f ] [ c ] = x [ f ] [ c ]:
r e t u r n z;
I
// C o p i a r una m a t r i z u t i l i z a n d o un mt od o
d o u b l e [ ] [ ] m2 = C o p i a r M a t r i z 2 D ( m l );
m l [ 0 ] [ 0 ] = 77; // m o d i f i c a r un e l e m e n t o de l a m a t r i z original
// V i s u a l i z a r l a m a t r i z m2
f o r ( i n t f = 0: f < m 2 .le n g t h : f++)
21 8 JA V A: C U R SO DE PROGRAM A CIN
f o r ( i n t c = 0: c < m 2 [ 0 ] . 1 e n g t h : c++)
System .out.print(m 2[f][c] + " ") :
S y s t e m . o u t . p r i n t l n t );
O tra form a de realizar una copia de una m atriz es utilizando el m todo clone
expuesto anteriorm ente. Q uizs esta form a de proceder resulte m s difcil de
com prender cuando se m anipulan m atrices m ultidim ensionales. Por eso es reco
m endable volver a analizar detenidam ente la figura expuesta en el apartado
M atrices num ricas m ultidim ensionales del captulo anterior. Si llega a la con
clusin de que una m atriz de dim ensiones f x c es una m atriz de una dim ensin de/
elem entos q ue son referencias a otras tantas m atrices de una dim ensin de c ele
m entos de un tipo especificado, le ser fcil entender el cdigo m ostrado a conti
nuacin, el cual copia una m atriz de dos dim ensiones referenciada p o r m i en otra
m atriz referenciada por m2:
i n t [ ] [ ] mi = 1 1 1 0 . 2 0 . 3 0 1 . 14 0 . 5 0 . 6 0 1 1 ;
i n t [ ] [ ] m2 = new i n t [ m i . 1 e n g t h ] [ m i [ 0 ] . 1 e n g t h ] ;
S y s t e m . a r r a y c o p y ( m l . 0 . m2. 0 . m i . 1 e n g t h ) :
i nt a rg - 1234 ; ..
jm bhhhnhhhm hm m hhnbm m hhi
S y s t e m . o u t . p r i n t l n a r g );
1
L a lnea som breada del ejem plo anterior invoca al m todo In c rem en ta rlo y
copia el valor del argum ento arg en el parm etro param del m todo. Esto signifi
ca q ue el argum ento ha sido pasado p o r valor. P or lo tanto, cualquier m odifica
cin que haga el m todo sobre param no afectar a la variable original. Segn lo
expuesto el m todo m a in m ostrar el resultado 1234, valor original de arg.
Q u hay que hacer para que un m todo pueda m odificar el valor original del
argum ento que se le pasa? Pasar dicho argum ento por referencia.
Tam bin hem os estudiado que un valor de un tipo prim itivo puede ser encap-
sulado en un objeto. Por ejem plo un valor de tipo in t puede ser encapsulado en un
objeto de la clase In te g e r. Entonces, si los objetos son pasados p o r referencia
puede un m todo m odificar el valor original del argum ento que se le pasa cuan
do ste es un objeto? A nalicem os el siguiente ejem plo:
Com o las clases que encapsulan los tipos prim itivos no tienen m todos anlo
gos al descrito, esta form a de pasar un valor de un tipo prim itivo p o r referencia
con la intencin de que sea m odificado, no sirve. C m o d ar solucin al problem a
planteado? Segn se ha expuesto anteriorm ente, una m atriz es un objeto, lo cual
C A P T U L O 8: M TO D O S 2 2 1
significa que cuando se pase com o argum ento a un m todo, ser pasado por refe
rencia. Por lo tanto, los cam bios que haga este m todo sobre los elem entos de esa
m atriz afectarn a la original. V eam os el siguiente ejem plo:
C ada elem ento de la m atriz args referencia a un argum ento, de m anera que
args[0] contiene el p rim er argum ento de la lnea de rdenes, a r g s [ l] el segundo,
etc. Por ejem plo, supongam os que tenem os una aplicacin Java denom inada Test
que acepta los argum entos -n y -/. Entonces, podram os invocar a esta aplicacin
escribiendo en la lnea de rdenes d el sistem a operativo la siguiente orden:
java Test -n -1
E sto hace que autom ticam ente la m atriz args d e objetos S t r in g se cree para
contener dos objetos S tr in g : uno con el prim er argum ento y otro con el segundo.
Puede im aginarla de cualquiera de las dos form as siguientes:
args
argsp - n - n
arg s i - 1 - 1
Para clarificar lo expuesto vam os a realizar una aplicacin que sim plem ente
visualice los valores de los argum entos que se la han pasado en la lnea de rd e
nes. E sto nos dar una idea de cm o acceder desde un program a a esos argum en
tos. Supongam os que la aplicacin se denom ina T est y que slo adm ite los
argum entos -rt, -k y -/. Esto quiere decir que p o d rem o s especificar de cero a tres
argum entos. Los argum entos repetidos y no vlidos se desecharn. P or ejem plo, la
siguiente lnea invoca a l aplicacin T est pasndole los argum entos -n y -/:
java Test -n -1
// Q u a r g u m e n t o s s e h a n p a s a d o ?
f o r ( i n t i = 0; i < a r g s . l e n g t h : i + + j
Argumentos:
-1
-n
224 JA V A: C U R S O DE PROGRAM A CIN
MTODOS RECURSIVOS
Se dice que un m todo es recursivo, si se llam a a s m ism o. El com pilador Java
perm ite cualquier nm ero de llam adas recursivas a un m todo. C ada vez que el
m todo es llam ado, sus parm etros y sus variables locales son iniciadas.
do
1
System .out.print("Nm ero? ):
nu mero = L e e r . d a t o l n t ( ):
)
while ( n u me r o < 0 || nu mero > 2 5 ) :
0 factorial(4) 24
4 * factorial(3) 4*6
2 3 * factoriai(2) 3*2
3 2 * factorial( 1) 2 * 1
4 1 * factorial(O) 1* 1
factorial(O) 1
C ada llam ada al m todo factorial aum enta en una unidad el nivel de recur
sin. C uando se llega a n = 0. se obtiene com o resultado el valor / y se inicia la
vuelta hacia el punto de partida, reduciendo el nivel de recursin en una unidad
cada vez.
con un nm ero determ inado de dgitos enteros com pletando con ceros por la
izquierda si fuera necesario,
o bien una serie de cantidades decim ales, una debajo de otra, ajustadas por la
com a.
Para controlar los distintos form atos. Java proporciona un conjunto de clases
en el paquete java.text. La figura siguiente m uestra estas clases. L os rectngulos
som breados son clases abstractas.
La clase F o r m a t es una clase base abstracta para dar form ato a nm eros, fe
chas/horas y m ensajes. D e esta clase se derivan tres subclases especializadas en
cada una de las tareas m encionadas: N u m b e rF o rm a t, D a te F o r m a t y M c ssa g e -
F o rm a t.
Object
J
17 Formal
j
17 NumberFormat DateForm at M essageForm at
J
r
J T
DecimalFormat Sim pleDateFormat
ChoiceForm at
Para dar form ato a un nm ero, prim ero hay que crear un objeto form ateador basa
do en un form ato especfico, y luego utilizar su m todo fo rm a t para convertir el
nm ero en una cadena construida a partir del form ato elegido. L os sm bolos que
se pueden utilizar para especificar un determ inado form ato son:
Sm bolo Significado_______________________________________________________
0 R epresenta un dgito cualquiera, incluyendo los ceros no significati
vos.
# R epresenta un dgito cualquiera, excepto los ceros no significativos.
R epresenta el separador decim al.
R epresenta el separador de los miles.
E Form ato cientfico. E, separa la m antisa y el exponente.
A cta com o separador cuando se especifican varios form atos.
S igno negativo de form a predeterm inada.
C A PTU LO 8: M TODOS 2 2 7
El siguiente ejem plo crea un objeto fo rm a to que perm itir obtener nm eros
form ateados con dos decim ales, si los hay, y con el punto de los miles.
D e c i m a l F o r m a t f o r m a t o = new D e c i m a l F o r m a t :
Strin g sa lid a = form ato.form at(dato);
S e puede utilizar tam bin un objeto form ateador basado en la localidad actual.
Por ejem plo, las siguientes lneas de cdigo darn lugar a nm eros form ateados
as: 1 2 3 . 4 5 6 . 0 0 P t s .
Nu mb e r F o rm a t f o r m a t o = N u m b e r F o r m a t . g e t C u r r e n c y I n s t a h c e ):
S t r in g s a lid a = form ato.form 'at(dato):
donde ( e n , U S ") significa ingls de E stados U nidos. O tros ejem plos de loca
lidades son: ( e n , " G B ") que significa ingls del R eino Unido; ( e s" , " E S )
que significa espaol de Espaa; ( f r , F R ") que significa francs de Francia;
(" d e " , D E ) que significa alem n de A lem ania; etc. A continuacin se explica
la clase Lcale.
O tros m todos de inters son ge tN u m b e rln sta n c e que devuelve el form ato
num rico predeterm inado que se em plea en la localidad que se especifique, o bien
en la actual si no se especifica ninguna localidad; y ge tP e rcen tln stan ce que de
vuelve el form ato para especificar un v alor en tanto p o r ciento.
Localidad
Local ef] pa s =
I
new L o c a l e t " e s , "ES") ,
new L o c a l e ( " e n . "US ).
I;
Alineacin
L os valores num ricos que escribim os, con o sin form ato, quedan alineados a u
tom ticam ente a la izquierda. Para alinear a la derecha una serie de valores num
ricos form ateados, adem s del objeto form ateador, hay que crear un objeto de la
clase F ie ld P o sitio n basado en la posicin utilizada para realizar la alineacin.
sta puede ser: IN T E G E R _F IE L D , alineacin por el ltim o dgito entero (por la
com a decim al), o bien E RAC TI N _FIELD , alineacin por el ltim o dgito d eci
mal (1N TEG ER_F!ELD y F R A C T IO N _F IE L D son dos constantes pertenecientes
a la clase N u m b e r F o im a t). Por ejem plo:
S t r i n g p a t r n - new S t r i n g ( # # # . # # # . # # 0 . 0 0 " ) :
Deci mal For mat f o r ma t o = new De c i ma l F o r ma t ( p a t r n ) ;
F i e l d P o s i t i o n f p - new F i e l d P o s i t i o n ( Nu mb e r F o r ma t . FRACTI0N_FIELD);
S t r i n g B u f f e r s a l i d a = new S t r i n g B u f f e r ( ):
f o r m a t o . f o r m a t t d a t o . s a l i d a , f p );
f o r ( i n t i = 0; i < ( p a t r n . 1 e n g t h ( ) - f p . g e t E n d I n d e x ( ) ) ; i++)
sal i d a . i n s e r t ( 0 . ' ') ;
Em pleando los conocim ientos expuestos hasta ahora podem os, com o ejercicio,
im plem entar una clase que incluya algunos m todos que despus podam os utilizar
para form atear nm eros. Estos m todos los definirem os static para que puedan
ser invocados sin necesidad de crear un objeto de la clase. La clase la denom ina
rem os O btener y sus m todos ser los siguientes:
A linD er. R ealiza la m ism a operacin que F orm atoP er y adem s, alinea los
nm eros a la derecha del patrn utilizado.
Form atoPas. R ealiza la m ism a operacin que Form atoP er pero utilizando
los sm bolos de puntuacin del pas especificado.
import j a v a . t i l
import j a v a . t e x t . * :
p u b l i c c l a s s Obtener
{
static public String Form atoLocal(double dato)
I
N u mb e r F o r m a t f o r m a t o = N u m b e r F o r m a t . g e t C u r r e n c y l n s t a n c e t ):
Strin g salida = form ato.form attdato):
return sa lid a:
1
import j a v a . i o . * ;
import j a v a .u t i 1 .*:
p u b l i c c l a s s CDemoFormatoNum n/m
I . ,, , : . 'i ' A i r m i M i. i :
static public void m a in (S trin g [] args)
(
PrintStream f lu j o S = System.out;
f l u j o S . p r i n t l n O b t e n e r . F o r m a t o L o e a l (1234 5 6 ) ) ;
f l u j o S . p r i n t l n( O b t e n e r . Form a t o L o c a l ( 1 2 . 3 4 5 6 . 7 8 9 ) ) :
f 1u j o S . p r i n t n ( O b t e n e r . F o rm a to L o c a l( 1 2 3 .4 5 ) ) ;
f l u j o S . p r i n t l n );
fl ujoS.p rintln(O bten er.fo rm atoP er( " # # . # # . # " . 123456)):
f 1u joS. p ri n t l n ( O b t e n e r . Form atoPer " # # # # " . 123456));
f 1 u j o S . p r i n t l n ( O b t e n e r . F o r m a t o P e r ( # # # . # # " . 1 2 3 4 5 6 . 7 8 9 ) ) ;
f 1u j o S . p r i n t n ( O b t e n e r . F o rm a to P e r(" 0 0 0 0 0 0 . 0 0 0 " . 1 2 3 .4 5 ) ) :
f l u j o S . p r i n t l n( O b t e n e r . Form a t o P e r ( " I # # . # # . # # : " . 1 2 3 4 5 . 67 ) ) ;
f l u j o S . p r i n t l n ( 0 b t e n e r . FormatoPer( "###.###.'###". 1 2 .3 4 ));
flu joS.p rintln);
S t r i n g p a t r n = new S t r i n g ( " # # # . # # # , # 0 . 0 0 " ) :
f l u j o S . p r i n t l n ( 0 b t e n e r .Al i n D e r ( p a t r n . 1 . 2 3 4 ) ) ;
flu jo S . p r i ntln(Obtener.Al i nD er(patrn. 12.345)):
fl u jo S.p rin tln (0 b te n e r.A l in D e r(p a tr n . -123.456));
CA PTU LO 8: M TODOS 2 3 1
f 1u j o S . p r i n t l n ( O b t e n e r . A l inDerpatrn. 123.456));
flujoS.println(O btener.Al inDerpatrn. 1234.567));
f 1u j o S . p r i n t l n ( O b t e n e r .Al i nDer(patrn. 12345.678));
f 1u j o S . p r i n t l n ( O b t e n e r . A l i nDer p a t r n , -12345)):
f l u j o S . p r i n t l n );
Locale[] pas =
I
new L o c a l e " e s " . " E S ).
new L o c a l e " e n " . " U S " ) .
I:
f o r ( i n t i = 0: i < p a s . l e n g t h ; i + + )
f l u j o S . p r i n t l n i Obtener.FormatoPa s ("# # # ,# # # .# # # ", 1 2 3 4 5 6 . 789,
pa s [ i ] ) ) ;
El siguiente ejem plo alm acena en salida la fecha y la hora actuales segn el
form ato especificado p o r patrn.
D a t e hoy - new D a t e ( ) ;
S t r i n g pa tr n = "EEEE dd-MMM-yyyy, HH:mm:ss :
S i m p l e D a t e F o r m a t f o r m a t o - new S i m p l e D a t e F o r m a t ( p a t r n ):
S t r i n g s a l i d a = f o r m a t o . f o r m a t h o y ):
Se puede utilizar tam bin un objeto form ateador basado en la localidad actual.
En este caso dicho objeto ser creado y devuelto por alguno de los m todos de la
clase D a te F o rm a t. Por ejem plo, las siguientes lneas de cdigo alm acenarn en
sF echa y sH ora la fecha y la hora segn el form ato local predeterm inado. Por
ejem plo: 1 6 - a g o - 0 2 y 2 1 : 0 6 : 34.
D a t e h o y = new D a t e ( ):
S t r i n g sFecha. sHora;
DateFormat formato:
f o r m a t o = D a t e F o r m a t . g e t D a t e l n s t a n c e t ):
sFecha = f o r m a t o . f o r m a t ( h o y ) :
f o r m a t o - D a t e F o r m a t . g e t T i m e l n s t a n c e );
sHora = f o r m a t o . f o r m a t ( h o y ) :
El m todo ge tD ate ln sta n ce sin argum entos devuelve el form ato utilizado pa
ra m ostrar la fecha en la localidad actual, y el m todo ge tT im e ln sta n c e sin argu
m entos devuelve el form ato utilizado en la localidad actual para m ostrar la hora.
A m bos m todos pueden ser invocados con un argum ento que especifique el estilo
con el que ser form ateada la fecha o la hora; por ejem plo:
DateForm at.getDa te I n s t a n c e ( D a t e F o r m a t . M E D I U M ) ;
Da t e F o r m a t . g e t D a t e l n s t a n c e ( D a t e F o r m a t . D E F A U L T , p a 1 s );
LA CLASE Arrays
La clase A r r a y s del paquete ja v a .u til contiene varios m todos static para m ani
pular m atrices. Estos m todos son: b in a ry S e a rc h . equals. fill y sort.
binarySearch
Este m todo perm ite buscar un valor en una m atriz que est ordenada ascenden
tem ente utilizando el algoritm o de bsqueda binaria. Este algoritm o ser explica
do m s adelante en otro captulo. A hora basta con saber que se trata de un
algoritm o m uy eficiente en cuanto a que el tiem po requerido para realizar una
bsqueda es m uy pequeo. L a sintaxis expresada de form a genrica para utilizar
este m todo es la siguiente:
donde m representa la m atriz, clave es el valor que se desea buscar del m ism o tipo
que los elem entos de la m atriz, y tipo es cualquier tipo de datos de los siguientes:
byte, char, short, int, long, float, d o u b le y Object.
ndice del elem ento de la m atriz donde debera encontrarse el v alo r buscado. La
expresin -{ punto de insercin) - 1" garantiza que el ndice devuelto ser m ayor
o igual que cero slo si el valor buscado es encontrado.
double[] a = 110,15.20,25.30.35.40.45,50.551;
nt i ;
= A r r a y s . b i n a r y S e a r c h ( a , 2 5 ) ; // i = 3
= A r r a y s . b i n a r y S e a r c h a , 2 7 ) ; // i = -5
= Arrays.binarySearcha. 5); // i - -1
= A r r a y s . b i n a r y S e a r c h a . 6 0 ) : // i = -11
equals
Este m todo perm ite verificar si dos m atrices son iguales. D os m atrices se consi
deran iguales cuando am bas tienen el m ism o nm ero de elem entos y en el m ism o
orden. Asim ism o, dos m atrices tam bin son consideradas iguales si sus referen
cias valen nuil. La sintaxis para utilizar este m todo expresada de form a genrica
es la siguiente:
donde m i y m 2 son m atrices del m ism o tipo y tipo es cualquier tipo de datos de
los siguientes: boolean. byte. char, short, int. long, float. d o u b le y Object.
El valor devuelto ser true si am bas m atrices son iguales y false en caso con
trario.
Com o ejem plo, puede probar los resultados que produce el siguiente cdigo:
double[] a = 1 1 0 .1 5 . 2 0 . 2 5 . 3 0 . 3 5 . 4 0 . 4 5 . 5 0 .5 5 1 :
double[] b = 1 1 0 . 1 5 . 2 0 . 2 5 . 3 0 , 3 5 . 4 0 . 4 5 . 5 0 .5 5 ) :
i f ( A r r a y s . e q u a l s ( a . b))
S y s t e m . o u t . p r i n t l n ( " S o n i g u a l e s " );
el se
S y s t e m . o u t . p r i n t l n ( " N o son i g u a l e s " ) :
fll
Este m todo perm ite asignar un valor a todos los elem entos de una m atriz, o bien
a cada elem ento de un rango especificado. La sintaxis expresada de form a genri
ca para utilizar este m todo es la siguiente:
CA PITU LO 8: M TODOS 2 3 5
double[] a = 110.15.20,25.30,35.40.45.50.55):
A r r a y s . f i l K a . 0 ) : // p o n e r l o s e l e m e n t o s d e l a m a t r i z a cero
sort
E ste m todo perm ite ordenar los elem entos de una m atriz en orden ascendente
utilizando el algoritm o quicksort. E ste algoritm o ser explicado m s adelante en
otro captulo. A hora basta con saber que se trata de un algoritm o m uy eficiente en
cuanto a que el tiem po requerido para realizar la ordenacin es m nim o. La sinta
xis expresada de form a genrica para utilizar este m todo es la siguiente:
void s o r t ( t i p o ] m)
void s o r t (tip oi'i m. int desdelnd. int hastalnd)
C om o ejem plo, puede probar los resultados que produce el siguiente cdigo:
LA CLASE Object
L a clase O b je c t es la clase raz de la jerarqua de clases de la biblioteca Java;
pertenece al paquete ja v a.lan g. A sim ism o, cualquier clase que im plem entem os en
nuestras aplicaciones pasar a ser autom ticam ente una subclase de esta clase.
Esto se traduce en que todos los m todos de O b je c t son heredados por las clases
de la biblioteca Java y p o r cualquier o tra clase que incluyam os en un program a.
T res de estos m todos (w ait, n otify y n o tify A II) soportan el control de hilos, por
lo tanto posponem os su estudio a un captulo posterior; otros m todos, com o
236 JA V A: C U R SO DE PROGRAM A CIN
En cam bio, la expresin strl.eq u a ls(str2 ) com para el contenido de los obje
tos; en este caso verifica si am bas cadenas contienen los m ism os caracteres. Esto
es as, porque el m todo e q u a ls de O b je c t ha sido sobreescrito en la clase S t r in g
para que haga esta tarea m s especfica. T odas las subclases de O b je c t deberan
sobreescribir el m todo e q u a ls para que realicen una com paracin que sea til.
String toStringO
El m todo to S tr in g de la clase O b je c t retom a: un S t r in g que alm acena el nom bre
de la clase del objeto que recibe el m ensaje to S trin g , el sm bolo \ y la repre
sentacin hexadecim al del cdigo hash del objeto. Esto es, la cadena de caracteres
sera equivalente a la proporcionada p o r la siguiente expresin:
o b j . g e t C l a s s ( ) . g e t N a m e ( ) + ' @ + I n t e g e r . t o H e x S t r i n g o b j . h a s h C o d e ) )
C uando se ejecute el ejem plo anterior la lnea som breada dar lugar al si
guiente resultado:
Test@73bf4fel
void finalize()
E ste m todo es invocado por el recolector de basura cuando Java determ ina que
no hay m s referencias a un objeto.
Este ejem plo crea un objeto S t r in g con el contenido abe . D icho proceso
puede realizarse tam bin as:
No obstante, es im portante saber cul es el com portam iento de Java ante las
dos form as expuestas de crear un objeto S trin g .
S t r i ng s t r l = " a b e " :
String str2 = "a b e ";
if (s trl.e q u a ls (str2 ))
I
// el resu ltad o es true siempre
1
if (strl = str2)
I
// e l r e s u l t a d o es true siempre
1
En este ejem plo, el resultado de strl.eq u a ls(str2 ) es siem pre true, lo cual es
lgico porque independientem ente de que se trate o no de objetos diferentes, los
contenidos son los m ism os (verem os que se trata de un nico objeto).
C A PTU LO 8: M TODOS 2 3 9
C uando se com pila la prim era lnea, Java aade el objeto S t r in g abe al rea
de m em oria destinada a tales objetos. C uando se com pila la segunda lnea no se
aade un nuevo objeto por que ya existe uno con el m ism o literal.
M em oria
abe"
Area de memoria
para objetos String
Sin em bargo, la utilizacin del operador new hace que se asigne m em oria pa
ra un nuevo objeto. P or ejem plo:
String s t r l = new S t r i n g ( a b e ) : II c r e a r un n u e v o o b j e t o
S t r i n g s t r 2 = a b e " :
if (strl .equals(str2))
I
// e l r e s u l t a d o es t r u e siempre
I
if (strl == s t r 2 )
I
// e l r e s u l t a d o es false siempre
I
C uando se com pila la prim era lnea del ejem plo anterior, Java aade el objeto
S t r in g abe alrea de m em oria destinada a tales objetos. C uando se com pila la
segunda lnea no se aade un nuevo objeto porque ya existe uno con el m ism o li
teral.
son equivalentes a:
EJERCICIOS RESUELTOS
El m todo rnd anterior tiene un parm etro de tipo int[] que perm itir pasar un
argum ento de tipo int por referencia. De esta form a, el m todo podr m odificar el
argum ento pasado con el valor del ltim o nm ero seudoaleatorio calculado, lo
que perm itir calcular el siguiente nm ero seudoaleatorio en funcin del anterior.
Se puede observar que, en realidad, el nm ero seudoaleatorio calculado es un va
lor entre 0 y 65535 y que para convertirlo a un v alor entre 0 y 1 lo dividim os por
65535; el cociente de tipo d o u b le es el valor devuelto p o r el m todo.
import j a v a . u t i 1 . * :
// G e n e r a r n m e r o s s e u d o a l e a t o r i o s
d o u b l e n;
f o r ( i n t i = 10: i ! = 0: i - - )
I
n - rnd(random);
System .out.println(n);
I
I
I
El m todo m a in del ejem plo anterior prim ero calcula un valor entre O y
65535 a partir del cual se generar el p rim er nm ero seudoaleatorio; este valor,
que es el resto de dividir el nm ero de m ilisegundos transcurridos desde el 1 de
enero de 1970 devuelto p o r el m todo g e tT im e de la clase D a te entre 65536, se
alm acena en el prim er elem ento de una m atriz denom inada random . D espus, pa
ra calcular cada nm ero seudoaleatorio, invoca al m todo rnd pasando el argu
m ento random por referencia; de esta form a, el m todo m d podr m odificarlo con
el nm ero seudoaleatorio que calcule, lo que garantizar calcular cada nm ero
seudoaleatorio en funcin del anterior.
int U m i t e S u p = 4 9 , l m i t e l n f = 1;
int n [ ] = new i n t [ 6 ] , i . k;
Arrays.sort(n);
f o r ( i = 0; i < n . l e n g t h ; i + + )
Sy ste m .o u t.p rin t(n [i] + "):
import j a v a .u t i 1 .*;
// C l a s i f i c a r l a m a t r i z
Arrays.sort(n);
// M o s t r a r l a m a t r i z
f o r ( i = 0 : i < n . l e n g t h ; i+ + )
S y s t e m . o u t . p r i n t { n [ i ] + " );
S y s t e m . o u t . p r i n t l n < );
El p rim er parm etro y el segundo del m todo F usionar son las dos m atrices
de partida, y el tercero es la m atriz que alm acenar los elem entos de las dos ante
riores.
b) C om parar los dos elem entos (uno de cada m atriz) y alm acenar en la m atriz re
sultado el m enor.
c) T o m ar el siguiente elem ento la m atriz a la que perteneca el elem ento alm ace
nado en la m atriz resultado, y volver al punto b).
int ind = 0, i n d A = 0. i n d B = 0. i n d C = 0:
if (listaA.length + 1i s t a B . 1ength = 0)
r e t u r n 0;
// F u s i o n a r l a s l i s t a s A y B en l a C
w h i l e ( i n d A < 1 i s t a A . 1 e n g t h && i n d B < 1 i s t a B . 1 e n g t h )
i f ( 1 i s t a A [ i n d A ] . c o m p a r e T o d i s t a B C i n d B ] ) < 0)
1i s t a C [ i n d C + + ] = 1i s t a A [ i n d A + + ] ;
el se
1i s t a C [ i n d C + + ] = 1 i s t a B [ i n d B + + ] ;
// L o s d o s b u c l e s s i g u i e n t e s s o n p a r a p r e v e r e l c a s o de que.
// l g i c a m e n t e una l i s t a f i n a l i z a r a n t e s q u e l a o t r a ,
f o r ( i n d = i n d A ; i n d < 1 i s t a A . 1e n g t h : i n d + + )
l i s t a C [ i n d C + + ] = 1i s t a A [ i n d ] :
return 1;
// D e c l a r a r l a m a t r i z q u e va a a l m a c e n a r e l r e s u l t a d o de
// f u s i o n a r l a s d o s a n t e r i o r e s
S t r i n g C ] l i s t a 3 - new S t r i n g [1 i s t a l . 1 e n g t h + 1 i s t a 2 . 1 e n g t h ] ;
// F u s i o n a r l i s t a l y 1 i s t a 2 y a l m a c e n a r e l r e s u l t a d o en l i s t a 3 .
// El m t o d o " F u s i o n a r " d e v o l v e r un 0 c u a n d o no s e pueda
// r e a l i z a r l a f u s i n ,
i n t i n d . r;
r = F u s i o n a r ! 1 i s t a l . 1 i s t a 2. 1 i s t a 3 > ;
// E s c r i b i r la m atriz resultante
i f ( r != 0)
I
246 JA V A: C U R SO D E PROGRAM A CIN
f o r ( i nd = 0: i n d < 1 i s t a 3 . 1 e n g t h : i n d + + )
S y s t e m . o u t . p r i n t l n ( 1 i s t a 3 [ i n d ] );
I
el se
S y s t e m . o u t . p r i n t l n < " E r r o r " );
t x x1
e = x + v + v + F +'-
P ara un valor de x dado, se calcularn y sum arn trm inos sucesivos de la serie,
hasta que el ltim o trm ino sum ado sea m enor o igual que una constante de error
predeterm inada (por ejem plo le-7). O bserve que cada trm ino es igual al anterior
p o r x/n para n = 1, 2 , 3, ... El p rim er trm ino es el 1. Para ello se pide:
import j a v a . i o . * :
p u b lic c l a s s Test
I
static d o u b l e e x p o n e n c i a l ( d o u b l e x)
(
int n - 1:
d o u b l e e x p . t r m i n o = 1;
exp = t r m i n o : // p r i m e r t r m i n o
w hile (trmino > le -7 )
I
trmino *= x/n; // s i g u i e n t e trmino
CA PTU LO 8: M TODOS 2 4 7
exp += t rm in o : // s u m a r o t r o t r m i n o
n++:
I
return ex p ;
I
EJERCICIOS PROPUESTOS
1. R ealizar un program a que se com porte com o un diccionario Ingls-Espaol; esto
es, solicitar una palabra en ingls y escribir la correspondiente palabra en espa
ol. El nm ero de parejas de palabras es variable, pero lim itado a un m xim o de
100. La longitud m xim a de cada palabra ser de 4 0 caracteres. Por ejem plo, su
poner que introducim os las siguientes parejas de palabras;
book libro
green verde
m ouse ratn
8 1 6
3 5 7
4 9 2
b) L lam e a un mtodo:
c) Escriba la cadena que sea m enor segn los n prim eros caracteres (esto es, la
que est antes por orden alfabtico).
4. R ealizar un program a que lea un conjunto de valores reales a travs del teclado,
los alm acene en una m atriz de m filas p o r n colum nas y a continuacin, visualice
la m atriz por filas.
C A PTU LO 8: M TODOS 2 4 9
La estructura de! program a estar form ada, adem s de por el m todo m ain , por
los m todos siguientes:
El parm etro m del m todo leerM atrz2D es la m atriz cuyos elem entos deseam os
leer.
El m todo sum aC olsM atriz2D devolver una m atriz unidim ensional con la suma
de las colum nas de la m atriz m de dos dim ensiones pasada com o argum ento.
[k) k\ (n k)\
/?! = /? * ( / ? - ! ) * ( - 2 )*...*2 * 1
El m todo fa cto ria l recibe com o parm etro un entero y devuelve el factorial
del m ism o,
El m todo com binaciones recibe com o parm etros dos enteros n y k, y de-
/ \
n
vuelve com o resultado el valor de
El m todo potencia recibe com o parm etros dos enteros, base y exponente, y
devuelve com o resultado el valor de baseexpo"e",e.
Programacin avanzada
Clases y paquetes
Subclases e interfaces
Excepciones
T rabajar con ficheros
Estructuras dinm icas
A lgoritm os
Hilos
CA PTU LO 9
@ F J. Ceballos/RA-MA
CLASES Y PAQUETES
S eguro que a estas alturas el trm ino clase y a le es fam iliar. En los captulos ex
puestos hasta ahora se han desarrollado aplicaciones sencillas, para introducirle
m s bien en el lenguaje y en el m anejo de la biblioteca de clases de Java que en el
d iseo de clases. No obstante, s ha tenido que quedar claro que un program a
orientado a objetos slo se com pone de objetos y que un objeto es la concrecin
de una clase. Sirva co m o ejem plo las aplicaciones que hem os desarrollado: todas
estn basadas en una clase aplicacin. Es hora pues de entrar con detalle en la
program acin orientada a objetos la cual tiene un elem ento bsico: la clase. En
este captulo, aprenderem os tam bin a organizar las clases en paquetes, lo que su
pone tam bin un nivel m s de proteccin para las m ismas.
U na clase es un tipo definido por el usuario que describe los atributos y los m to
dos de los objetos que se crearn a partir de la m ism a. Los atributos definen el
estado de un determ inado objeto y los m todos son las operaciones que definen su
com portam iento. Form an parte de estos m todos los constructores, que perm iten
iniciar un objeto, y los destructores, que perm iten destruirlo. Los atributos y los
m todos se denom inan en general m iem bros de la clase.
class Circulo
I
// m i e m b r o s p r i v a d o s
p r i v a t e d o u b l e x. y : // c o o r d e n a d a s d e l c e n t r o
p riv a t e double ra d io : II r a d i o d e l c i r c u l o
II m i e m b r o s p r o t e g i d o s
protected void m sgE sN e gativ o()
I
S y ste m .o u t .p rin tln ( "El r a d io e s n e g a t i v o . Se c o n v ie r t e a p o s i t i v o ):
// m ie m b ro s p b l i c o s
p u b l i c C l r c u l o O I ) // c o n s t r u c t o r s i n p a r m e t r o s
p u b l i c C i r c u l o t d o u b l e e x , d o u b l e c y . d o u b l e r ) // c o n s t r u c t o r
I
x = ex; y cy:
i f ( r < 0)
I
m s g E s N e g a t i v o ( ):
r = -r;
1
r a d i o = r;
p u b lic double r e a C I r c u l o ( )
I
return Math.PI * radio * radio;
C A PTU LO 9: CL A SES Y PAQUETES 2 5 5
E ste ejem plo define un nuevo tipo de datos. Crculo, que puede ser utilizado
dentro de un program a fuente exactam ente igual que cualquier otro tipo. Un o b
jeto de la clase C rculo tendr los atributos x , y y radio, los m todos m sgEsN ega-
tivo, lo n g C ircu n feren d a y reaC rculo, y dos constructores Crculo, uno sin
parm etros y o tro con ellos.
Atributos
L os atributos constituyen la estructura interna de los objetos de una clase. Para
declarar un atributo, proceda exactam ente igual que ha hecho para declarar cual
quier otra variable dentro de un m todo. Por ejem plo:
class Circulo
p r i v a t e do u b le x, y;
p riv a t e double radio:
II...
I
En una clase, cada atributo debe tener un nom bre nico. En cam bio, se puede
u tilizar el m ism o nom bre con atributos, en general con m iem bros, que pertenez
can a diferentes clases.
class Crculo
[
private d o u b l e x, y;
private d o u b l e r a d i o = 1:
// ...
l
Tam bin podem os declarar com o atributos de una clase, referencias a otros
objetos de clases existentes. El siguiente ejem plo define la clase P unto y despus
declara el atributo centro de Crculo, de la clase Punto.
class Punto
(
private d o u b l e x. y:
class Circulo
P ara definir un m todo m iem bro de una clase, proceda exactam ente igual que
ha hecho para definir cualquier otro m todo en las aplicaciones realizadas en los
captulos anteriores. N o olvide que una aplicacin se basa en una clase. Como
ejem plo puede observar los m todos C rculo y longC ircunferencia de la clase
Crculo.
class Circulo
I
II . . .
p u b l i c C 1 r c u l o ( d o u b l e ex. double cy. double r) // c o n s t r u c t o r
I
x = ex: y = cy:
i f ( r < 0)
I
m sgEsNegati v o ( ):
r = -r :
I
r a d i o = r;
l
En Java un m todo es una definicin incluida siem pre dentro del cuerpo de
una clase. A sim ism o, recuerde que los m todos no se pueden anidar.
El concepto de clase incluye la idea de ocultacin de datos, que bsicam ente con
siste en que no se puede acceder a los atributos directam ente, sino que hay que
hacerlo a travs de m todos de la clase. Esto quiere decir que, de form a general, el
usuario de la clase slo tendr acceso a uno o m s m todos que le perm itirn ac
ceder a los m iem bros privados, ignorando la disposicin de stos (dichos m todos
se denom inan m todos de acceso). De esta form a se consiguen dos objetivos im
portantes:
Piense que si el objetivo uno no se cum pliera, cuando se diera el objetivo dos
el usuario tendra que rcescribir el cdigo que hubiera desarrollado basndose en
la eslructura interna d e los datos.
Para controlar el acceso a los m iem bros de una clase. Java provee las palabras
clave p rv a te (privado), p ro te c te d (protegido) y p u b lic (pblico), aunque tam
bin es posible om itirlas (acceso predeterm inado). E stas palabras clave, denom i
nadas m odificadores d e acceso, son utilizadas para indicar el tipo de acceso
perm itido a cada m iem bro de la clase. Si observam os la clase C irculo expuesta
anteriorm ente identificam os m iem bros privados, protegidos y pblicos.
Acceso predeterminado
class CRacional
I
i n t Numerador:
i n t Denominador:
N u me r a d o r = num:
i f (den = 0 ) den - 1; //el d e n o m i n a d o r no p u e d e s e r c e r o
D e n o m i n a d o r = den:
I
void V i s u a l i z a r R a c i o n a l ()
(
System .out.printn(Num erador + "/ " + D e n o m i n a d o r ):
Un m iem bro de una clase declarado sin m odificadores que indiquen el control
de acceso, puede ser accedido por cualquier clase perteneciente al m ism o paquete.
N inguna otra clase, o subclase, fuera de este paquete puede tener acceso a estos
m iem bros (estudiarem os las subclases en el captulo siguiente). R ecuerde que las
clases im plem entadas en nuestros program as pertenecen, p o r om isin, al paquete
predeterm inado (vea en el captulo 4 Paquetes y proteccin de clases ). De esta
form a Jav a asegura q ue toda clase pertenece a un paquete.
Acceso pblico
Un m iem bro declarado p u b lic (pblico) est accesible para cualquier otra clase o
subclase que necesite utilizarlo. La interfaz pblica de una clase, o sim plem ente
interfaz, est form ada por todos los m iem bros pblicos de la m ism a. Asim ism o,
los atributos s ta tic de la clase generalm ente son declarados pblicos. Sirva com o
ejem plo el atributo P l de la clase M ath : p u b lic static fin a l double Pl.
Acceso privado
Un m iem bro declarado p riv a te (privado) es accesible solam ente por los m todos
de su propia clase. Esto significa que no puede ser accedido por los m todos de
cualquier otra clase, incluidas las subclases.
Acceso protegido
Un m iem bro declarado p ro te c te d (protegido) se com porta exactam ente igual que
uno privado para los m todos de cualquier otra clase, excepto para los m todos de
las clases del m ism o paquete o de sus subclases con independencia del paquete al
que pertenezcan, para las que se com porta com o un m iem bro pblico.
C A PTU LO 9: CL A SES Y PAQUETES 2 5 9
Parece lgico que la estructura de datos de un objeto fecha est form ada por
los m iem bros da, m es y ao, y perm anezca oculta al usuario. Por otra parte, las
operaciones sobre estos objetos tendrn que perm itir asignar una fecha, m todo
asignarF echa, obtener una fecha de un objeto existente, m todo obtenerFecha, y
verificar si la fecha que se quiere asignar es correcta, m todo fechaC orrecta. Es
tos tres m todos form arn la interfaz pblica. C uando el da corresponda al mes
de febrero, el m todo fechaC orrecta necesitar com probar si el ao es bisiesto pa
ra lo que aadirem os el m todo bisiesto. Ya que un usuario no necesita acceder a
este m todo, lo declararem os protegido con la intencin de que, en un futuro, s
pueda ser accedido desde una subclase. Segn lo expuesto, podem os escribir una
clase denom inada C Fecha as:
// M t o d o s
p r o t e c t e d b o o l e a n bi s i e s t o ()
I
// c u e r p o d e l m t o d o
I
public void asignarFechatint dd . i n t mm. int aaaa)
I
// c u e r p o d e l mt odo
)
public void obte nerFecha (int[] fecha)
I
II c u e r p o d e l mt odo
I
public b o o l e a n f e c h a C o r r e c t a ()
II c u e r p o d e l m t o d o
2 6 0 JA V A : C U R SO DE PROGRAM A CIN
El paso siguiente es definir cada uno de los m todos. Al h ablar de los m odifi
cadores de acceso qued claro que cada uno de los m todos de una clase tiene ac
ceso directo al resto de los m iem bros. Segn esto, la definicin del m todo
asignarF echa puede escribirse as:
O bserve que por ser asignarF echa un m todo m iem bro de la clase C Fecha,
puede acceder directam ente a los atributos da, m es y ao de su m ism a clase, in
dependientem ente de que sean privados. Estos atributos correspondern en cada
caso al o b jeto que recibe el m ensaje asignarF echa (objeto para el que se invoca el
m todo; vea m s adelante, en este m ism o captulo, la referencia im plcita this).
Por ejem plo, si declaram os los objetos fe c h a I y fe c h a 2 de la clase C F echa, y en
viam os a fe c h a l el m ensaje asignarF echa:
f e c h a l . a s i g n a r F e c h a ( d d . mm. a a a a ) :
com o respuesta a este m ensaje, se ejecuta el m todo asignarF echa que asigna los
datos dd, m m y aaaa al objeto f e c h a l ; esto es, a fe c h a l.d a , fe c h a l.m e s y f e
chal.ao-, y si a fe c h a 2 le enviam os tam bin el m ensaje asignarFecha:
f e c h a 2 . a s i g n a r F e c h a ( d d , mm, a a a a ) :
com o respuesta a este m ensaje, se ejecuta el m todo asignarF echa que asigna los
datos dd, m m y aaaa al objeto fe c h a l: esto es, a fe c h a !.d a , fe c h a l.m e s y f e
ch a l.a o .
/////////////////////////////////////////////////////////////////
// D e f i n i c i n de l a c l a s e CFecha
p u b l i c c l a s s C F ec h a
I
// A t r i b u t o s
private int da. mes , ao;
// M t o d o s
protected boolean b i s i e s t o ! )
I
return ((ao X 4 0 ) && ( a o % 1 00 ! = 0 ) || ( a o X 4 0 0 0)):
C A PTU LO 9: CL A SES Y PA Q U ETES 2 6 1
R esum iendo: la funcionalidad de esta clase est soportada por los atributos
privados da, m es y ao, y por los m todos asignar Fecha, obtenerFecha, fe c h a -
Correcla y bisiesto.
El m todo pblico asignarF echa, recibe tres enteros y los alm acena en los
atributos d a. m es y ao del objeto que recibe el m ensaje asignarF echa (objeto
para el que se invoca dicho m todo).
El m todo pblico obtenerFecha, perm ite extraer los datos da, m es y ao del
objeto que recibe el m ensaje obtenerFecha.
262 JA V A : C U R SO D E PROGRAM A CIN
MTODOS SOBRECARGADOS
En los captulos anteriores, al trabajar con las clases de la biblioteca de Java nos
hem os encontrado con clases que im plem entan varias veces el m ism o m todo. Por
ejem plo, en el captulo 5 dijim os que la clase In p u t S t r e a m im plem enta tres for
m as del m todo read:
y que la clase P rin tS tr e a m im plem enta m ltiples form as de los m todos p rin t y
p rin tln : por ejem plo:
Pues bien, cuando en una clase un m ism o m todo se define varias veces con
distinto nm ero de parm etros, o bien con el m ism o nm ero de parm etros pero
diferencindose una definicin de otra en que al m enos un parm etro es de un tipo
diferente, se dice que el m todo est sobrecargado.
Los m todos sobrecargados pueden diferir tam bin en el tipo del v alor retor
nado. A hora bien, el com pilador Java no adm ite que se declararen dos m todos
que slo difieran en el tipo del v alor retornado; deben diferir tam bin en la lista de
parm etros; esto es, lo que im porta son el nm ero y el tipo de los parm etros.
C om o ejem plo, sobrecargarem os el m todo asignarF echa p ara que pueda ser
invocado con cero argum entos; con un argum ento, el da; con dos argum entos, el
da y el m es; y con tres argum entos, el da, el m es y el ao. Los datos da, m es o
ao om itidos en cualquiera de los casos, sern obtenidos de la fecha actual pro
porcionada por el sistem a.
f e c h a . a s i g n a r F e c h a f ):
fecha.asignarFecha(dla):
f e c h a . a s i g n a r F e c h a ( d 1 a . mes):
f e c h a , a s i g n a r F e c h a ( d i a . mes . a o ) ;
Si el com pilador Java no encontrara un m todo exactam ente con los m ism os
tipos de argum entos especificados en la llam ada, realizara sobre dichos argu
m entos las conversiones im plcitas perm itidas entre tipos, tratando de adaptarlos a
alguna de las definiciones existentes del m todo. Si este intento fracasa, entonces
se producir un error.
Para com probar que la clase C Fecha que acabam os de disear trabaja correc
tam ente, podem os escribir una aplicacin Test segn se m uestra a continuacin:
/////////////////////////////////////////////////////////////////
// A p l i c a c i n que u t i l i z a la c l a s e CFecha
//
public class Test
I
// V i s u a l i z a r una f e c h a
public sta t ic void visualizarFecha(C Fech a fecha)
I
i n t [ ] f = new i n t [ 3 ] ;
f e c h a .o b t e n e r F e c h a ( f ) :
System .out.p rintln(f[0] + "/" + f[l] + "/" + f[2]);
// E s t a b l e c e r una f e c h a , v e r i f i c a r l a y v i s u a l i z a r l a
p u b lic s t a t ic void m a in (S trin g [] args)
I
C F ec h a f e c h a - new C F e c h a ) : // o b j e t o d e t i p o C F ech a
i n t d a . me s , a o :
do
I
S y s t e m . o u t .p r in t t "d a . ## : "): da - L e e r . d a t o I n t ( ):
System, out. p r i n t C m e s . M : "): mes - L e e r . d a t o l n t t );
CA PTU LO 9: CL A SES Y PA Q U ETES 2 6 5
visualizarFecha fecha ):
N otar que la clase C Fecha declara los atributos da, m es y a o privados. Esto
quiere decir que slo son accesibles por los m todos de su clase. Si un m todo de
otra clase intenta acceder a uno de estos atributos, el com pilador genera un error.
En cam bio, com o C Fecha y Test pertenecen al m ism o paquete, al predeterm ina
do. los m todos de Test s podran acceder el m todo protegido bisiesto de C Fe
cha. Por ejemplo:
En cam bio, los m todos asignarF echa, obtenerF echa y fech a C o rrecta son
pblicos. Por lo tanto, son accesibles, adem s de p o r los m todos de su clase, por
cualquier otro m todo de otra clase. S irva com o ejem plo el m todo visualizarFe-
cha de la clase Test. Este m todo presenta en la salida estndar la fecha alm ace
nada en el objeto que se le pasa com o argum ento. O bserve que tiene que invocar
al m todo obtenerF echa para acceder a los datos de un objeto C Fecha. Esto es as
porque un m todo que no es m iem bro de la clase del objeto, no tiene acceso a sus
datos privados.
Por om isin una clase tiene el nivel de acceso de p a q u ete; por ejem plo, la cla
se C rculo expuesta anteriorm ente tiene este nivel de acceso (no ha sido declarada
266 JA VA: CU R SO DE PROGRAM A CIN
p u b lic, por lo que tiene el nivel de acceso de paquete). En cam bio, cuando se de
sea que una clase tenga nivel de acceso p b lico , hay que calificarla com o tal utili
zando la palabra reservada p u b lic: la clase C Fecha del ejem plo anterior tiene este
nivel de acceso. O tro ejem plo: la clase L eer utilizada desde la clase Test anterior
es pblica (en nuestro caso est ubicada en la carpeta m isC lases especificada por
una de las rutas de la variable de entorno CLASSPATH)-, pero aunque no hubiese
sido pblica tam bin se podra u tilizar desde la clase Test, ya que am bas pertene
cen al m ism o paquete, al predeterm inado.
REFERENCIA this
f e c h a l . a s i g n a r F e c h a t d a . mes . ao):
S egn lo expuesto, el m todo asignarF echa podra ser definido tam bin com o
se m uestra a continuacin:
do
w hile ( ! fecha.fechaCorrecta()):
En este caso, igual que en el ejem plo anterior, el m todo fechaC orrecta cono
ce con exactitud el objeto sobre el que tiene que actuar, puesto que se ha expresa
do explcitam ente. Pero qu pasa con el m todo bisiesto que se encuentra sin
referencia directa alguna en el cuerpo del m todo fech a C o rrecta ?
En este o tro caso, la llam ada no es explcita com o en el caso anterior. L o que
ocurre en la realidad es que todas las referencias a los atributos y m todos del
objeto para el que se invoc el m todo fech a C o rrecta (objeto que recibi el m en
saje fech a C o rrecta), son im plcitam ente realizadas a travs de th is. S egn esto, la
sentencia if anterior podra escribirse tam bin as:
N orm alm ente en un m todo no es necesario utilizar esta referencia para acce
der a los m iem bros del objeto im plcito, pero es til cuando haya que devolver
una referencia al mismo.
static p ara hacer q ue la constante sea de la clase y no del objeto. D eclarar una re
ferencia fin a l a un objeto supone que esa referencia slo pueda utilizarse para re-
ferenciar ese objeto; cualquier intento accidental de m odificar dicha referencia
para q ue seale a otro objeto ser detectado durante la com pilacin, en vez de
causar errores durante la ejecucin. Por ejem plo;
f i n a l C F e c h a c u m p l e a o s = new C F e c h a O ;
C F e c h a f e c h a = new C F e c h a O :
// ...
cumpleaos = fecha: II Error: referencia constante
Q uin puede cam biar el m todo? U na subclase que intente redefinirlo, pero
slo podr hacerlo si el m todo no es fin a l (estudiarem os las subclases en el ca
ptulo siguiente).
Q uizs cuando desarrolle una clase por prim era v ez no tenga m uchas razones
para d ecid ir qu m todos puede declarar final. H galo cuando necesite que la cla
se se ejecute con m s rapidez, pero pensando en la lim itacin que est im ponien
do a las posibles subclases de esa clase. La biblioteca de Java declara final
m uchos de los m todos que se utilizan con m ayor frecuencia con la intencin de
obtener una m ayor eficiencia durante la ejecucin.
Una clase, tam bin se puede declarar final. Por ejem plo:
C uando una clase se declara fin a l estam os im pidiendo que de esa clase se
puedan derivar subclases. A dem s todos sus m todos se convierten autom tica
m ente en final. N o hay m uchas razones para hacer esto ya que sacrificam os una
de las caractersticas m s potentes de la POO: la reutilizacin del cdigo. En al
gunos casos excepcionales, com o ocurre con la clase M a t h de la biblioteca de Ja
va, puede ser beneficioso por las razones expuestas al h ablar de los m todos final.
C A P T U L O 9: CL A SES Y PAQUETES 2 6 9
INICIACIN DE UN OBJETO
Sabem os que un objeto consta de una estructura interna (los atributos) y de una
interfaz que perm ite acceder y m anipular tal estructura (los m todos). Ahora,
cm o se construye un objeto de una clase cualquiera? Pues, de form a anloga a
com o se construye cualquier otra variable de un tipo predefinido. Por ejem plo:
i n t edad ;
Este ejem plo define la variable ed a d del tipo predefinido int. En este caso, el
com pilador autom ticam ente reserva m em oria para su ubicacin, le asigna un
valor (cero si se trata de un atributo de una clase, o indeterm inado si es local a un
m todo) y proceder a su destruccin, cuando el flujo de ejecucin vaya fuera del
m bito donde haya sido definida.
E sto nos hace pensar en la idea de que de alguna m anera el com pilador llama
a un m todo de iniciacin, constructor, para iniciar cada una de las variables de
claradas, y a un m todo de elim inacin, destructor, para liberar el espacio ocupa
do por dichas variables, ju sto al salir del m bito en el que han sido definidas.
Pues bien, con un objeto de una clase ocurre lo m ism o. Por ejem plo,
C Fech a f e c h a = new C F e c h a O :
Constructor
En Java, una form a de asegurar que los objetos siem pre contengan valores vlidos
es escribir un constructor. Un constructor es un m todo especial de una clase que
es llam ado autom ticam ente siem pre que se crea un objeto de la m ism a. Su fun
cin es iniciar nuevos objetos de su clase. C uando se crea un objeto, Java hace lo
siguiente:
270 JA V A: C U R SO DE PROGRAM A CIN
D ado q ue los constructores son m todos, adm iten parm etros igual que stos.
C uando en una clase no especificam os ningn constructor, el com pilador aade
uno pblico por om isin sin parm etros.
Un constructor se distingue fcilm ente porque tiene el m ism o nom bre que la
clase a la q ue pertenece (por ejem plo, el constructor para la clase C Fecha se de
nom ina tam bin C Fecha), no se hereda, no puede retom ar un valor (incluyendo
v o id ) y no puede ser declarado fin al, sta tic , a b s tra c t, s y n c h ro n iz e d o n a tiv e (los
dos prim eros m odificadores ya son conocidos; los otros lo sern en la m edida que
am pliem os nuestros conocim ientos sobre Java).
public c la ss CFecha
I
// A t r i b u t o s
p r v a t e i n t d a , mes , ao;
// M t o d o s
p u b l i c C F e c h a ( i n t dd. i n t mm. int aaaa) // c o n s t r u c t o r
I
d a = dd ; mes = mm; a o = a a a a :
i f ( ! f e c h a C o r r e c t a ( ))
1
System .out.println("Fecha incorrecta. Se a s i g n a la actual.");
a s i g n a r F e c h a t ):
1
1
// ...
C A P T U L O 9: CLA SES Y PAQUETES 2 7 1
C uando una clase tiene un constructor, ste ser invocado autom ticam ente
siem pre que se cree un nuevo objeto de esa clase. El objeto se considera construi
do con ios valores p o r om isin ju sto antes de iniciarse la ejecucin del construc
tor. P o r lo tanto, a continuacin, desde el cuerpo del constructor segn se puede
observar en el ejem plo anterior, es posible asignar valores a sus atributos, invocar
a los m todos de su clase, o bien llam ar a m todos de otros objetos.
En el caso de que el constructor tenga parm etros, para crear un nuevo objeto
hay que especificar la lista de argum entos correspondiente entre los parntesis que
siguen al nom bre de la clase del objeto. El siguiente ejem plo m uestra esto con cla
ridad:
// V i s u a l i z a r una f e c h a
p u b lic s t a t i c void v is u a liz a rF e c h a (C F e c h a fecha)
I
i n t [] f = new i n t [ 3 ] :
fecha.obtenerFecha(f);
System .out.pri n t l n ( f [0] + "/ " + f [1] + "/" + f [2]):
I
Este ejem plo define un objeto fe c h a e inicia sus datos m iem bro da, m es y
ao con los valores 1, 3 y 2002, respectivam ente. Para ello, invoca al constructor
C Fecha(int dd, int mm, int a a a a ), le pasa los argum entos 1, 3 y 2002 y ejecuta el
cdigo que se especifica en el cuerpo del m ism o. U na vez construido el objeto, vi
sualizam os su contenido haciendo uso d e un m todo del m ism o que perm ite obte
ner sus atributos. La siguiente lnea es la salida de la aplicacin anterior:
1 / 3 / 2 00 2
CF e c h a o t r a F e c h a = new C F e c h a O ;
public CFechaO // c o n s t r u c t o r
I
asignarFechaO ; // a s i g n a r f e c h a actual
Por ejem plo, aplicando lo expuesto, podem os aadir a la clase CFecha cons
tructores para iniciar un objeto, por om isin con la fecha actual proporcionada por
la funcin asignarF echa sin parm etros, o bien especificando slo el da, o el da
y el m es, o el da, el m es y el ao; los valores no especificados se obtendrn de la
fecha actual del sistem a proporcionada por asignarFecha. El cdigo siguiente
m uestra las distintas sobrecargas que satisfacen lo anteriorm ente expuesto:
Es posible escribir un m todo que tenga el m ism o nom bre que el constructor;
lgicam ente, a diferencia de ste, ahora hay que especificar el tipo del valor retor
nado. N o obstante, esta form a de proceder no es aconsejable porque puede crear
confusin a la hora de interpretar el cdigo de la clase. P or ejem plo:
Llamar a un constructor
A diferencia de los otros m todos de la clase, un constructor no puede ser invoca
do directam ente, pero s indirectam ente a travs de th is. Esto perm ite utilizar la
tcnica de m todo abreviado, expuesta al hablar de m todos sobrecargados, tam
bin con los constructores. Para llam ar a un constructor en la clase actual desde
otro constructor utilice la siguiente sintaxis:
public C F e c h a t i n t dd) // c o n s t r u c t o r
t h i s O ; / / i n v o c a a l c o n s t r u c t o r C F e c h a s i n p a r m e t r o s
d 1a = d d :
i f ( I f e c h a C o r r e c t a t ))
I
System .out.printlnt"Fecha incorrecta. Se a s i g n a la actual."):
a s i g n a r F e c h a ):
Asignacin de objetos
N o olvide que cuando trabaja con objetos lo que realm ente m anipula desde cu al
quier m todo son referencias a los objetos. P or ejem plo:
C F ec h a f e c h a l - new CFechaO;
C F ec h a f e c h a 2 - new CFecha(15):
C F ec h a f e c h a 3 - new CFecha(22. 3):
C F e c h a f e c h a 4 - f e c h a l :
f e c h a 3 - f e c h a 2 :
El m todo copiar copia m iem bro a m iem bro el objeto pasado com o argu
m ento en el objeto que recibe el m ensaje copiar. P or ejem plo, la siguiente lnea de
cdigo copia el objeto fe c h a 2 en el objeto fe c h a 1.
fechal.copiar(fecha2);
fecha2.copiar(fecha3);
fecha 1 . c o p i a r ( f e c h a 2 ) :
Pero qu podem os hacer para poder escribir las dos lneas anteriores en una
sola? E sto es, para poder escribir:
f e c h a l . c o p i a r ( f e c h a 2 . c o p i a r ( f e c h a 3 ) ):
Constructor copia
O tra form a de iniciar un objeto es asignndole otro objeto de su m ism a clase en el
m om ento de su creacin. Lgicam ente, si se crea un objeto tiene que intervenir un
constructor. El prototipo para este constructor es de la forma:
276 JA V A: C U R S O D E PROGRAM A CIN
C om o ejem plo, aada un constructor copia a la clase C Fecha. ste ser com o
se indica a continuacin:
p u b l i c C F e c h a l C F e c h a o b j ) // c o n s t r u c t o r copia
I
da = obj.di a :
mes = o b j . m e s :
ao = o b j . a o :
I
C F ec h a f e c h a l = new C F e c h a d . 3. 2 0 0 2 ) :
C F ec h a f e c h a 2 = new C F e c h a f e c h a l );
E ste ejem plo crea e inicia un objeto fe c h a l y a continuacin crea otro objeto
fe c h a 2 inicindole con fe c h a l. A diferencia del m todo copiar expuesto en el
apartado anterior, inicialm ente aqu slo existe un objeto (fechal):; despus se crea
otro objeto (fech a 2 ) y se inicia con el prim ero.
DESTRUCCIN DE OBJETOS
De la m ism a form a que existe un m todo que se ejecuta autom ticam ente cada
vez que se construye un objeto, tam bin existe un m todo que se invoca autom ti
cam ente cada vez que se destruye. E ste m todo recibe el nom bre genrico de
d estructor y en el caso concreto de Java se corresponde con el m todo finalize.
Un objeto es destruido autom ticam ente cuando se elim inan todas las referen
cias al m ism o. U na referencia a un objeto puede ser elim inada porque el flujo de
ejecucin salga fuera del m bito donde ella est declarada, o porque explcita
m ente se le asigne el valor nuil.
Destructor
Un d estructor es un m todo especial de una clase que se ejecuta antes de que un
objeto de esa clase sea elim inado fsicam ente de la m em oria. Un destructor se
distingue fcilm ente porque tiene el nom bre predeterm inado finalize. C uando en
una clase no especificam os un destructor, el com pilador proporciona uno a travs
de la clase O b je c t cuya sintaxis es la siguiente:
Para d efinir un destructor en una clase tiene que reescribir el m todo anterior.
A diferencia de lo que ocurra con los constructores, en una clase slo es posible
definir un destructor. En el cuerpo del m ism o puede escribir cualquier operacin
que quiera realizar relacionada con el objeto que se vaya a destruir.
R esum iendo: un destructor es invocado autom ticam ente ju sto antes de que el
objeto sea recolectado com o basura por el recolector de basura de Java. Y
cundo ocurre esto? C uando no queden referencias al objeto.
public c la ss CFecha
I
// ...
public c la s s Test
I
// V i s u a l i z a r una f e c h a
278 JA VA: C U R S O DE PRO G R A M A CI N
Si una clase tiene m iem bros que son objetos de otras clases, su destructor se
ejecuta antes que los destructores de los objetos m iem bro. En otras palabras, el
orden de destruccin es inverso al orden de construccin.
Un destructor tam bin se puede llam ar explcitam ente as: objeto. finalize().
Sin em bargo, invocar a finalize no activa un objeto para que sea enviado a la
basura. Slo cuando se elim inan todas las referencias que apuntan al m ism o, ste
se m arca com o destruible.
CA PTU LO 9: C L A SES Y PAQUETES 2 7 9
A hora bien, si desea forzar una com pleta recoleccin de basura (m arcar y ba
rrer), puede hacerlo llam ando al m todo ge (garbage collector: recolector de ba
sura) de la clase S ystem . P or ejem plo:
fecha.obtenerFecha(f);
S y stem .o ut.p r i n t n < f [0] + "/" + f[l] + "/" + f[2]);
1
P ara ver lo expuesto con detalle, vam os a escribir una clase C V ector para
construir objetos que representen m atrices num ricas con un nm ero cualquiera
de elem entos. P or lo tanto, sera inapropiado definir com o m iem bro privado de la
clase C V ector una m atriz con un nm ero fijo de elem entos. E n su lugar, definire
mos una referencia, vector, a una m atriz de tipo d o u b le, p o r ejem plo, para d es
pus asignar dinm icam ente la cantidad de m em oria necesaria para la m atriz.
o b je to C V e c to r
S X m atriz
v e c to r 1 -*
..........
n E le m e n to s J
V J
Y p o r los m todos:
constructores para crear un objeto C V ector con un nm ero de elem entos pre
determ inado, con un nm ero de elem entos especificado, a partir de una m atriz
unidim ensional, o bien a partir de otro objeto CVector.
public C V e c t o r t ) // n m ero de e l e m e n t o s p o r o m i s i n : 10
I
n E l e m e n t o s = 10:
v e c t o r = new d o u b l e [ n E 1e m e n t o s ] :
p u b lic C V ector(C V e c to r v) // c o n s t r u c t o r c o p i a
I
n E l e m e n t o s = v . n E 1e m e n t o s :
v e c t o r = new d o u b l e [ n E l e m e n t o s ] :
// C o p i a r e l o b j e t o v
f o r ( i n t i = 0: i < nElem entos: i + + )
vectorfi] = v.vector[i]
I
O bservar que este m todo adem s de copiar los atributos del objeto v en el
objeto referenciado por th is, copia tam bin los valores de la m atriz; si no hi
ciera esto ltim o tendram os una sola m atriz referenciada p o r dos objetos.
co p ia r: m todo que perm ite asignar un objeto C V ector a otro. O bservar que
este m todo realiza el m ism o proceso que el constructor copia; adem s, retor
na una referencia al objeto resultante de la copia.
p o n erV a lo rE n: m todo que perm ite asignar un dato al elem ento especificado
de un objeto CVector.
p u b l i c v o i d p o n e rV a lo rE n i n t i . d o u b le v a l o r ) I v e c t o r [ i ] = v a l o r ; I
valorEn: m todo que devuelve el dato alm acenado en el elem ento especifica
do de un o bjeto CVector.
/////////////////////////////////////////////////////////////////
// D e f i n i c i n de l a clase CVector
II
public class CVector
I
private double[] vector; // m a t r i z v e c t o r
private in t nElementos; II n m ero de e l e m e n t o s de l a matriz
public C V e c t o r d o u b l e [ ] m) // c r e a un C V e c t o r d e s d e una m a t r i z
(
nEle mentos = m .length ;
v e c t o r = new d o u b l e [ n E 1e m e n t o s ] :
// C o p i a r l o s e l e m e n t o s de l a m a t r i z m
f o r ( i n t i = 0; i < nElem entos: i + + )
v e c t o r i ] = m [ i ]:
p u b lic CVector c o p ia rC V e c to r v) // c o p i a un C V e c t o r en o t r o
I
n E l e m e n t o s = v . n E 1e m e n t o s ;
v e c t o r = new d o u b l e [ n E 1e m e n t o s ] ;
II C o p i a r e l o b j e t o v
f o r ( i n t i = 0: i < n E l e m e n t o s ; i + + )
vector[i] = v.vector[i]
return this;
Para probar la clase expuesta escriba, por ejem plo, la siguiente aplicacin:
/////////////////////////////////////////////////////////////////
// A p l i c a c i n q u e u t i l i z a la clase CVector
//
public class Test
I
// V i s u a l i z a r un v e c t o r
p u b l i c s t a t i c v o id v i s u a 1i z a r V e c t o r ( C V e c t o r v)
I
i n t ne = v . 1o n g i tudC );
f o r ( i n t i = 0: i < ne; 1 + + )
System .out.p r i n t ( v .valo r E n ( i ) + " ");
S y s t e m . o u t . p r i n t l n ( ):
C V e c t o r v e c t o r 3 = new C V e c t o r ( v e c t o r 2 );
vi sual i z a r V e c t o r lv e c t o r 3):
d o u b l e x [ ] = I 1, 2 , 3. 4, 5 . 6 . 7 I : // m a t r i z x
C V e c t o r v e c t o r 4 = new C V e c t o r ( x ) :
v i s u a l i z a r V e c t o r v e c t o r 4 );
llam a al constructor C V ector(int ne) y crea un objeto ve cto rl con 5 elem entos.
Las lneas:
C V e c t o r v e c t o r 2 = new C V e c t o r O ;
CA PTU LO 9: CL A SES Y PA Q U ETES 2 8 5
llam an al co nstructor C V ector sin argum entos y crea un objeto vector2 con 10
elem entos por om isin. D espus asigna valores a cada uno de los elem entos de
vector2. L a lnea:
C V e c t o r v e c t o r 3 = new C V e c t o r t v e c t o r 2 ) ;
llam a al constructor copia y crea un objeto vector3 iniciado con los datos del o b
je to vector2. Las lneas:
double x [ ] - 1 1 . 2 . 3 . 4 . 5. 6. 7 I : 7/ m a t r i z x
C V e c t o r v e c t o r 4 = new C V e c t o r ( x ) ;
C om o se puede observar, cada vez que se crea un objeto es llam ado autom ti
cam ente un constructor, lo que garantiza la iniciacin del objeto. El que se llam e a
uno o a o tro constructor, depende del nm ero y tipo de argum entos especificados.
C uando el flujo de ejecucin sale fuera del m bito donde ha sido definido un
objeto C V ector, el recolector de basura m arcar y barrer tanto el objeto com o la
m atriz referenciada p o r el m ism o, liberando la m em oria ocupada.
Sin em bargo, una clase con m iem bros que son referencias a otros objetos,
com o es C Vector, potencialm ente tiene problem as. Para com probarlo, suponga
que al diseador de la clase C V ector se le hubiera ocurrido escribir el constructor
copia as:
public CVector(CVector v) // c o n s t r u c t o r c o p i a
I
nEle mentos = v . n E1e m e n to s:
vector = v.vector;
d o u b l e x [ ] = I 1 , 2 , 3 . 4 . 5. 6. 7 (; // m a t r i z x
C V e c t o r v e c t o r l = new C V e c t o r ( x ) :
v i s u a l i z a r V e c t o r ( v e c t o r l ) ; // e s c r i b e 1 2 3 4 5 6 7
f o r ( i n t i = 0: i < v e c t o r 2 . l o n g i t u d * ) : i + + )
v e c t o r 2 . p o n e r V a l o r E n ( i . v e c t o r 2 . v a l o r E n t i ) * 10):
v i s u a l i z a r V e c t o r ( v e c t o r 2 ) ; // e s c r i b e 10 2 0 3 0 4 0 5 0 6 0 70
I
// v e c t o r 2 ha s i d o d e s t r u i d o
v i s u a l i z a r V e c t o r { v e c t o r l ); // e s c r i b e 10 2 0 3 0 4 0 50 6 0 70
Ahora el m todo m a in crea un objeto ve cto rl iniciado con los valores de una
m atriz x e incluye un bloque que crea un nuevo objeto vector2 a partir de v e c to r l,
para lo cual se invoca al constructor copia.
O bserve que ahora este constructor sim plem ente copia los atributos del objeto
v en los correspondientes atributos del nuevo objeto creado. P or lo tanto, el resul
tado de una sentencia com o:
C V e c t o r v e c t o r 2 = new C V e c t o r v e c t o r l );
v e c to rl ve c to r2
m a triz
c_ _ _ v e c to r
-c_ _ _ vecto r
n E le m e n to s [ lE le m e n to s
Piense ahora qu suceder cuando el flujo de ejecucin salga fuera del mbito
de vecto rl. Pues que el objeto v e c to r l ser enviado a la basura y elim inado por el
recolector de basura. S er enviado tam bin a la basura el objeto m atriz referen-
CA PTU LO 9 : CL A SES Y PAQUETES 2 8 7
Esta m ism a teora es aplicable al m todo copiar. Esto significa que debem os
poner un especial inters cuando escribam os m todos que tengan com o finalidad
duplicar objetos que tienen atributos que son referencias a otros objetos.
COMPARAR OBJETOS
Segn vim os en el captulo anterior, la clase O b je c t es la clase raz de la jerarqua
de clases de la biblioteca Java y de cualquier otra clase que im plem entem os en
nuestras aplicaciones, lo que se traduce en que todos ellas heredan los m todos de
O bject, com o equals, to S tr in g o finalize. por ejem plo.
C m o han sido im plem entados estos m todos? Pues de una form a m uy gen
rica, sin pensar en ningn objeto en particular. P or ejem plo, e q u a ls proporciona el
m ism o resultado que el operador esto es, com para las referencias a los o b
jeto s, no sus contenidos, lo cual es lgico: no podem os com parar dos objetos que
an no sabem os cm o son. A hora bien, una vez diseada una clase com o CVec-
tor, si necesitam os que el m todo e q u a ls nos diga cm o es un objeto C V ector con
respecto a otro, tenem os que sobreescribir dicho m todo.
Mtodo equals
/////////////////////////////////////////////////////////////////
// A p l i c a c i n que u t i l i z a la clase CVector
//
288 JA V A: C U R S O DE PROGRAM A CIN
public c la s s Test
I
II V i s u a l i z a r un v e c t o r
public s t a t ic void visu a liz a rV e c to r(C V e c to r v)
I
i n t ne = v . l o n g i t u d ! );
f o r ( i n t i = 0: i < ne: 1+ + )
System.out.print(v.valorEn(i) + " );
S y s t e m . o u t . p r i n t l n C );
C V e c t o r v e c t o r 2 = new C V e c t o r ( v e c t o r l );
for ( i n t i = 0 : i < v e c t o r 2 . 1 o n g i t u d ( ) : i + + )
v e c t o r 2 . p o n e r V a l o r E n ( i . v e c t o r 2 . v a l o r E n ( i )* 10):
v i s u a l i z a r V e c t o r ( v e c t o r 2 ) : // e s c r i b e 10 2 0 30 4 0 50 6 0 70
if (vectorl = vector2)
System, out. p r i n t l n C r e f e r e n c i a s al mi s mo o b j e t o ' ' ) :
e l se
System .out.println("referencias a objetos diferentes"):
if (vectorl.equals(vector2))
System .out.pri n t ln ("o b je to s i g u a l e s );
el s e
System .out.println("objetos d i f e r e n t e s " ):
1.0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7.0
10.0 2 0.0 30.0 4 0.0 50.0 6 0.0 70.0
referencias a objetos diferentes
objetos diferentes
Atributos static
La ltim a versin de la clase C irculo definida al principio de este captulo decla
raba do s atributos: centro y radio. Esto se traduce en que cada objeto de la clase,
cada crculo, tiene su propia copia de esos dos atributos. Pero seguro que en ms
de una ocasin querrem os utilizar un atributo (una variable) del cual exista una
nica copia que pueda ser utilizada por todos los objetos de la m ism a clase; esto
es. una variable con m bito global. El problem a es que Java no perm ite declarar
variables globales tal com o se interpretan en otros lenguajes de program acin; ca
da variable en Java debe ser declarada dentro de una clase, la cual define su pro
pio m bito. La alternativa que Java ofrece para dar solucin al problem a
planteado es d eclarar el atributo static.
C om o ejem plo, supongam os que querem os por una parte, no tener que acce
d er a la constante P I de la clase M a t h cada vez que calculem os el rea del crculo
0 la longitud de la circunferencia, y por otra, conocer el nm ero de objetos C r
culo que hay creados en cada instante. Para hacer esto, obviam ente es m s efi
ciente asociar dos atributos con la clase, p i y num C rculos, que con cada objeto.
El cdigo m ostrado a continuacin m uestra cm o aadir estos atributos a la clase:
class Punto
1
p r iv a t e double x, y;
public c la ss Cireulo
(
// A t r i b u t o s
p r i v a t e s t a t i c d o u b l e pi = 3 . 1 4 1 5 9 2 ;
p u b li c s t a t i c i n t numCrculos;
// Mtodos
290 JA V A: C U R SO DE PRO G R A M A CI N
t h is ( 100.0, 1 0 0 . C 1 0 0 . 0 ) :
I
p u b lic double r e a C I r c u l o ( )
I
return pi * radio * radio:
i
i
public c la ss Test
I
public static void m a in (S t r in g [] args)
I
C i r c u l o o b j l = new C l r c u l o O :
S y s t e m . o u t .p r i n t l n ( o b j 1 .1 ongCi r c u n f e r e n c ia ( ) ) ;
System .out.p r in t ln (o b jl. re a C i r c u l o ( )):
C i r c u l o o b j 2 = new C i r c u l o l O O . 1 0 0 , 1 0 ) :
System .out.pri ntln(o bj2.1o n gC ircun feren cia());
S y ste m .o u t.p rin tln (o b j2 . re a C irc u lo ());
S y s t e m . o u t . p r i n t l n ( C 1 r c u l o . numCi r c u l o s ) ;
A nteriorm ente dijim os que Java no perm ite declarar variables globales. No
obstante, C rculo.num C rculos se com porta igual que si lo fuera, ya que utilizando
esta sintaxis podem os acceder a num C rculos desde cualquier otra clase.
Mtodos static
Un m todo declarado static carece de la referencia this por lo que no puede ser
invocado para un objeto de su clase, sino que se invoca en general all donde se
necesite utilizar la operacin para la que ha sido escrito. D esde este punto de vista
es im posible que un m todo static pueda acceder a un m iem bro no static de su
clase; por la m ism a razn, s puede acceder a un m iem bro static. C om o ejem plo,
recuerde la clase M a t h estudiada en el captulo 5; uno de sus m todos es sq rt y la
form a de invocarlo desde cualquier m todo de otra clase es: M ath.sqrt(n). C om o
vem os, utilizam os esta expresin para invocar al m todo s q r t de la clase M a t h y
calcular la raz cuadrada de n sin pensar en ningn objeto en particular.
Un m todo s ta tic puede acceder a los m iem bros (atributo o m todo) sta tic de
su clase pero no puede acceder a los m iem bros no sta tic . P or ejem plo, si en el
m todo anterior intenta establecer el atributo radio a 0, el com pilador le m ostrar
un erro r indicndole que no se puede hacer referencia a una variable no esttica
desde un m todo esttico.
P or otra parte, un m iem bro s ta tic s puede ser accedido por un m todo inde
pendientem ente de que sea s ta tic o no. Por ejem plo, el m iem bro p i de la clase
C rculo es accedido por los m todos no estticos longC ircunferencia y reaCr-
cu lo y por el m todo esttico cam biarP recisinP iA de su m ism a clase. Si el acce
so se hace desde un m todo de otra clase, dicho m iem bro tiene que ser invocado a
travs del nom bre de la clase segn se explic anteriorm ente. Por ejem plo:
C1rculo.cambiarPrecisinPiA(3.l4);
C i r c u l o o b j 2 = new C l r c u o t l O O . 1 0 0 . 1 0 ) :
S y s t e m . o u t . p r i n t l n ( o b j 2 . 1ongCi r c u n f e r e n c i a ( ) ) :
S y ste m .o u t.p rin tln (o b j2 . re a C 1 rc u lo t)):
S y s t e m . o u t . p r i n t l n ( C 1 r c u l o . n u m C I r c u l o s ):
Iniciador esttico
Sabem os que tanto los atributos del objeto com o los de la clase pueden ser inicia
dos en la propia declaracin. Sirva com o ejem plo el atributo p i de la clase Crcu
lo. A hora, m ientras que los atributos de la clase son iniciados cuando la clase es
cargada por prim era vez, los atributos del objeto son iniciados para cada objeto en
el instante de su creacin.
C A PTU LO 9: CL A SES Y PAQUETES 2 9 3
stati c
I
// i n i c i a c i n ele l o s atributos de l a clase
1
C om o ejem plo, vam os a aadir a la clase C rculo dos atributos sta tic . seno y
coseno, q ue proporcionen las tablas del seno y coseno de grado en grado. Dichos
atributos sern iniciados a travs de un iniciador esttico com o se puede observar
a continuacin:
p u b l i c el a s s C r e u l o
I
// A t r i b u t o s
p r i v a t e s t a t i c d o u b l e pi = 3 . 1 4 1 5 9 2 :
pu blic s t a t ic int num Cireulos:
p u b l i c s t a t i c d o u b l e s e n o [ ] = new d o u b l e C 3 6 0 ] :
p u b l i c s t a t i c d o u b l e c o s e n o = new d o u b l e [ 3 6 0 ] :
// I n i c i a d o r e s t t i c o
static
1
// T a b l a s d e l s e n o y c o s e n o de g r a d o en g r a d o
fo r ( i n t i = 0 ; i < 360: i++)
I
d o u b l e s . c:
// C a l c u l a r e l s e n o y e l c o s e n o de i
s = M a th .s in (M a t h .t o R a d i a n s ( i )):
c = Math.co s(M a th .t o R a d ia n s ( i)):
// A l m a c e n a r l o s v a l o r e s r e d o n d e a d o s a 6 d e c i m a l e s
s e n o f i ] = M a t h . r i n t ( s * 1 0 0 0 0 0 0 )/1000000:
c o s e n o [ i ] = M a t h . r i n t ( c * 1 0 0 0 0 0 0 >/1000000:
294 JA V A: C U R S O DH PROGRAM A CIN
Java perm ite cualquier nm ero de iniciadores estticos aunque el com pilador
finalm ente los fusionar en uno slo en el m ism o orden en el que aparezcan en la
definicin de la clase. E ste iniciador se ejecutar solam ente una vez: cuando el
sistem a cargue la clase p o r prim era vez.
MATRICES DE OBJETOS
Se puede crear una m atriz de objetos de cualquier clase, de la m ism a form a que se
crea una m atriz de nm eros, de caracteres, de objetos S trin g , etc. Por ejemplo,
suponiendo que tenem os definida una clase C Persona podem os definir la matriz
listaTelfonos con 100 elem entos de la form a siguiente:
1 i s t a T e l f o n o s [ i ] = new C P e r s o n a [ a r g u m e n t o s ] ) :
El listado siguiente m uestra un ejem plo de una clase C Persona que define los
atributos privados nom bre, direccin y telfono relativos a una persona, y los
m todos pblicos que form an la interfaz de esta clase de objetos:
/////////////////////////////////////////////////////////////////
// D e f i n i c i n de l a c l a s e CPersona
//
public c la ss CPersona
I
// A t r i b u t o s
p r i v a t e S t r i n g nombre:
private Strin g direccin;
p riva te long te lfon o:
// M t o d o s
public CPersona) I )
public CPersonaString nom, String dir. long t e l )
I
nombre = nom:
di r e c c i n = d i r :
telfono = t e l ;
nombre = nom;
r e t u r n n o mbr e ;
public void a s i g n a r T e l f o n o ( 1 o ng t e l )
I
telfono = t e l ;
U n m todo com o asignarN om bre sim plem ente asigna el nom bre pasado co
m o argum ento al atributo nom bre del objeto que recibe el m ensaje. Y un m todo
com o obtenerN om bre devuelve el atributo nom bre del objeto que recibe el m en
saje. La explicacin para los otros m todos es anloga. P or ejem plo:
C P e r s o n a o b j = new C P e r s o n a O ;
o b j . a s i g n a r N o m b r e ( " J a v i e r " );
System .out.println(obj.obtenerN om bre()): // e s c r i b e : Javier
El listado siguiente m uestra un ejem plo de lo que puede ser la clase lista de
telfonos, que denom inarem os C ListaTfnos. D efine los atributos privados lista-
Telfonos. m atriz de objetos C Persona, y nE lem entos, nm ero de elem entos de la
m atriz, y los m todos que se describen a continuacin:
/////////////////////////////////////////////////////////////////
// D e f i n i c i n de l a clase CListaTfnos.
//
public c la ss CListaTfnos
I
p r i v a t e C P e r s o n a f ] 1 i s t a T e l f o n o s ; // m a t r i z de o b j e t o s
p r i v a t e i n t n E l e m e n t o s : // n me r o d e e l e m e n t o s de l a m a t r i z
Para crear un objeto lista de telfonos escribirem os una lnea de cdigo como
la siguiente:
S egn este ejem plo, la clase C ListaT fnos tiene que tener un constructor sin
argum entos Q u debe hacer este constructor? Iniciar un objeto C ListaTfnos con
una m atriz listaTeifonos con 0 elem entos:
A ntes de que se ejecute el cuerpo del constructor anterior, nE lem entos vale 0
y listaTelfonos n u il; y despus de que se ejecute, nE lem entos sigue valiendo 0 y
listaT elfonos referencia una m atriz de longitud 0 (propiedad le n g th = 0).
p u b l i c b o o le an el i m i n a r ( l o n g tel)
I
// B u s c a r e l t e l f o n o y e l i m i n a r r e g i s t r o
f o r ( i n t i = 0; i < n E l e m e n t o s : i + + )
i f (1 ist a T e l fo n o sfi] . obtenerTelfono() == te l)
I
1i s t a e l f o n o s i ] = n u il ;
un E l e m e n t o M e n o s d i s t a T e l f o n o s ) ;
return true:
)
return false:
I
O bservam os que cuando se invoca al m todo unE lem entoM enos se pasa como
argum ento la lista de telfonos actual que ahora quedar referenciada por su pa
rm etro listaA ctual Q u tiene que hacer este m todo? Pues, asignar al atributo
UstaTelfonos un nuevo espacio de m em oria que perm ita albergar un elemento
m enos de los que tiene actualm ente, co p iar uno a uno los elem entos que tena
hasta ahora la m atriz (referenciados p o r listaA ctual) m enos el que tiene asignado
la referencia n u il y decrem entar el atributo nE lem entos. C uando la ejecucin de
este m todo finalice, el bloque de m em oria viejo referenciado p o r listaActual ser
enviado a la basura y recolectado p o r el recolector de basura.
C A P T U L O 9: CLASES Y PAQUETES 2 9 9
pos = 1 i s t a t f n o s . b u s c a r t c a d e n a b u s c a r . p o s i c i n _ i n i c i o _ b s q u e d a ):
p u b lic CPersona va lo rE n ( in t i )
I
i f ( i > = 0 && i < n E l e m e n t o s )
r e t u r n 1 i s t a T e l f o n o s [ i ]:
300 JA V A : C U R SO D E PRO G R A M A CI N
el se
I
System .out.p rin tln C nd ice f u e r a de l i m i t e s " ) ;
r e t u r n n u l 1:
El m todo longitud devuelve el nm ero de elem entos que tiene actualm ente la
m atriz listaTelfonos.
1. B u s c a r
2. B u s c a r s i g u i e n t e
3. A a d i r
4. E l i m i n a r
5. S a l i r
Opcin: 3
n o mbr e : Javier
direccin: Santander
telfono: 942232323
1. B u s c a r
2. B u s c a r s i g u i e n t e
3. A a d i r
4. E l i m i n a r
5. S a l i r
Opcin:
// C r e a r un o b j e t o l i s t a d e t e l f o n o s v a c i o
C L i s t a T f n o s l i s t a t f n o s = new C L i s t a f n o s ( ) :
do
I
opc i n = me n( ):
switch (opcin)
I
hhhhhhhhhhhhhhhhhhhhhhhhhhhhbb
// B u s c a r un e l e m e n t o q u e c o n t e n g a " c a d e n a b u s c a r " .
// E s t a s u b c a d e n a s e r o b t e n i d a d e l t e c l a d o ,
pos = 1 i s t a t f n o s . b u s c a r ( c a d e n a b u s c a r , 0);
// S i s e e n c u e n t r a , m o s t r a r s u s d a t o s
break;
b us c a r
II B u s c a r e l s i g u i e n t e e l e m e n t o q u e c o n t e n g a l a subcadena
// u t i l i z a d a en l a l t i m a b s q u e d a .
pos = 1i s t a t f n o s .b u s c a r ( c a d e n a b u s c a r. pos + 1);
II S i s e e n c u e n t r a , m o s t r a r s u s d a t o s ,
break; __
// O b t e n e r d e l t e c l a d o l o s d a t o s n o mb r e , d i r e c c i n y
II t e l f o n o d e l n u e v o e l e m e n t o a a a d i r , y a a d i r l o ,
l i s t a t f n o s . a a d i r t n e w C P e r s on a ( no mb r e. d i r e c c i n , t e l f o n o ) ) ;
break;
bhhhhmhhhhbhhhhhhnhbbhhhhhhhbhmnhi
// O b t e n e r d e l t e c l a d o e l n me r o de t e l f o n o a e l i m i n a r y
// e l i m i n a r l o de l a 1 i s t a .
elim inado = 1i s t a t f n o s . e lim i n a r t t e l f o n o ) ;
break
c a s e 5: / / s a l i r
1i s t a t f n o s = n u i l :
w h i 1e ( o p c i n != 5 ) ;
import j a v a . i o . * ;
/////////////////////////////////////////////////////////////////
II A p l i c a c i n p a r a t r a b a j a r con m a t r i c e s de o b j e t o s
//
public class Test
I
public static in t menO
I
S y s t e m . o u t . p r i n t ( \ n \ n ):
S y s t e m . o u t . p r i n t l n C ' l . B u s c a r );
302 JA V A: C U R S O D E PRO G R A M A CI N
// C r e a r un o b j e t o l i s t a de t e l f o n o s v a c i o ( c o n c e r o e l e m e n t o s )
C L i s t a T f n o s l i s t a t f n o s = new C L i s t a T f n o s ( ):
i n t o p c i n = 0. pos = -1:
S t r in g cadenabuscar - n u il;
S t r i n g n o mbr e , d i r e c c i n ;
long te lfono;
boolean e lim ina d o - f a l s e ;
do
I
try
1
sw itch (opcin)
f l u j o S . p r i n t t " c o n j u n t o de c a r a c t e r e s a b u s c a r ");
c a d e n a b u s c a r - f l u j o E . r e a d L i n e ):
pos = l i s t a t f n o s . b u s c a r ( c a d e n a b u s c a r , 0 ):
i f ( pos -1)
i f (1 i s t a t f n o s . 1 o n g i t u d ( ) ! = 0 )
f l u j o S . p r i n t l n ( " b s q u e d a f a l l i d a ):
el se
f 1 u j o S . p r i n t l n ( "1 i s t a v a c i a " ) :
el se
I
f 1 u j o S . p r i n t l n ( 1 i s t a t f n o s . v a l o r E n ( p o s ) . obtener No mb r e( ) ) :
f l u j o S . p r i n t l n d i s t a t f n o s . v a l o r E n ( p o s ) . o b t e n e r D i r e c c i n ( ));
C A PTU LO 9: CL A SES Y PAQUETES 3 0 3
f l u j o S . p r i n t l n 1i s t a t f n o s . v a l o r E n ( p o s ) . o b t e n e r T e l f o n o ( ) ) ;
I
break;
c a s e 2: // b u s c a r s i g u i e n t e '
pos = 1 i s t a t f n o s . b u s c a r t c a d e n a b u s c a r . pos + 1 ) :
i f (pos == -1)
i f (1 i s t a t f n o s . 1 o n g i t u d ( ) ! = 0 )
f 1u j o S . p r i n t l n ( " b s q u e d a f a l 1 i d a );
el se
f 1 u j o S . p r i n t l n ( "1 i s t a v a c i a " );
el s e
I
f 1u j o S . p r i n t l n ( 1 i s t a t f n o s . v a l o r E n ( p o s ) . o bt e ner Nombret) ) ;
f l u j o S . p r i n t I n d i s t a t f n o s . v a l o r E n ( p o s ) . o b t e n e r i r e c c i n ( )):
f l u j o S . p r i n t l n ( l i s t a t f n o s . v a l o r E n ( p o s ) . o b t e n e r T e l f o n o ));
I
break;
c a s e 3: aadir
flujoS.printt"nom bre: ); nombre = f l u j o E . r e a d L i n e t ):
f l u j o S . p r i n t C d i r e c c i n : " ) ; d i r e c c i n = f l u j o E . r e a d L i n e ( );
flujoS.printt"telfono: ); t e l f o n o = L e e r . d a t o L o n g t ):
1 i s t a t f n o s . a a d i r ( n e w C Pers ona( nombr e, d i r e c c i n , t e l f o n o ) ) ;
break;
c a s e 4: // e l i m i n a r
f 1 u j o S . p r i n t ( " t e l f o n o : " ) ; t e l f o n o = L e e r . d a t o L o n g ( );
e lim in a d o = 1i s t a t f n o s . e l i m i n a r ( t e l f o n o ) :
i f (elim inado)
f l u j o S . p r i n t l n ( " r e g i s t r o e l i m i n a d o " ):
el se
i f (1 i s t a t f n o s . l o n g i t u d ( ) ! = 0)
f l u j o S . p r i n t l n ( " t e l f o n o no e n c o n t r a d o ):
el se
f l u j o S . p r i n t l n ( 1 i s t a v a c i a " ):
break; __ _
c a s e 5: // s a l i r
1i statfnos = nuil;
PAQUETES
En el captulo 4 ya fue expuesto el concepto de paquete. Si recuerda, dijim os que
un paquete es un conjunto de clases, lgicam ente relacionadas entre s, agrupadas
bajo un nom bre; incluso, un paquete puede contener a otros paquetes.
304 JA V A : C U R S O DE PROGRAM A CIN
Tam bin vim os que la propia biblioteca de clases de Java estaba organizada
en paquetes dispuestos jerrquicam ente. La jerarq u a a la que nos referim os es
anloga a la estructura jerrq u ica de carpetas o directorios que utilizam os para o r
ganizar los ficheros en un disco duro.
A sim ism o sabem os que para referim os a una clase d e un paquete, tenem os
que hacerlo anteponiendo al nom bre de la m ism a el nom bre de su paquete, ex
cepto cuando el paquete haya sido im portado explcitam ente, com o se indica en el
siguiente ejem plo, o im plcitam ente (caso del paquete ja v a .Ia n g ). P or ejem plo, la
aplicacin Test anterior utiliza, entre otras, la clase In p u t S t r e a m R e a d e r del pa
quete java.io. D ebido a que la aplicacin incluye la lnea de cdigo:
import j a v a . i o . * :
podem os referim os a esa clase sim plem ente p o r su nom bre. En otro caso, ten
dram os que haber utilizado su nom bre com pleto: ja v a .io .In p u tS tre a m R e a d e r.
R esum iendo: los paquetes ayudan a organizar las clases en grupos para faci
litar el acceso a las m ism as cuando las necesitem os en un program a; reducen los
conflictos de nom bres (lgicam ente, la probabilidad de que dos nom bres coinci
dan ser m enor cuantos m s elem entos intervengan); y perm iten proteger las cla
ses (una clase con nivel de proteccin de paquete, clase no pblica, no est
disponible para otros paquetes, ni siquiera para los subpaquetes).
Crear un paquete
Para crear un paquete hay que seguir bsicam ente los pasos indicados a continua
cin:
1. Seleccio nar e l nom bre d e l paquete. Para nom brar un paquete, Sun M icrosys
tem s recom ienda utilizar el nom bre de su dom inio de Internet, pero con los
elem entos a la inversa. Por ejem plo, si Sun hubiera seguido esta recom enda
cin en todos los casos, todos sus paquetes em pezaran p o r co m .su n .ja v a ya
que el dom inio de Internet para Java es ja va .su n .co m . Puede alargar el nom
bre para describir genricam ente las clases del paquete; por ejemplo:
com .sun.java.sw ing. La idea que se persigue es la exclusividad del nombre
del paquete, con el fin de no cau sar conflictos con los paquetes de otros.
R ealicem os un ejem plo para practicar. D ejando ahora a un lado el dom inio de
Internet, supongam os que deseam os crear los paquetes:
m isClases.es
mi s C l a s e s . t i l i d a d e s
CA PTU LO 9: CL A SES Y PAQUETES 3 0 5
C L A S S P A T H " . : c : \ j a v a \ j d k l . 3 \ m i s C l a s e s : c : \ j a v a \ j d k l .3
S iguiendo con el ejem plo, cream os la carpeta m isC lases en la ruta especifica
da y, dentro de ella, las carpetas es y utilidades.
B misClases
!P~l es
Q utilidades
Para finalizar el ejem plo, coloque la clase L eer que im plem entam os en el ca
ptulo 5, en la carpeta es (entrada salida). E dtela y aada la siguiente lnea:
package
import j a v a . i o . * ;
p u b l i c c l a s s Leer
I
II C u e r p o de l a clase
I
package m i s C l a s e s . u t i 1i d a d e s :
p u b lic e l a s s CPersona
I
// C u e r p o de l a clase
306 JA V A: C U R SO DE PROGRAM A CIN
package H H B S H H
pu blic c la ss CListaTfnos
I
// C u e r p o d e l a clase
I i^ . _
Para probar los paquetes que acabam os de crear, copie en un nuevo directorio
la aplicacin Test que realizam os anteriorm ente (slo el fichero Test.java). Des
pus, edtela y aada las sentencias im p o r t necesarias para especificar el paquete
al que pertenecen las clases Leer, C Persona y C ListaTfnos utilizadas por la apli
cacin. Finalm ente, com pile y ejecute la aplicacin para com probar los resulta
dos. Puede observar que al com pilar la aplicacin Test tam bin sern com piladas
las clases Leer, C Persona y C ListaTfnos, si an no lo estaban.
import m i s C l a s e s . e s . * :
import m i s C l a s e s . u t i l i d a d e s . * :
import j a v a . i o . * :
/////////////////////////////////////////////////////////////////
// A p l i c a c i n para t r a b a j a r con m a t r i c e s de o b j e t o s
//
public c la ss Test
1
// C u e r p o de l a clase
public c la s s CRacional
I
// A t r i b u t o s
p r i v a t e lo ng numerador;
p r i v a t e lo ng denominador;
CA PTU LO 9: C L A SES Y PAQUETES 3 0 7
// M t o d o s
I:
pu blic CRacional() // c o n s t r u c t o r
I
n u m e r a d o r = 0:
denomi n a d o r = 1;
I
C uando utilicem os argum entos para construir un nm ero racional, otras ope
raciones que debe realizar el constructor son verificar si el denom inador es cero,
en cu y o caso podem os forzar a que sea 1, o negativo, en cuyo caso invertim os el
signo del num erador y del denom inador. A sim ism o, sim plificar la fraccin siem
pre que sea posible. Segn esto la definicin del constructor C R acional con dos
argum entos puede ser as:
if ( denominador = = 0 )
I
S y s t e m . o u t . p r i n t l n ( " E r r o r : d e n o m i n a d o r 0. Se a s i g n a 1.");
d e n o m i n a d o r = 1;
I
308 JA V A: C U R S O DE PROGRAM A CIN
if ( denomi n a d o r < 0 )
I
numerador = -numerador;
denominador = denominador;
1
S i m p l i f i c a r C );
I
La funcin m iem bro Sim plificar utiliza el algoritm o de Euclides para obtener
el m xim o com n divisor (m cd) del num erador y del denom inador, y sim plificar
el nm ero racional dividiendo el num erador y el denom inador p o r ese m cd.
O tros constructores de inters pueden ser: uno que nos convierta un entero en
un nm ero racional y otro, el constructor copia:
public C R a c i o n a l ( l o n g num ) // c o n s t r u c t o r
I
n u m e r a d o r = num;
denomi n a d o r = 1;
public C R a c io n a l( CRacional r ) // c o n s t r u c t o r c o p i a
I
numerador = r .n u m e ra d o r;
denominador = r .denominador;
C A PTU LO 9: CL A SES Y PAQUETES 3 0 9
r3 - rl.sum art r 2 ) :
Com o vem os, la solucin es escribir un m todo su m a r con un parm etro que
haga referencia a un objeto C Racional, el operando de la derecha; el operando de
la izquierda referencia el objeto que recibe el m ensaje sum ar. La funcin debe de
volver una referencia al objeto C R acional resultado de la sum a. Segn lo ex
puesto, el m todo puede ser el siguiente:
Esta versin crea un objeto tem p invocando al constructor C Racional con los
valores resultantes de realizar la sum a, y devuelve tem p com o resultado ya sim
plificado por el constructor. Este m todo podra escribirse tam bin as:
p u b l i c C R a c i o n a l sumar( C R a c i o n a l r )
i
r e t u r n new C R a c i o n a l ( n u m e r a d o r * r . d e n o m i n a d o r +
denominador * r.num erador,
denominador * r.den o m ina do r ):
|
Esta versin crea un objeto tem poral invocando al constructor C Racional con
los valores resultantes de realizar la sum a, y lo devuelve com o resultado una vez
sim plificado por el constructor.
l o n g n - 2:
C R a c i o n a l r 2 = new C R a c i o n a l d . 4):
310 JA V A : C U R SO DE PRO G R A M A CI N
C uando ejecute este cdigo, observar que todo funciona correctam ente. Esto
se debe a que la expresin new C Racional(n), utilizando el constructor de la clase,
construye un objeto tem poral que es el que recibe el m ensaje sum ar. El resto del
proceso ocurre com o se ha explicado anteriorm ente.
Pensem os ahora en las operaciones de com paracin; por ejem plo en la opera
cin que nos perm ita saber si dos racionales son iguales. Supongam os las si
guientes declaraciones:
C R a c i o n a l r l = new C R a c i o n a l ( 1 ) :
C R a c i o n a l r 2 = new C R a c i o n a l d . 4 ) :
C R a c io n a l r3;
r3 = r l .s u m a r ( r 2 ) :
C R a c i o n a l r 4 = new C R a c i o n a l ( r 2 ) :
// ...
P ara com probar si dos objetos r2 y r3 son iguales, podem os proceder com o se
puede observar a continuacin:
if (r3.e q u als(r2)) rl = r 3 . s u m a r ( r 4 );
esto es, el usuario no debe tener la posibilidad de acceder a los atributos num era
d o r y denom inador de form a independiente.
Jav a tiene varias sobrecargas de los m todos p r in t y p r in tln para perm itir la
salida de valores de tipos predefinidos y objetos de las clases O b jec t, S trin g y
m atriz de caracteres. Si nuestra intencin es utilizar la m ism a sintaxis para visua
lizar un objeto C Racional, nos encontrarem os con que, lgicam ente, no existe una
sobrecarga de estos m todos para esta clase d e objetos. P ensando en lo que real
m ente hacen estos m todos, convertir su argum ento en un objeto S trin g , podem os
redefinir el m todo to S trin g heredado de la clase O b je c t, para convertir un objeto
C R acional en un objeto S trin g . De esta form a, m ostrar un objeto C R acional re
sultar tan sencillo com o se m uestra a continuacin:
C R a c i o n a l r l = new C R a c i o n a l U . 4 ) ;
Syste m .o u t.p ri n t l n ( r l .t o S t r i n g ( )):
Igual que para los m todos p rin t y p rin tln . Java tiene varias sobrecargas del
m todo re a d pero no existe una sobrecarga que perm ita leer objetos de la clase
C R acional a travs del teclado. Por esta razn, vam os a aadir a esta clase un
m todo leer que perm ita teclear un nm ero racional segn el form ato siguiente:
/ - ]entero[/entero. E ste m todo, utilizando el m todo dato de la clase L eer que
expusim os en el captulo 5, leer en nm ero racional com o una cadena de caracte
res. U na vez ledo, el m todo leer verificar si el form ato es vlido; para ello debe
cum plirse que el p rim er carcter sea el signo m enos o un dgito del 0 al 9, que los
siguientes caracteres sean dgitos y que si hay una / , slo sea una y no est en la
ltim a posicin. La lectura se repetir m ientras la cadena no sea vlida; en otro
caso, se extraer el num erador y el denom inador que utilizarem os com o argu
m entos en la construccin del objeto C R acional que ser devuelto por el m todo.
A continuacin puede ver el cdigo com pleto para este m todo:
ba r r a s = 0;
System .o ut.p rin t" [ - ] entero[/entero]: "):
r a c i o n a l = L e e r . d a t o O ; // l e e r e l r a c i o n a l
i f ( r a c i o n a l . 1 e n g t h ( ) = = 0)
carcterVlido = false;
else
I
// El p r i m e r c a r c t e r p u e d e s e r un d g i t o o e l s i g n o menos
c a r c t e r V l i do =
( r a c i o n a l . c h a r A t ( O ) > = 0 && r a c i o n a l . c h a r A t ( O ) < = ' 9 ' ) ||
(racional.charAt(O) = && r a c i o n a l . 1 e n g t h ) > 1 ) ;
// El l t i m o c a r c t e r no p u e d e s e r una /
i f ( r a c i o n a l .c h a r A t r a c i o n a l .1 e n g t h )-1 ) == / )
carcterVlido = false:
I
// El r e s t o de l o s c a r a c t e r e s p u e d e n s e r d g i t o s o / ( s l o una)
f o r ( i = 1; c a r c t e r V l i d o && i < r a c i o n a 1 . 1 e n g t h ) ; 1 + + )
I
c a r c t e r V l i d o = r a c i o n a l . c h a r A t i ) >= ' 0 ' &&
r a c i o n a 1 . c h a r A t ( i ) <= ' 9 ' ||
racional.charA ti)
i f ( r a c i o n a l . c h a r A t i ) == / ) barras++;
i f ( b a r r a s > 1) c a r c t e r V l i d o = f a l s e :
I
if ( IcarcterVlido) System .o u t .p r i n t l n ( " Entrada no v l i d a . " ) :
I
w hile (Ic a r c te rV lid o ):
// E x t r a e r e l n u m e r a d o r y e l d e n o m i n a d o r
i f ( ( i = r a c i o n a l . i n d e x O f ' / ) ) - 1 ) // no h a y d e n o m i n a d o r
I
num = L o n g . p a r s e L o n g r a c i o n a l );
den = 1:
I
el se
I
num = L o n g . p a r s e L o n g r a c i o n a l . s u b s t r i n g O , i ) ) : // 0 a i - 1
den = L o n g . p a r s e L o n g r a c i o n a l . s u b s t r i n g i + 1 ) ) :
I
// C o n s t r u i r y d e v o l v e r e l o b j e t o C R a c i o n a l
r e t u r n new C R a c i o n a l ( n u m . d e n ) ;
CRacional r l = new C R a c i o n a l ( 1 ) :
CRacional r 2 = new C R a c i o n a l l . 4 ) ;
<
CA PTU LO 9: CLASES Y PAQUETES 3 1 3
rl.copiar(r2);
if ( r . e s C e r o t )) ...
En este ejem plo se observa que el objeto r recibe el m ensaje esC ero. La res
puesta a este m ensaje ser la ejecucin del m todo esC ero que deber devolver
tr u e si el racional es cero, o false en caso contrario. D icho m todo puede escribir
se as:
// V e r i f i c a r s i e s 0
p u b l i c booleari e s C e r o t )
I
return n u m e r a d o r = = 0;
I
O tras operaciones de inters pueden ser increm entar y decrem entar en una
unidad un nm ero racional. P or ejem plo:
r 2 . c o p i a r ( r l . i n c r e m e n t a r ( ) ) ; // i n c r e m e n t a r r l y copiarlo en r 2
r 3 . d e c r e m e n t a r ( ) ; // i n c r e m e n t a r r 3
Los m todos correspondientes que perm iten realizar las operaciones m encio
nadas son los siguientes:
// I n c r e m e n t a r en 1
p u b lic CRacional increm entar!)
314 JA V A : C U R S O D E PROGRAM A CIN
numerador + = denominador;
return th is;
// D e c r e m e n t a r en 1
p u b lic CRacional decrem entar()
I
numerador -= denominador;
return th is;
1
rl. c o p i a r ( r l . c a m b i a d o D e S i g n o ( ) ) :
El m todo cam biadoD eSigno debe devolver el v alor cam biado de signo del
racional que recibi este m ensaje, pero sin m odificar ste. La solucin se m uestra
a continuacin:
// - u n a r i o
p u b lic CRacional cambiadoDeSigno()
I
C R a c i o n a l temp = new C R a c i o n a l ( -numerador, denominador ):
r e t u r n temp;
1
L os m todos expuestos no son los nicos; sim plem ente son un ejem plo de las
m uchas operaciones que se pueden program ar. A continuacin se m uestra el cdi
go com pleto que hem os escrito para la clase C R acional:
/////////////////////////////////////////////////////////////////
// C l a s e p a r a o p e r a r con nmeros racionales (u tiliza la clase Leer)
//
public c la ss CRacional
I
// A t r i b u t o s
p r i v a t e lo ng numerador;
p r i v a t e lo n g denominador;
// M t o d o s
protected CRacional Sim p lifica r()
I
// M x i m o comn d i v i s o r
l o n g mcd, temp, r e s t o ;
mcd = M a t h . a b s ( n u m e r a d o r );
temp = M a t h . a b s ( d e n o m i n a d o r );
CA PTU LO 9: C L A SES Y PAQUETES 3 1 5
public CRacionalO // c o n s t r u c t o r
I
n u m e r a d o r = 0:
denomi n a d o r = 1:
// S u m a r n m e r o s racionales
p u b lic CRacional sumart C R a c i o n a l r )
I
return new C R a c i o n a l ( n u m e r a d o r * r . d e n o m i n a d o r +
denomi n a d o r * r . n u m e r a d o r ,
denomi n a d o r * r . d e n o m i n a d o r ):
// R e s t a r n m e r o s r a c i o n a l e s
p u b lic CRacional r e s t a r CRacional r )
I
return new C R a c i o n a l ( n u m e r a d o r * r . d e n o m i n a d o r -
denomi n a d o r * r . n u m e r a d o r ,
denomi n a d o r * r . d e n o m i n a d o r ):
// M u l t i p l i c a r n m e r o s r a c i o n a l e s
p u b l i c C R a c i o n a l mu t i p l i c a r ( C R a c i o n a l r )
I
return new C R a c i o n a l ( n u m e r a d o r * r . n u m e r a d o r ,
denominador * r.den o m ina do r ):
// D i v i d i r n m e r o s r a c i o n a l e s
p u b lic CRacional d i v i d i r CRacional r )
I
r e t u r n new C R a c i o n a 1 ( n u m e r a d o r * r . d e n o m i n a d o r .
denominador * r.nu m erado r );
// V e r i f i c a r s i d o s n m e r o s r a c i o n a l e s son iguales
p u b lic boolean e q u a ls CRacional r )
I
return ( numerador * r . denominador =
d e n o m in a d o r * r . n u m e r a d o r );
// V e r i f i c a r s i un r a c i o n a l e s menor q u e o t r o
p u b l i c b o o l e a n me n o r ( C R a c i o n a l r )
I
return ( numerador * r .denominador <
d e n o m i n a d o r * r . n u m e r a d o r );
// V e r i f i c a r s i un r a c i o n a l e s m a y o r que o t r o
p u b l i c b o o l e a n mayor( C R a c i o n a l r )
I
return ( numerador * r .denominador >
d e n o m i n a d o r * r . n u m e r a d o r );
CA PTU LO 9: CL A SES Y PAQUETES 3 1 7
// D e v o l v e r un n mero r a c i o n a l como c a d e n a
public S trin g to S t r in g O
I
return new S t r i n g t n u m e r a d o r + " / " + denominador):
// E s t a b l e c e r un n me r o r a c i o n a l
p u b lic s t a t i c CRacional l e e r O
I
l o n g num. den;
int i . b a rra s:
boolean c a r c t e r V li d o :
String ra c io n a l;
do
I
b a r r a s = 0;
System .out.printC" [ - ] entero[/entero]: "):
r a c i o n a l = L e e r . d a t o O ; II l e e r e l r a c i o n a l
if ( r a c i o n a l . 1 e n g t h ( ) = = 0)
c a r c t e r V l i do = f a l s e :
el se
I
II E l p r i m e r c a r c t e r p u e d e s e r un d i g i t o o e l s i g n o menos
c a r c t e r V l i do =
( r a c i o n a l . c h a r A t ( O ) > = ' 0 ' && r a c i o n a l . c h a r A t ( O ) < = ' 9 ' ) ||
( r a c i o n a l.charAt(O) == && r a c i o n a l . 1e n g t h ( ) > 1 ) :
II El l t i m o c a r c t e r no p u e d e s e r una /
i f ( r a c i o n a l .c h a r A t t r a c i o n a l .1e n g t h ( )-1 ) = '/ ')
carcterVlido = false:
I
II El r e s t o de l o s c a r a c t e r e s pueden s e r d g i t o s o / ( s l o una)
f o r ( i = 1; c a r c t e r V l i d o && i < r a c i o n a l . 1 e n g t h ( ) ; i + + )
I
carcterVlido = r a c i o n a l . c h a r A t ( i ) > = ' 0 ' &&
r a c i o n a l . c h a r A t ( i ) < = ' 9 ||
racional.charA t(i) = '/ ':
if ( r a c i o n a l.c h a r A t i ) == ' / ) barras++:
if ( b a r r a s > 1) c a r c t e r V l i d o = f a l s e ;
1
if ( carcterVlido) S y s t e m . o u t . p r i n t l n ( " E n t r a d a no v l i d a . " ) :
I
w hile ( c a r c te rV lid o ):
// E x t r a e r e l n u m e r a d o r y e l d e n o m i n a d o r
i f ( ( i = r a c i o n a l . i n d e x O f ( ' / ' ) ) = = - 1 ) // no h a y d e n o m i n a d o r
I
num = L o n g . p a r s e L o n g f r a c i o n a l ) ;
den = 1:
318 JA V A: C U R SO DE PRO G R A M A CI N
el se
I
num = L o n g . p a r s e L o n g ( r a c i o n a l . s u b s t r i n g ( 0 , i ) ) : // 0 a i - 1
den = L o n g . p a r s e L o n g ( r a c i o n a l . s u b s t r i n g ( i + 1 ) ) :
)
II C o n s t r u i r y d e v o l v e r e l o b j e t o C R a c i o n a l
r e t u r n new C R a c i o n a l ( n u m . d e n ) :
II C o p i a r un r a c i o n a l en o t r o
p u b lic CRacional co p ia r( CRacional r )
I
numerador = r.num erador;
denominador = r.den o m ina do r:
return th is :
// V e r i f i c a r s i e s 0
p u b lic boolean e s C e r o O
I
return numerador = 0;
// I n c r e m e n t a r en 1
p u b lic CRacional incre m entare)
I
numerador + = denominador:
return th is:
// D e c r e m e n t a r en 1
p u b lic CRacional d ecrem entar()
I
numerador -= denominador;
return th is;
// - u n a r i o
p u b lic CRacional cambiadoDeSigno()
I
C R a c i o n a l temp = new C R a c i o n a l ( -numerador, denominador );
r e t u r n temp;
CA PTU LO 9: C L A SES Y PAQUETES 3 1 9
EJERCICIOS RESUELTOS
Una m atriz m ultidim ensional en Java representa un conjunto de elem entos que
pueden ser accedidos m ediante variables suscritas o de subndices. D ichos subn
dices son especificados utilizando uno o m s corchetes: []. Por ejem plo:
d o u b l e [ ] [ ] [ ] m i M a t r i z D o u b l e - new d o u b l e C 5 ] [ 1 0 ] [ 4 ] :
i n t i . j . k . c o n t a = 1;
/ / ...
m i M a t r i z D o u b l e [ i ] [ j ] [ k ] = conta++;
U na construccin sim ilar puede realizarse utilizando una m atriz unidim ensio
nal y m anipularla com o si fuera una m atriz m ultidim ensional. P ara ello, definire
m os una clase C M atriz con los siguientes atributos:
La clase C M atriz tiene com o funcin representar una m atriz m ultidim ensio
nal. O bserve q ue el m iem bro m atriz sirve para referenciar una m atriz de una di
m ensin de elem entos de tipo d o u b le. que el m iem bro nD im s contiene el nm ero
de dim ensiones y dim sM atriz es una referencia a una m atriz que contendr el va
lor de cada una de ellas.
final int A 5:
final int B - 10:
int i . j . c o n t a = 1;
CMatriz m - new C M a t r i z t A. B ): // m a t r i z d e 2 d i m e n s i o n e s (A*B)
// A s i g n a r d a t o s a l a m a t r i z m
f o r ( i - 0: i < A: i + + )
f o r ( j - 0: j < B: j + + )
m .asignarDato(conta++, i, j );
// V i s u a l i z a r l a m a t r i z m
f o r ( i = 0 : i < A: i + + )
I
f o r ( j = 0: j < B: j + + )
System .out.print(m .obtenerDato( i. j ) + " "):
S y s t e m . o u t . p r i n t l n t ):
320 JA V A : C U R SO DE PRO G R A M A CI N
E n este ejem plo m representa una m atriz de dos dim ensiones. O bserve que pa
ra acceder a un elem ento utilizam os dos subndices / y j . Pero com o la m atriz fsi
cam ente es una m atriz de una dim ensin, la idea fundam ental es im plem entar un
m ecanism o que convierta una posicin dada por 1. 2 3 subndices en la posicin
equivalente de la m atriz unidim ensional. Por ejem plo, si los subndices del ele
m ento al que deseam os acceder son i l , i2 c i3 y las dim ensiones de la m atriz m
son d i , d2 y d 3 , el desplazam iento se calcula as: ((H *d2)+ i2)*d3+ i3.
m atriz
d im s M a triz D im e n s io n e s A , B y C
nD im s N m e ro d e d im e n s io n e s
Segn lo expuesto, la clase C M atriz estar form ada por los atributos privados
m encionados, por el m todo privado.
void c o n s t r u i r ( i n t [] di m )
CM atriz)
CMatriz int di )
C M a t r i z i n t d i . i n t d2 )
C M a t r i z t i n t d i . i n t d 2, i n t d3 )
int totalElem entos)
in t desplazamiento! i n t f ] subind )
void a sig n a rD a to in t dato, int il )
vo id a s ig n a rD a to ! i n t dato, int il. int i 2 )
void asignarD atot in t dato, i n t i l . i n t i 2. i n t i3 )
double obtenerDato! in t i l )
double obtenerDato! in t i l . int i 2 )
double obtenerDato! i n t i l . i n t i 2. i n t i 3 )
2. Escriba los constructores CM atriz. Sus parm etros se corresponden con los
valores de las dim ensiones de la m atriz. Estos m todos invocan al m todo
con stru ir para crear un objeto CM atriz.
void c o n s t r u i r ( i n t [ ] dim )
dim m atriz unidim ensional de enteros que contiene el valor de cada una
de las dim ensiones.
Por ejem plo, si n es 2, dim [0] y d i mf J ] tienen que ser valores m ayores que
cero y dim [2 no interviene. E ntonces el nm ero de elem entos de la m atriz se
ra dim fO ] * d im [ l] . E ste valor ser calculado p o r el m todo totalElem entos
que se expone en el apartado siguiente.
5. Escriba el m todo totalE lem entos. E ste m todo calcula el nm ero total de
elem entos de la m atriz de 1, 2 3 dim ensiones.
El m todo totalE lem entos retom a el nm ero total de elem entos de la matriz.
6. E scriba el m todo desplazam iento. Este m todo calcula la posicin que tiene
dentro de la m atriz unidim ensional referenciada p o r m atriz, el elem ento que
est en la m atriz m ultidim ensional en la posicin especificada por los subn
dices alm acenados en la m atriz referenciada p o r subind. Previam ente, verifica
s los subndices estn dentro de los lm ites perm itidos.
7. Escriba el m todo asignarD ato. E ste m todo asigna un dato d al elem ento de
la m atriz m ultidim ensional, especificado por los subndices i l , i2 e i3. asig
narD ato invoca al m todo desplazam iento para calcular el desplazam iento.
8. Escriba el m todo obtenerD ato. E ste m todo obtiene un d ato del elem ento de
la m atriz m ultidim ensional, especificado p o r sus subndices i l , i2 e i3. obte
nerD ato invoca al m todo desplazam iento para calcular el desplazam iento.
El m todo obtenerD ato retom a el valor alm acenado en el elem ento especifi
cado de la m atriz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 2 3 24
25 2 6 27 2 8 2 9 30 31 3 2 3 3 34 35 3 6 3 7 38 39 4 0 41 4 2 43 44 45
4 6 4 7 4 8 4 9 50
C M a t r i z m( A . B ):
m.obtenerDato! i . j );
//////////////////////////////////////////////////////////////////
// M a t r i z m u l t i d i m e n s i o n a l b a s a d a en una u n i d i m e n s i o n a l
//
public class CMatriz
I
private doublef] m atriz; // m a t r i z u n i d i m e n s i o n a l
private i n t nDims; // n me r o de d i m e n s i o n e s
private i n t [ ] dim sM atriz; // v a l o r d e c a d a d i m e n s i n
C A PTU LO 9: CLASES Y PA Q U ETES 3 2 3
public CM atrizO II c o n s t r u c t o r
I
i n t d i m [ ] = I 10 I : // d i m e n s i n por omisin
c o n s t r u i r di m );
//////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// A p l i c a c i n para t r a b a j a r con C M a t r i z
II
public class Test
I
public static void m a in (S trin g [] args)
I
f i n a l i n t A = 5:
f i n a l i n t B = 10:
i n t i . j . c o n t a = 1:
C M a t r i z m = new C M a t r i z t A. B ); // m a t r i z d e 2 d i m e n s i o n e s
// A s i g n a r d a t o s a l a m a t r i z m
f o r ( i = 0: i < A: i + + )
for ( j = 0: j < B: j + + )
m .asignarDato(conta++. i. j ):
// V i s u a l i z a r l a m a t r i z m
f o r ( i - 0 : i < A; i + + )
I
f o r ( j = 0 : j < B: j + + )
System .out.print(m .obtenerDato( i . j ) + " " ) :
S y s t e m . o u t . p r i n t l n );
R espuesta a la pregunta 10. Los m todos asignarD ato y obtenerD ato estn
sobrecargados para poder utilizar sus form as adecuadas segn se trate de una m a
triz de 1. 2 3 dim ensiones.
p u b l i c C M a t r i z t i n t d i . i n t d2 ) // c o n s t r u c t o r
p r v a t e v o i d c o n s t r u i r ( i n t [ ] dim )
pu b lic int total Elem entos!)
EJERCICIOS PROPUESTOS
1. Suponiendo un texto escrito en m insculas y sin signos de puntuacin (una
palabra estar separada de otra por un espacio en blanco), realizar un p ro
gram a que lea texto de la entrada estndar (del teclado) y d com o resultado
la frecuencia con que aparece cada palabra leda del texto.
El resultado se alm acenar en un m atriz en la que cada elem ento ser un objeto
C Palabra con los atributos:
S tr in g palabra; // p a l a b r a
int contador; // nmero de v e c e s q u e a p a r e c e en e l texto
2. E scribir una clase C om plejo para trabajar con nm eros com plejos.
Q u es un nm ero com plejo? U n nm ero com plejo est com puesto por dos n
m eros reales y se representa de la form a a+ bi\ a recibe el nom bre de com ponente
real y b el de com ponente im aginaria. Si b = 0, se obtiene el nm ero real a, lo que
quiere decir que los nm eros reales son un caso particular de los nm eros com
plejos.
Los nm eros com plejos cubren un cam po que no tiene sentido en el cam po de los
nm eros reales. Por ejem plo, no existe ningn nm ero real que sea igual a V -9 .
T am poco tienen sentido las expresiones (-2 )3 /2 o lo g (-2 ). Para resolver este tipo
CA PTU LO 9: CLASES Y PAQUETES 3 2 7
Puesto que un nm ero com plejo (a, b) es un par ordenado de nm eros reales,
puede representarse geom tricam ente m ediante un punto en el plano; dicho de
o tra forma, m ediante un vector. De aqu se deduce que: a + b i, nm ero com plejo
en form a binm ica, es equivalente a m (cos a + i sen a ), nm ero com plejo en
form a polar, lo que indica que a = m eo s a y que b = m sen a.
Suma: ( a . b )+ ( c , d ) =(a+c.b+d)
D iferencia: ( a . b ) - ( c . d ) ( a - c . b - d )
Producto: <a.b)*(c.d)=(ac-bd.ad+bc)
C ociente: ( a , b ) / ( c , d )=( ( a c + b d ) / ( c 2 +d 2 ) , ( be - a d ) / ( c 2 + d 2 ) )
Estas operaciones y otras form arn parte de la interfaz de la clase C om plejo. Las
com paraciones entre com plejos estarn referidas a sus m dulos.
Segn la definicin dada, podem os representar un com plejo com o un objeto que
tenga d o s atributos, uno para alm acenar la parte real y otra para la parte im agina
ria.
C ada trm ino del polinom io ser representado por una clase C Term ino y cada po
linom io por una clase CPolinom io.
La clase C Term ino tendr dos atributos privados: coeficiente y exponente, y los
m todos necesarios para perm itir al m enos:
La clase C P olinom io tendr dos datos m iem bro privados: nm ero de trm inos que
tiene el polinom io (nroTerm inos) y una m atriz que referenciar los trm inos del
polinom io (term ino), as com o los m todos necesarios para perm itir al menos:
SUBCLASES EINTERFACES
Las caractersticas fundam entales de la POO son abstraccin, encapsulam iento,
herencia y p olim orfism o. H asta ahora slo hem os abordado la abstraccin y la
encapsulacin.
E ntre las caractersticas enum eradas anteriorm ente, hay una que destaca: la
herencia. L a herencia provee el m ecanism o m s sim ple para especificar una for
ma alternativa de acceso a una clase existente, o bien para definir una nueva clase
que aada nuevas caractersticas a una clase existente. Esta nueva clase se deno
m ina subclase o clase derivada y la clase existente, superclase o clase base.
C la s e C C u e n ta
X
)
C la s e C C u e n ta C o rrie n te
)
C la s e C C u e n ta A h o rro
j
U na jerarq u a de clases m uestra cm o los objetos se derivan de otros objetos
m s sim ples heredando su com portam iento. Los usuarios de C++ y de otros len
guajes de program acin orientada a objetos estn acostum brados a ver jerarquas
de clases para describir la herencia. Los de Java seguirn, en general, los m ism os
pasos.
330 JA V A : C U R S O D E PROGRAM A CIN
C uando una clase se disea para ser genrica, es casi seguro que no necesita
rem os crear objetos de ella; la razn de su existencia es proporcionar los atributos
y com portam ientos que sern com partidos por todas sus subclases. U na clase que
se com porte de la form a descrita se denom ina clase abstracta y se define com o tal
calificndola explcitam ente abstracta (a b s tra c t). Por ejem plo:
U na clase abstracta puede contener el m ism o tipo de m iem bros que una clase
que no lo sea, y adem s pueden contener m todos abstractos, que una clase no
abstracta no puede contener.
A la vista de este ejem plo, puede intentar declarar la clase C Cuenta no abs
tracta y com probar que el com pilador Java le m uestra un m ensaje indicndole
que una clase slo puede contener m todos abstractos si es abstracta.
CA PTU LO 10: SUBC LA SES E INTERFACES 3 3 1
SUBCLASES Y HERENCIA
V uelva a echar una ojeada a la figura m ostrada al principio de este captulo. Se
trata de u na jerarq u a de clases que puede ser analizada desde dos puntos de vista:
2. C uando se abord el diseo de una aplicacin para adm inistrar las cuentas de
una entidad bancaria, la solucin fue dise ar una clase especializada para cada
una de las cuentas y agrupar el cdigo com n en una superclase de stas.
A trib u to S ig n ificad o
nom bre D alo de tipo S tr in g que alm acena el nom bre del pro
pietario de la cuenta.
cuenta D ato de tipo S tr in g que alm acena el nm ero de la
cuenta.
saldo D ato de tipo d o u b le que alm acena el saldo de la cuenta.
tipoD elnters D ato de la clase de tipo d o u b le que alm acena el tipo de
inters.
332 JA V A: C U R SO DE PROGRAM A CIN
M to d o S ig n ificad o
C Cuenta E s el constructor de la clase. Inicia los datos nom bre,
cuenta, saldo y tipoD elnters.
asignarN om bre Perm ite asignar el dato nom bre.
obtenerN om bre R etorna el dato nom bre.
asignarC uenta Perm ite asignar el dato cuenta.
obtenerC uenta R etorna el dato cuenta.
estado R etorna el saldo de la cuenta.
com isiones Es un m todo abstracto sin parm etros que ser redefi-
nido en las subclases. Se ejecutar los das uno de cada
m es para cobrar el im porte del m antenim iento de una
cuenta.
ingreso Es un m todo que tiene un parm etro cantidad de tipo
d o u b le que aade la cantidad especificada al saldo ac
tual de la cuenta.
reintegro Es un m todo que tiene un parm etro cantidad de tipo
d o u b le que resta la cantidad especificada del saldo ac
tual de la cuenta.
a signarTipoD einters M todo que perm ite asignar el dato tipoD elnters.
obtenerT ipoD elnters M todo que retom a el dato tipoD elnters.
intereses M todo abstracto. C alcula los intereses producidos.
//////////////////////////////////////////////////////////////////
// C l a s e C C u e n t a : c l a s e a b s t r a c t a q u e a g r u p a los datos c o mu n e s a
// c u a l q u i e r t i p o de c u e n t a b a n c a r i a .
//
public abstract class CCuenta
I
// A t r i b u t o s
private String nombr e:
private String cuenta:
p ri vate double saldo:
p r iv a t e double tipoDelnters:
// M t o d o s
publi c CCuenta( ) I I ;
public CCuenta(String nom, String cue, double sal. double tipo)
I
asignarNombret nom):
asignarCuenta(cue):
i n g r e s o s a l );
asignarTipoDelnters!tipo):
CA PTU LO 10: SUBC LA SES E IN TERFA CES 3 3 3
p u b lic double e s t a d o ! )
I
return saldo:
)
p u b lic double o b te n e r T ip o D e ln t e r s t)
I
return tipoDelnters;
I
U na form a de hacer esto sera definir una nueva clase C C uentaAhorro con los
atributos y m todos de C Cuenta, a los que aadiram os los nuevos atributos y
m todos, segn m uestra el esquem a siguiente:
C A P T U L O 10: SU B C LA SE S E IN TERFA CES 3 3 5
E sta form a de proceder puede que funcione, pero no deja d e ser una m ala so
lucin; adem s de suponer un derroche de tiem po y esfuerzo, todo el trabajo que
ya estaba realizado no ha servido para nada. A qu es donde la herencia ju eg a un
papel im portante; la utilizacin de esta caracterstica evitar que recurram os a
soluciones com o la planteada. A travs de la herencia. Java perm ite definir la cla
se C C uentaA horro com o una extensin d e CCuenta. Y esto cm o se hace? D efi
niendo una subclase de la clase existente.
El ejem plo m ostrado a continuacin define la clase C C uentaA horro com o una
extensin de CCuenta.
U na subclase puede serlo de una sola superclase, lo que se denom ina herencia
sim ple o derivacin sim ple. Java, a diferencia de otros lenguajes orientados a o b
jeto s, no perm ite la herencia m ltiple o derivacin m ltiple, esto es, que una sub
clase se derive de dos o m s clases.
336 JA V A : C U R SO DE PRO G R A M A CI N
Una subclase puede, a su vez, ser una superclase de otra clase, dando lugar as
a una jera rq u a de clases. P or lo tanto, una clase puede ser una superclase directa
de una subclase, si figura explcitam ente en la definicin de la subclase, o una su
perclase indirecta si est varios niveles arriba en la jerarq u a de clases, y por lo
tanto no figura explcitam ente en el encabezado de la subclase.
1. U na subclase hereda todos los m iem bros de su superclase, excepto los cons
tructores, lo que no significa que tenga acceso directo a todos los miembros.
U na consecuencia inm ediata de esto es que la estructura interna de datos de
un objeto de una subclase, estar form ada por los atributos que ella define y
p o r los heredados de su superclase.
U na subclase s puede acceder directam ente a los m iem bros pblicos (public)
y protegidos (p ro te c te d ) de su superclase; y en el caso de que pertenezca al
m ism o paquete de su superclase, tam bin puede acceder a los m iem bros pre
determ inados.
3. Los m iem bros heredados por una subclase pueden, a su vez, ser heredados
por m s subclases de ella. A esto se le llam a propagacin de herencia.
C ontinuando con el ejem plo, diseem os una nueva clase C C uentaA horro que
tenga, adem s de las m ism as capacidades de C Cuenta, las siguientes:
A trib u to S ig n ificad o
cuotaM an ten i m i en to D ato de tipo d o u b le que alm acena la com isin que cobrar
la entidad bancaria p o r el m antenim iento de la cuenta.
M to d o S ig n ificad o
C C uentaAhorro Es el constructor de la clase. Inicia los atributos de la m is
ma.
asignarC uotaM anten Establece la cuota de m antenim iento de la cuenta.
obtenerC uotaM anten D evuelve la cuota de m antenim iento d e la cuenta.
com isiones M todo que se ejecuta los das uno de cada m es para cobrar
el im porte correspondiente al m antenim iento de la cuenta.
intereses M todo que perm ite calcular el im porte correspondiente a
los intereses/m es producidos.
import j a v a . u t 1 1 . * :
//////////////////////////////////////////////////////////////////
// C l a s e C C u e n t a A h o r r o : c la s e derivada de CCuenta
//
public class CCuentaAhorro extends CCuenta
{
// A t r i b u t o s
p r iv a t e double cuotaMantenimiento;
338 JA V A: C U R SO DE PROGRAM A CIN
// M t o d o s
public CCuentaAhorro() II // c o n s t r u c t o r sin parmetros
i f ( d a ! = 1) r e t u r n 0 . 0 :
// A c u m u l a r l o s i n t e r e s e s p o r mes s l o l o s d a s 1 de c a d a mes
double in te re s e s P ro d u c id o s = 0.0;
i n t e r e s e s P r o d u c i d o s = e s t a d o ! ) * o b t e n e r T i p o e l n t e r s t ) / 1200.0;
ingreso!interesesProducidos):
A tributos M todos
A tributos M todos
intereses
ingreso
reintegro
asignarTipoD elnters
obtenerT ipoD elnters
cuotaM antenim icnto constructores C C uentaA horro
asignarC uotaM anten
obtenerC uotaM anten
com isiones
intereses
Escribam os ahora una pequea aplicacin basada en una clase Test que cree
un objeto C CuentaAhorro:
public c la ss Test
I
public s t a t ic void m a in (S trin g [] args)
1
C C u e n t a A h o r r o c l i e n t e O l = new C C u e n t a A h o r r o C );
e l i e n t e O l . a s i g n a r N o m b r e ( " U n n o m b r e " ):
e l i e n t e O l . a s i g n a r C u e n t a f " U n a c u e n t a " );
e l i e n t e O l .a s i g n a r T i p o D e I n t e r s ( 2 . 5 ) :
elienteOl.asignarCuotaM anten(300);
e l i e n t e O l . in g r e s o (1000000):
e l i e n t e O l . re i n t e g r o C 5 0 0 0 0 0):
e l i e n t e O l . c o m i s i o n e s ( ):
// c l i e n t e O l no p u e d e a c c e d e r a l o s miembros p r i v a d o s , como
// c u e n t a .
class ClaseA
I
public int atributo_x = 1:
public i n t mtodo_x()
(
return atributo_x * 10:
1
public in t mtodo_y()
I
return a t r i b u t o _ x + 10 0 :
public c la ss Test
I
public static void m a in (S trin g [] args)
(
C l a s e B o b j C l a s e B = new C l a s e B O :
S y s t e m . o u t . p r i n t l n ( o b j C l a s e B . a t r i b u t o _ x ) : // e s c r i b e 2
S y s t e m . o u t . p r i n t l n ( o b j C l a s e B . m t o d o _ y ( ) ) : // e s c r i b e 101
S y s t e m . o u t . p r i n t l n t o b j C l a s e B . m t o d o _ x ( ) ) ; // e s c r i b e - 2 0
public in t mtodo_x()
I
return su p e r.atribu to_x * -10;
I
super.atributo_x
th is.atribu to_x
( ( C1a s e A ) t h i s ) . a t r i buto_x
Sin em bargo, puede haber ocasiones en que deseem os que un objeto de una
subclase responda al m ism o m todo heredado de su superclase pero con un com
portam iento diferente. Esto im plica redefinir en la subclase el m todo heredado de
su superclase.
Se puede observar que este m todo ha sido redefinido en la C laseB para que
realice unos clculos diferentes a los que realizaba en la C laseA.
super,mtodo_x()
thi s ,m to d o _ x ()
En cam bio, una expresin com o la siguiente es vlida para el com pilador, pe
ro, de acuerdo con lo que aprendi en el apartado anterior, no producir los re
sultados que quiz usted esperaba.
// M t o d o de l a C 1 a s e B
publi c in t m todo_z()
I
II...
return ( ( C 1 a s e A ) t h is ) .mtodo_x() + atribu to_x;
C A P T U L O 10: SUBC LA SES E IN TERFA CES 3 4 5
Lo anteriorm ente expuesto se traduce en que prim ero se ejecutan los cons
tructores de las superclases de arriba a abajo en la jera rq u a de clases y finalm ente
el de la subclase. Esto sucede as, porque una subclase contiene todos los atributos
de su superclase, y todos tienen que ser iniciados, razn p o r la que el constructor
de la subclase tiene que llam ar im plcita o explcitam ente al de la superclase.
Sin em bargo, cuando se hayan definido constructores con parm etros tanto en
las subclases com o en las superclases, tal vez se desee construir un objeto de la
subclase inicindolo con unos valores determ inados. En este caso, la definicin ya
conocida p ara los constructores de una clase cualquiera se extiende ahora para
perm itir al constructor de la subclase invocar explcitam ente al constructor de la
superclase. E sto se hace utilizando la palabra reservada su p e r:
Se puede observar que la sintaxis y los requerim ientos son anlogos a los uti
lizados con th is cuando se llam a a otro constructor de la m ism a clase.
346 JA VA: C U R SO DE PROGRAM A CIN
p u b l i c C C u e n t a A h o r r o ( S t r i n g nom, S t r i n g c u e , d o u b l e sal,
d o u b l e t i p o , d o u b l e m a nt )
I
supertnom, cue, s a l , t i p o ) ; // i n v o c a al c o n s t r u c t o r C C u e n t a
asignarCuotaManten(m ant); // i n i c i a c u o t a M a n t e n i m i e n t o
I
S egn lo expuesto, cuando se crea un objeto de una subclase, por ejem plo
clienteO l o cliente02, prim ero se construye la porcin del objeto correspondiente
a su superclase y a continuacin la porcin del objeto correspondiente a su sub
clase. Esto es u na form a lgica de operar, ya que perm ite al constructor de la sub
clase h acer referencia a los atributos de su superclase que ya han sido iniciados.
Segn lo expuesto, los objetos de una subclase son construidos de abajo hacia
arriba; esto es, la pila de llam adas relativas a los constructores de las clases invo
lucradas crece hasta llegar a la clase raz en la jerarq u a de clases; en este instante,
com ienza a ejecutarse el constructor de esta superclase: prim ero se construyen sus
atributos ejecutando, cuando sea necesario, los constructores de los m ism os, y
despus, se pasa a ejecutar el cuerpo del constructor de dicha superclase; y a con
tinuacin se ejecuta el cuerpo del constructor de la subclase. Este orden se aplica
recursivam ente por cada constructor de cada una de las clases.
P o r ejem plo, si definim os en una subclase un m todo finalize para liberar los
recursos asignados por dicha clase, debem os rede finir el m todo finalize en la su
perclase para liberar tam bin los recursos asignados por ella. Pero si el m todo fi
nalize de la subclase no invoca explcitam ente al m todo finalize de la superclase,
este ltim o nunca ser ejecutado y los recursos asignados por la superclase no se
rn liberados C undo debem os invocar al m todo finalize de la superclase? El
m ejor lugar para hacerlo es en la ltim a lnea del m todo finalize de la subclase,
porque com o la parte del objeto de la subclase se ha construido una vez que esta
ba construida la parte del objeto de la superclase, en m s de una ocasin los vn
culos existentes entre una y otra parte exigirn deshacer lo construido, ju sto en el
orden inverso.
Para ver prcticam ente la form a de im plem entar los destructores, volvam os al
ejem plo anteriorm ente expuesto con la ClaseA y la C laseB, y aadam os un des
tructor a cada una de ellas que supuestam ente hace algo.
348 JA V A: C U R SO DE PRO G R A M A CI N
class ClaseA
(
public int a t r i b u t o _ x = 1:
public i n t mtodo_x()
I
return atributo_x * 10:
1
public i n t mtodo_y()
(
return a t r i b u t o _ x + 10 0 :
1
public c la ss Test
I
public static void m a in (S trin g [] args)
I
C l a s e B o b j C l a s e B = new C l a s e B ! ) :
/ / ...
objClaseB = nuil:
C A PTU LO 10: SUBC LA SES E IN TERFA CES 3 4 9
// E j e c u t a r e l r e c o l e c t o r de b a s u r a
R unti rne r u n t i m e = R u n t i m e . g e t R u n t i m e t );
run t i m e . g e ( ) ;
r u n t i m e . r u n F i n a l i z a t i o n ):
Puesto que Java proporciona para cada clase que definam os un m todo fin a li
ce heredado de la clase O b je c t, una program acin segura aconseja redefinir este
m todo en cada una de las subclases que escribam os, aunque no haga nada; sim
plem ente con la intencin de invocar al m todo fn alize de la superclase, p o r si
alguna versin futura de la m ism a incluye un m todo finalize.
JERARQUIA DE CLASES
U na subclase puede asim ism o ser una superclase de otra clase, y a s sucesiva
m ente. En la siguiente figura se puede ver esto con claridad:
C la s e O b je c t
J
^ C la s ^ C u e n t^ ^ ^ J
C la s e C C u e n ta C o rrie n te C o n ln
J
350 JA V A: CU R SO D E PROGRAM A CIN
La raz del rbol es la clase que representa el tipo m s general, y las clases
term inales en el rbol (nodos hoja) representan los tipos m s especializados.
Com o ejem plo, vam os a com pletar la jerarq u a de clases expuesta con las cla
ses que faltan: C C uentaC orriente y C C uentaC orrienteC onln.
La clase C C uentaC orriente es una nueva clase que hereda de la clase CCuen
ta. Por lo tanto, tendr todos los m iem bros de su superclase, a los que aadiremos
los siguientes:
A trib u to S ig n ificad o
transacciones D ato de tipo in t que alm acena el nm ero de transac
ciones efectuadas sobre esa cuenta.
im porte PorTrans D ato de tipo d o u b le que alm acena el im porte que la
entidad bancaria cobrar por cada transaccin.
transE xentas D ato de tipo in t que alm acena el nm ero de transac
ciones gratuitas.
M to d o S ig n ificad o
C C uentaC orriente Es el constructor de la clase. Inicia los atributos de la
m ism a.
deerem entarTransacciones D ecrem enta en 1 el nm ero de transacciones.
asignarlm porteP orTrans Establece el im porte p o r transaccin.
obtenerlm porteP orT rans D evuelve el im porte por transaccin.
asignarTransE xentas Establece el nm ero de transacciones exentas.
obtenerTransE xentas D evuelve el nm ero de transacciones exentas.
ingreso A ade la cantidad especificada al saldo actual de la
cuenta e increm enta el nm ero de transacciones.
CA PTU LO 10: SU B C LA SE S E IN TERFA CES 3 5 1
import j a v a . t i l .*;
//////////////////////////////////////////////////////////////////
// C l a s e C C u e n t a C o r r i e n t e : c la se derivada de C C u e n t a
//
public class C C u e n t a C o r r i e n t e e x t e n d s CCuenta
I
// A t r i b u t o s
private int transacciones:
p riv a t e double im p o rte P o rT ra n s;
private int transExentas;
I I Mtodos
pu blic CCuentaCorriente*) II // c o n s t r u c t o r sin parmetros
p u b l i c C C u e n t a C o r r i e n t e * S t r i n g nom. S t r i n g c u e , d o u b l e s a l .
double tip o , double imptrans, in t tra nsex)
I
s u p e r ( n o m , c u e . s a l , t i p o ) ; // i n v o c a al c o n s t r u c t o r C C u e n t a
t r a n s a c c i o n e s = 0; // i n i c i a t r a n s a c c i o n e s
a s i g n a r l m p o r t e P o r T r a n s ( i m p t r a n s ) ; // i n i c i a i m p o r t e P o r T r a n s
asignarTransExentas( tra n se x ); // i n i c i a t r a n s E x e n t a s
public vo id d e c re m e n ta rT ra n sa c c io n e s()
I
t r a n s a c c i o n e s - -;
return:
1
importePorTrans = imptrans;
// A c u m u l a r l o s i n t e r e s e s p o r mes s l o l o s d i a s 1 de c a d a mes
double in te re s e s P ro d u c id o s - 0.0:
// H a s t a 3 0 0 0 e u r o s al 0 . 5 % . El r e s t o al i n t e r s e s t a b l e c i d o ,
i f ( e s t a d o ! ) < - 3000)
in t e r e s e s P r o d u c id o s = e s t a d o ! ) * 0.5 / 1200.0;
else
I
i n t e r e s e s P r o d u c i d o s = 3000 * 0 . 5 / 1 2 0 0 .0 +
( e s t a d o ! ) - 3000) * o b t e n e r T i p o D e l n t e r s ! ) / 1200.0:
I
i n g r e s o ! i n t e r e s e s P r o d u c i d o s );
// E s t e i n g r e s o no d e b e i n c r e m e n t a r l a s transacciones
d e c r e m e n t a r T r a n s a c c i o n e s ! );
return interesesProducidos;
I
I
//////////////////////////////////////////////////////////////////
O bserve que el constructor de la clase C C uentaC orriente tiene los parm etros
necesarios para iniciar sus datos m iem bro, excepto transacciones que inicialm ente
vale 0 . y los heredados de su superclase. El cuerpo del constructor consta de la
llam ada al constructor de su superclase y de las llam adas a los m todos de la pro
pia clase que perm iten iniciar de form a segura los atributos de la m ism a. Tam bin
se ha im plem entado un constructor sin parm etros.
P rocediendo de form a sim ilar a com o lo hem os hecho para las clases C C uen
taA horro y C C uentaC orriente. construim os a continuacin la clase C CuentaCo-
rrienteC onln (cuenta corriente con intereses) derivada de CC uentaC orriente.
Supongam os que este tipo de cuenta se ha pensado para que acum ule intere
ses de form a distinta a los otros tipos de cuenta, pero para obtener una rentabili
dad m ayor respecto a C C uentaC orriente.
D igam os que se trata de una cuenta de tipo C C uentaC orriente que precisa un
saldo m nim o de 3000 euros para que pueda acum ular intereses. Segn esto,
C C uentaC orrienteC onln, adem s de los m iem bros heredados, slo precisa im-
piem entar sus constructores y variar el m todo intereses:
354 JA V A : CU R SO DE PRO G R A M A CI N
M to d o S ig n ificad o
C C uentaC orriente E s el constructor de la clase. Inicia los atributos de la mis
ma.
intereses Perm ite calcular el im porte/m es correspondiente a los inte
reses producidos. Precisa un saldo m nim o de 3000 euros.
import j a v a . t i l .*;
//////////////////////////////////////////////////////////////////
// C l a s e C C u e n t a C o r r i e n t e C o n l n : c l a s e d e r i v a d a de C C u e n t a C o r r i e n t e
//
public c la ss CCuentaCorrienteConln extends CCuentaCorriente
(
// M t o d o s
p u b lic CCuentaCorrienteConln!) (1 // c o n s t r u c t o r sin parmetros
// A c u m u l a r i n t e r s m e n s u a l s l o l o s d i a s I de c a d a mes
double in te re s e s P ro d u c id o s = 0.0:
i n t e r e s e s P r o d u c i d o s = e s t a d o ! ) * o b t e n e r T i p o O e l n t e r s ! ) / 1200.0:
i n g r e s o ! i n t e r e s e s P r o d u c i d o s ):
// E s t e i n g r e s o n o d e b e i n c r e m e n t a r l a s t r a n s a c c i o n e s
d e c r e m e n t a r T r a n s a c c i o n e s ! );
//////////////////////////////////////////////////////////////////
directa, puede tener varias superclases indirectas: todas las que haya en el cam ino
para llegar desde su superclase hasta la clase raz; esto es im portante porque lo
que una subclase hereda de su superclase, ser heredado a su vez p o r una subclase
de ella, y as sucesivam ente.
i n g r e s o ! i n t e r e s e s P r o d u c i d o s );
d e c r e m e n t a r T r a n s a c c i o n e s ! );
s u p e r . i n g r e s o ! i n t e r e s e s P r o d u c i d o s );
S y s t e m . o u t . p r i n t l n ( el i e n t e O l . o b te n e rN o m b re !));
Sy ste m .o u t.p rin tn (e l i e n teO l.obtenerCuenta() );
System .out.printn(el ienteO l.estado!)):
S y s t e m . o u t .p r in t n ( e lie n t e O l.obtenerTi p o D e In te r s!));
System .out.printn(el ie n te O l.in te re se s!)):
356 JA V A: C U R SO DE PRO G R A M A CI N
C C u e n t a C o r r i e n t e C o n l n e l i e n t e 0 2 = new C C u e n t a C o r r i e n t e C o n I n ( ) ;
e l i e n t e 0 2 . a s i gn arN o m bre("el i ente 0 2 " ) ;
e l i e n t e 0 2 . a s i g n a r C u e n t a C 1 2 3 4 5 6 7 8 9 0 );
e lie n te 0 2 .asig n a rT ip o D e In te r s(3.0):
elien te02.asignarT ransExentas(0):
el i e n t e 0 2 . a s i g n a r l m p o r t e P o r T r a n s ( l . O ) :
e lie n te 0 2 . in g r e s o (20000);
el i e n t e 0 2 . r e i n t e g r o ( 1 0 0 0 0 ) :
e l i e n t e 0 2 . i n t e r e s e s ( ):
e l i e n t e 0 2 . c o m i s i o n e s ( );
System .out.p rin tln clie nte02.obtenerN om bre()):
Syste m .out.p rin tln (eliente02.ob ten erC ue nta()):
S y ste m .o u t .p rin tln c lie n t e 0 2 .estado());
Finalm ente, indicar que aunque en ninguna clase de nuestra jerarqua han in
tervenido m iem bros sta tic , su com portam iento en cuanto a la herencia se refiere
es el m ism o que el de los otros m iem bros, pero teniendo presente que son m iem
bros de la clase; y si es necesario, cuando se trate de m todos, tam bin pueden ser
redefinidos, aunque, en este caso, el nom bre de la clase indicar la versin del
m todo que se invocar. U na advertencia, si definiera, por ejem plo, en C Cuenta el
atributo tipoD elnters sta tic , lgicam ente se m antendra una nica copia que uti
lizaran tanto los objetos de C C uenta com o los de sus subclases.
E ste ejem plo declara una variable clienteO I de la subclase C C uentaC orriente
de CCuenta. D espus crea un objeto de e sa subclase y alm acena su referencia en
la variable clienteO I. U na vez que disponem os de la referencia a un objeto pode
m os trabajar con l com o lo hem os venido haciendo hasta ahora. P or ejem plo:
S t r i n g c u e n t a = el i e n t e O l . o b t e n e r C u e n t a ( ) :
d o u b l e s a l d o = e l i e n t e O l . e s t a d o );
Conversiones implcitas
El ejem plo anterior no aporta nada que nos sorprenda; operaciones com o sas ya
han sido expuestas anteriorm ente. Pero, qu pasara si a la variable clienteO I le
asignam os la referencia a un objeto de la subclase C C uentaC orrienteC onln de
C C uentaC orriente. P or ejem plo:
Si ejecutam os este ejem plo, com probarem os que los resultados obtenidos son
los m ism os que obtuvim os con el ejem plo anterior. Esto es as porque Java per
m ite convertir im plcitam ente una referencia a un objeto de una subclase en una
referencia a su superclase directa o indirecta. V eam os o tro ejem plo:
358 JA VA: C U R SO DE PROGRAM A CIN
C Cu e n t a c l i e n t e :
CCuentaCorriente clie n te O l =
new C C u e n t a C o r r i e n t e * " e l i e n t e O l " , " 1 2 3 4 5 6 7 8 9 1 " ,
10000. 3 . 5 . 1 . 0 . 6 ) :
CCuentaCorrienteConln c lie n te 0 2 =
new C C u e n t a C o r r i e n t e C o n l n * " e l i e n t e 0 2 " , " 1 2 3 4 5 6 7 8 9 2 .
El ejem plo anterior declara una referencia cliente de la clase C C uenta, la cual
utilizam os despus para referenciar indistintam ente a un objeto clienteO l de la
clase C C uentaC orriente, o a un objeto cliente02 de la clase C C uentaC orriente
C onln.
CCuenta e l i e n t e ;
CCuentaCorriente c lie n te O l =
new C C u e n t a C o r r i e n t e * " e l i e n t e O l " . " 1 2 3 4 5 6 7 8 9 1 " ,
10000, 3 . 5 , 1 . 0 . 6);
CCuentaCorrienteConln c lie n te 0 2 =
new C C u e n t a C o r r i e n t e C o n l n * " e l i e n t e 0 2 . " 1 2 3 4 5 6 7 8 9 2 " .
2 0 0 0 0 , 2 . 0 . 1 . 0 . 6 ):
eliente = e lie n te O l:
el i e n t e . a s i g n a r Im p o r te P o r T r a n s ( 1 . 0 ) : // er r o r : no es un mtodo de CCuenta
// . . .
el i ente = el i e n t e 0 2 :
c l i e n t e . a s i g n a r T r a n s E x e n t a s ( l O ) : // er r o r : no es un mtodo de CCuenta
77 . . .
CA PTU LO 10: SUBC LA SES E IN TERFA CES 3 5 9
Este ltim o ejem plo define las m ism as referencias y objetos que el anterior.
Pero ahora observam os que un intento de acceder al m todo asignarlm porteP or-
Trans ocasiona un error. Esto es porque el tipo de la variable cliente, que es
C Cuenta, determ ina que el objeto referenciado por ella slo puede recibir m ensa
je s de la clase de dicha variable; dicho de otra form a, slo puede ser m anipulado
p o r m todos de la clase C C uenta (propias y heredadas). L o m ism o diram os res
pecto al m ensaje a signarTransE xentas enviado al objeto inicialm ente referencia-
do p o r cliente02 y finalm ente, tam bin p o r cliente.
CCuenta cliente:
CCuentaCorriente c lie n te O l =
new C C u e n t a C o r r i e n t e ! " e l i e n t e O l " , " 1 2 3 4 5 6 7 8 9 1 " ,
10000, 3 . 5 , 1.0, 6):
CCuentaCorrienteConln c lie n te 0 2 =
new C C u e n t a C o r r i e n t e C o n l n ! " e l i e n t e 0 2 " , " 1 2 3 4 5 6 7 8 9 2 " .
20000. 2 . 0 . 1 .0 . 6 ):
double in t e r e s e s :
cliente = elien teO l:
i n t e r e s e s = e l i e n t e . i n t e r e s e s ! ) ; // C C u e n t a C o r r i e n t e . i n t e r e s e s ! )
// ...
Este ejem plo declara cliente de la clase C Cuenta, la cual utilizam os despus
para referenciar indistintam ente a un objeto clienteO l de la clase C C uentaC o
rriente, o a un objeto cliente02 de la clase C C uentaC orrienteC onln. Por otra par
te, el m todo intereses est definido en la superclase C C uenta y redefinido en sus
subclases C C uentaC orriente y C C uentaC orrienteC onln. P or lo tanto, la expresin
cliente.intereses!) invocar a C C uentaC orriente.intereses!) si cliente seala a un
objeto C C uentaC orriente, e invocar a C C uentaC orrienteC onln.intereses!) si
cliente seala a un objeto C C uentaC orrienteC onln.
Conversiones explcitas
La conversin contraria, de una referencia a un objeto de la superclase a una refe
rencia a su subclase, no se puede hacer, aunque se fuerce a ello utilizando una
construccin cast, excepto cuando el objeto al que se tiene acceso a travs de la
referencia a la superclase es un objeto de la subclase. Por ejem plo:
360 JA V A: C U R SO DE PROGRAM A CIN
CCuentaCorriente clie n te O l =
new C C u e n t a C o r r i e n t e ! " e l i e n t e O l , 1 2 3 4 5 6 7 8 9 1 .
10000. 3 . 5 . 1.0. 6 );
CCuentaCorrienteConln c lie n te :
c l i e n t e = c l i e n t e O l : // e r r o r de c o m p i l a c i n : c o n v e r s i n i m p l c i t a
// no p e r m i t i d a
// La s i g u i e n t e l i n e a d u r a n t e l a e j e c u c i n l a n z a un a e x c e p c i n
// de t i p o C 1 a s s C a s t E x c e p t i o n . d e b i d o a q u e l a c o n v e r s i n
// e x p l c i t a r e q u e r i d a no s e p e r m i t e
c lie n t e = (CCuentaCorrienteConlri)cl i e n t e O l:
// La l i n e a a n t e r i o r s e r i a v l i d a s i c l i e n t e O l r e f e r e n c i a r a a un
// o b j e t o d e l a c l a s e d e c l i e n t e , e s t o e s . C C u e n t a C o r r i e n t e C o n l n .
POLIMORFISMO
L a utilizacin de subclases y de m todos definidos en una clase y redefinidos en
sus clases derivadas es frecuentem ente denom inada program acin orientada a
objetos. En cam bio, la facultad de llam ar a una variedad de m todos utilizando
exactam ente el m ism o m edio de acceso, proporcionada p o r los m todos redefini-
dos en las subclases, es a veces denom inada polim orfism o.
La palabra polim orfism o" significa la facultad d e asum ir m uchas form as,
refirindose a la facultad de llam ar a m uchos m todos diferentes utilizando una
nica sentencia.
A sim ism o, sabem os que una referencia a una subclase puede ser convertida
im plcitam ente por Java en una referencia a su superclase directa o indirecta. Esto
significa q ue es posible referirse a un objeto de una subclase utilizando una varia
ble del tipo de su superclase.
p u b lic e la s s Test
I
public static void m a in ( S t r in g ! ] args)
C A P T U L O 10: SU B C LA SE S E IN TERFA CES 3 6 1
C C u e n t a [ ] c l i e n t e = new C C u e n t a [ 1 0 0 ] ;
// C r e a r o b j e t o s y g u a r d a r s u s r e f e r e n c i a s en l a m a t r i z
c l i e n t e [ 0 ] = new C C u e n t a A h o r r o ! " e l i e n t e O O " . 3 0 0 0 1 2 3 4 5 0 " .
10000. 2 . 5 . 3 0 ) :
c l i e n t e l ] = new C C u e n t a C o r r i e n t e ! " e l i e n t e O l " . " 6 0 0 0 1 2 3 4 5 0 " .
10000, 2 .0 . 1 . 0 . 6 ):
cliente[2] = new C C u e n t a C o r r i e n t e C o n l n ! " e l i e n t e 0 2 ,
" 4 0 0 0 1 2 3 4 5 0 " , 10000. 3 . 5 . 1.0, 6);
for (in t i = 0; e l i e n t e [ i ] ! = n u i l ; i + + )
I
System .o ut.p r i n t ( c l i e n t e [ i ] . obtenerNombre!) +
S y s t e m . o u t . p r i n t 1n ( e l i e n t e [ i ] . i n t e r e s e s ! ) ) :
Este ejem plo define una m atriz cliente de tipo C C uenta con 100 elem entos
que Java inicia con el valor n u il. D espus crea un objeto de una de las subclases y
alm acena su referencia en el prim er elem ento de la m atriz; aqu Java realizar una
conversin im plcita del tipo de la referencia devuelta por n ew al tipo CCuenta.
E ste proceso se repetir para cada objeto nuevo que deseem os crear (en nuestro
caso tres veces). Finalm ente, utilizando un bucle m ostram os el nom bre del cliente
y los intereses que le correspondern p o r m es. Pregunta: en cul d e las dos lneas
de este bucle se aplica la definicin de polim orfism o? L gicam ente en la ltim a
porque, segn lo estudiado hasta ahora, invoca a las distintas definiciones del
m todo intereses utilizando el m ism o m edio de acceso: una referencia a CCuenta.
C om o ejem plo, vam os a escribir un program a que cree un objeto que repre
sente a una entidad bancaria con un cierto nm ero de clientes. Este objeto estar
definido por una clase que denom inarem os C Banco y los clientes sern objetos de
alguna de las clases de la jerarq u a construida en los apartados anteriores.
C la s e O b je c t
)
L[ Clase C C u e n t ^ ^ ^ ^ J [_ C la s e C B a n c o J
C la s e C C u e n ta A h o rro
J
C la s e C C u e n ta C o rrie n te
}
0 C la s e C C u e n ta C o rrie n te C o n ln
)
362 JA VA : C U R SO D E PROGRAM A CIN
L a estructura de datos que represente el banco tiene que ser capaz de alm ace
nar objetos C C uentaAhorro, C C uentaC orriente y C C uentaC orrienteC onln. Sa
biendo que cu alquier referencia a un objeto de una subclase puede convertirse
im plcitam ente en una referencia a un objeto de su superclase, la estructura idnea
es una m atriz de referencias a la superclase C Cuenta. E sta m atriz ser dinm ica;
esto es, aum entar en un elem ento cuando se aada un objeto de alguna de las
subclases y dism inuir en uno cuando se elim ine; inicialm ente tendr 0 elem entos.
Segn esto, la clase C Banco, que no pertenece a nuestra jerarqua, tendr los atri
butos y m todos que se exponen a continuacin:
A trib u to S ig n ificad o
clientes M atriz de referencias de tipo CCuenta.
nE lem entos N m ero de elem entos de la m atriz.
M to d o S ig n ificad o
CBanco Es el constructor de la clase. Inicia la m atriz clientes con
cero elem entos.
unE lem entoM s A ade un elem ento vaco (n u il) al final d e la m atriz, in
crem entando su longitud en 1.
unE lem entoM enos Elim ina un elem ento cuyo valor sea n u il, decrem entando
su longitud en 1.
insertarC liente A signa un objeto de alguna de las subclases de C Cuenta al
elem ento i de la m atriz clientes.
clienteEn D evuelve el objeto que est en la posicin i de la m atriz
clientes.
longitud D evuelve la longitud de la m atriz.
elim inar Elim ina el objeto que coincida con el nm ero de cuenta pa
sado com o argum ento, poniendo el elem ento correspon
diente de la m atriz a valor nuil.
buscar D evuelve la posicin en la m atriz clientes del objeto cuyo
nom bre o cuenta, total o parcial, coincida con el valor pa
sado com o argum ento.
//////////////////////////////////////////////////////////////////
// C l a s e C B a n c o : c l a s e que m a n t i e n e una m a t r i z de r e f e r e n c i a s a
// o b j e t o s de c u a l q u i e r t i p o de c u e n t a b a n c a r i a .
//
public class C Ba n c o
I
private C C u e n t a [ ] c l i e n t e s : // m a t r i z de o b j e t o s
private i n t n E l e m e n t o s : // n m e r o de e l e m e n t o s de l a m a t r i z
CA PTU LO 10: SUBC LA SES E IN TERFA CES 3 6 3
pu blic CBanco)
I
// C r e a r una m a t r i z v a c i a
n E l e m e n t o s - 0:
c l i e n t e s = new C C u e n t a [ n E l e m e n t o s ] ;
p u b l i c CCuenta c l i e n t e E n int i )
(
// D e v o l v e r l a r e f e r e n c i a al o b j e t o i de l a m a t r i z
i f ( i > = 0 && i < n E l e m e n t o s )
r e t u r n c 1i e n t e s [ i ]:
el se
I
System .out.p r i n t n ( " ndice fuera de l i m i t e s " ) :
r e t u r n n u l 1;
364 JA V A: C U R SO DE PROGRAM A CIN
//////////////////////////////////////////////////////////////////
CA PTU LO 10: SUBC LA SES E IN TERFACES 3 6 5
Para finalizar, queda escribir una aplicacin que utilizando la clase CBanco,
construya la entidad bancaria objetivo del ejem plo propuesto. Esta aplicacin pre
sentar un m en com o el indicado a continuacin:
1. Saldo
2. Buscar sig u ie n te
3. Ingreso
4. Reintegro
5. Aadir
6. Elim inar
7. Mantenimiento
8. Sal i r
Opcin:
p u b lic c la s s lest
I
p u b l i c s t a t i c CCuenta leerD atostint op) I ... I
do
1
o p c i n = m e n ( ):
366 JA V A : C U R S O DB PRO G R A M A CI N
switch (opcin)
I
c a s e 1: // s a l d o
// B u s c a r un e l e m e n t o p o r e l no mb r e o p o r l a c u e n t a .
// La s u b c a d e n a d e b s q u e d a s e r o b t e n i d a d e l t e c l a d o ,
pos = b a n c o .b u sc a rc a d e n a b u sc a r, 0):
// S i s e e n c u e n t r a , m o s t r a r n o mb r e , c u e n t a y s a l d o
break:
c a s e 2: II b u s c a r s i g u i e n t e
// B u s c a r e l s i g u i e n t e e l e m e n t o que c o n t e n g a l a s u b c a d e n a
// u t i l i z a d a en l a l t i m a b s q u e d a ( c a s e 1 ) .
pos = b a n c o . b u s c a r ( c a d e n a b u s c a r . pos + 1):
// S i s e e n c u e n t r a , m o s t r a r n o mb r e , c u e n t a y s a l d o
break;
c a s e 3: // i n g r e s o
c a s e 4: // r e i n t e g r o
// I n g r e s a r o r e i n t e g r a r una c a n t i d a d en l a c u e n t a
// e s p e c i f i c a d a . Ambos d a t o s s e s o l i c i t a r n d e l t e c l a d o ,
pos = b a n c o . b u s c a r ( cu enta . 0 ) :
i f ( o p c i n = = 3)
b a n co.e lienteEn(p os).ingreso(canti d a d );
el se
ban co.clienteEn(pos).reintegro(cantidad):
break:
c a s e 5: // a a d i r
// A a d i r un n u e v o c l i e n t e . El o b j e t o c o r r e s p o n d i e n t e
II s e r d e v u e l t o p o r e l m t o d o s t a t i c l e e r D a t o s d e e s t a
// a p l i c a c i n , que o b t e n d r l o s d a t o s d e s d e e l t e c l a d o .
b a n c o . a a d i r ( l e e r D a t o s ( t i p o _ o b j e t o ) ):
break;
c a s e 6 : // e l i m i n a r
// E l i m i n a r e l c l i e n t e q u e c o i n c i d a c o n l a c u e n t a
// t e c l e a d a .
banco.elim inar(cuenta);
break:
c a s e 7: // m a n t e n i m i e n t o
II C o b r a r c o m i s i o n e s e i n g r e s a r i n t e r e s e s
f o r (pos = 0: pos < b a n c o .1o n g i t u d ( ); pos++)
I
b a n c o . e l i e n t e E n ( p o s ) . c o m i s i o n e s ):
b a n c o . e l i e n t e E n ( p o s ) . i n t e r e s e s ! );
1
break;
c a s e 8 : // s a l i r
banco = n u i l ;
w h i 1e ( o p c i n != 8 ) ;
CA PTU LO 10: SUBC LA SES E IN TERFA CES 3 6 7
import j a v a . i o . * ;
/////////////////////////////////////////////////////////////////
// A p l i c a c i n p a r a t r a b a j a r c o n l a c l a s e CBanco y la j e r a r q u a
II d e c l a s e s d e r i v a d a s de C C u e n t a
//
public c la ss Test
I
// P a r a l a e n t r a d a d e d a t o s s e u t i l i z a L e e r . c l a s s
p u b l i c s t a t i c C C u e n t a 1e e r D a t o s ( i n t o p)
I
CCuenta obj = n u i l :
S t r i n g n o mbr e , c u e n t a :
d o u b l e s a l d o , t i p o i , m a nt ;
System, out. p r i n t "Nom bre : "):
nombre = L e e r . d a t o ! );
System, o u t . p r i n t ! " C u e n t a : ");
c u e n t a = L e e r . d a t o ! ):
System, o u t . p r i n t ! " S a l d o : ");
s a l d o = L e e r . d a t o D o u b l e ! ):
S y s t e m , o u t . p r i n t ! " T i p o de i n t e r s : ");
tip o i = Leer.datoDouble!):
i f ( op = = 1)
I
S y s t e m . o u t . p r i n t ! " M a n t e n i m i e n t o .................. : " ) ;
mant = L e e r . d a t o D o u b l e ( ) ;
o b j = new C C u e n t a A h o r r o n o m b r e . c u e n t a , s a l d o , tipoi. mant):
1
else
I
int transex;
368 JA V A : C U R SO DE PRO G R A M A CI N
double imptrans;
S y s t e m . o u t . p r i n t ! " Importe por t r a n s a c c i n : ");
i m p t r a n s - L e e r . d a t o D o u b l e ! );
S y ste m .o u t.p rin tC 'T ra n sa c c io n e s e xe n ta s..: "):
t r a n s e x = L e e r . d a t o l n t ! ):
if (op = = 2)
o b j = new C C u e n t a C o r r i e n t e ! n o m b r e , c u e n t a , s a l d o , t i p o i ,
imptrans. tra nsex ):
else
o b j = new C C u e n t a C o r r i e n t e C o n I n ( n o m b r e . c u e n t a , s a l d o .
t i p o i . imptrans. transex)
)
return obj ;
i n t o p c i n = 0. pos = -1:
S t r in g cadenabuscar = n u il:
S t r i n g n o mb r e , c u e n t a :
double cantidad:
boolean e lim ina d o = f a l s e :
CA PTU LO 10: SUBC LA SES E IN TERFACES 3 6 9
do
I
o p c i n = m e n ( );
switch (opcin)
I
c a s e 1: // s a l d o
flu j o S . p r in t t "N o m b r e o cuenta, to tal o p a rc ia l );
cadenabuscar = L e e r.d a to O ;
pos = b a n c o . b u s c a r ( c a d e n a b u s c a r , 0 );
i f ( pos = = -1 )
i f ( b a n c o . 1 o n g i t u d ( ) ! = 0)
f 1 u j o S . p r i n t l n ( " b s q u e d a f a l 1 i d a ):
el se
f l u j o S . p r i n t l n ( " n o hay c l i e n t e s " ) ;
else
I
f 1u j o S . p r i n t l n ( b a n c o . e l i e n t e E n p o s ) . o b te n e rN o m b re ());
f 1u j o S . p r i n t l n ( b a n c o . e l i e n t e E n ( p o s ) . o b t e n e r C u e n t a ( ) ) ;
f lu j o S . p r i n tln (b a n c o .e lie n te E n tp o s) . e sta d o t));
I
break;
c a s e 2: II b u s c a r s i g u i e n t e
pos = b a n c o . b u s c a r t c a d e n a b u s c a r , pos + 1);
i f ( pos = 1)
i f ( b a n c o . 1 o n g i t u d ( ) ! = 0)
f 1 u j o S . p r i n t l n ( " b s q u e d a f a l 1 i d a " ):
el se
f l u j o S . p r i n t l n ( " n o h a y c l i e n t e s );
else
[
f 1u j o S .p ri n t l n ( b a n c o . e l i e n t e E n ( p o s ) .obtenerNom bret));
f l u j o S . p r i n t l n ( b a n c o . e l i e n t e E n ( p o s ) . o b t e n e r C u e n t a O );
f lu jo S . p r in t ln t b a n c o .c li enteEn(pos) . e sta d o t)):
1
break;
c a s e 3: // i n g r e s o
c a s e 4 : // r e i n t e g r o
f l u j o S . p r i n t t "C uen ta: " ) : cuenta = L e e r . d a t o O :
pos = b a n c o . b u s c a r ( c u e n t a , 0 ) ;
i f (pos = -1)
i f ( b a n c o . 1o n g i t u d ( ) ! = 0 )
f 1u j o S . p r i n t l n < " b s q u e d a f a l 1 i d a " ):
el se
f l u j o S . p r i n t l n { " n o hay c l i e n t e s " ) ;
el se
I
f l u j o S . p r i n t ( " C a n t i d a d : " ) ; c a n t i d a d = L e e r . d a t o D o u b l e ( ):
i f ( o p c i n = = 3)
b a n c o . e l i e n t e E n ( p o s ) . i n g r e s o ( c a n t i d a d ):
el se
370 JA V A: C U R SO DE PROGRAM A CIN
banco.el i e n t e E n ( p o s ) . r e i n t e g r o ( c a n t i d a d ) ;
I
break;
c a s e 5: // a a d i r
f l u j o S . p r i n t ( " T i p o de c u e n t a : l - ( C A ) , 2 - ( C C ) . 3 - C C I ):
do
o p c i n = L e e r . d a t o l n t );
w h i l e ( o p c i n < 1 || o p c i n > 3 ) :
b a n c o . a a d i r ( l e e r D a t o s ( o p c i n ) ):
break:
c a s e 6 : // e l i m i n a r
f l u j o S . p r i n t ( "C uen ta: ); cuenta = L e e r . d a t o O ;
e l i m i n a d o = b a n c o . e l i m i n a r ( c u e n t a );
i f (elim inado)
f l u j o S . p r i n t l n ( " r e g i s t r o e l i mi n a d o " );
el s e
i f ( b a n c o . 1o n g i t u d ( ) ! = 0)
f l u j o S . p r i n t n ( " c u e n t a no e n c o n t r a d a " ) ;
el se
f l u j o S . p r i n t l n C ' n o hay c l i e n t e s " ) :
break:
c a s e 7: // m a n t e n i m i e n t o
f o r ( p o s = 0: p o s < b a n c o . l o n g i t u d ( ) ; p o s + + )
I
b a n c o . e l i e n t e E n p o s ) . comi s i o n e s ( ):
b a n c o . el i e n t e E n ( p o s ) . i n t e r e s e s ! ) :
1
break:
c a s e 8: // s a l i r
banco = n u i l ;
whi 1 e ( o p c i n 1=8);
/////////////////////////////////////////////////////////////////
Se puede observar que el m antenim iento de las cuentas de los clientes (case 7)
resulta sencillo gracias a la aplicacin de la definicin de polim orfism o. Esto es.
el m todo com isiones o intereses que se invoca para cada cliente depende del tipo
del objeto referenciado p o r el elem ento accedido de la m atriz clientes de banco.
MTODOS EN LNEA
C uando el com pilador Java conoce con exactitud qu m todo tiene que llam ar pa
ra responder al m ensaje que se ha program ado que un objeto reciba en un instante
determ inado, puede tom ar la iniciativa de reem plazar la llam ada al m todo p o r el
cuerpo del m ism o. Se dice entonces que el m todo est en lnea. El que se pro
CA PTU LO 10: SUBC LA SES E IN TERFA CES 3 7 1
duzca esta circunstancia, por ejem plo, porque el m todo es corto, redundar en
tiem pos de ejecucin m s bajos ya que se evita que el intrprete Java tenga que
llam ar al m todo. En principio, en Java, todos los m todos de una clase pueden
ser m todos en lnea.
La consulta dinm ica acerca del m todo que hay que invocar es rpida, pero
no tan rpida com o invocar a un m todo directam ente. A fortunadam ente no hay
m uchos casos en los que Java necesite usar la consulta dinm ica. P or ejem plo, los
m todos finales (fin al), los estticos (sta tic ) y los privados (p riv a te ) pueden ser
invocados directam ente; y si son cortos son candidatos a ser m todos en lnea. Si
un m todo es final, el com pilador sabe que ese m todo no puede ser redefinido,
por lo tanto existe una sola versin; si es esttico es invocado anteponiendo el
nom bre de su clase; y si es privado no puede ser invocado por un m todo que no
sea de su clase. P or lo tanto, en ninguno de los tres casos habr que tom ar una de
cisin acerca de a qu m todo hay que llam ar.
INTERFACES
De form a genrica una interfaz se define as: un dispositivo o un sistem a utilizado
por entidades inconexas para interactuar. Segn esta definicin un control rem oto
es una interfaz, el idiom a ingls es una interfaz, etc. A nlogam ente, una interfaz
Jav a es un dispositivo que perm ite interactuar a objetos no relacionados entre s.
Las interfaces Java en realidad definen un conjunto de m ensajes que se puede
aplicar a m uchas clases de objetos, a los que cada una de ellas debe responder de
form a adecuada. P or eso, una interfaz recibe tam bin el nom bre de protocolo.
El m odificador de acceso p u b lic indica que la interfaz puede ser utilizada por
cualquier clase de cualquier paquete. Si no se especifica, entonces slo estar ac
cesible para las clases definidas en el m ism o paquete que la interfaz. U na interfaz
puede incluirse en un paquete exactam ente igual que una clase.
El nom bre de una interfaz se puede utilizar en cualquier lugar donde se pueda
utilizar el nom bre de una clase.
Para com prender con claridad las interfaces vam os a realizar un ejem plo de
una interfaz 1Fecha que va a ser utilizada para que dos clases (G r e g o r ia n C a le n -
d a r y una de las subclases de C C uenta) interacten entre s.
import j a v a . t i l .*;
//////////////////////////////////////////////////////////////////
II interfaz IFecha: mtodos y c o n s t a n t e s para obtener
// e l d a , mes y a o
//
public interface IFecha
I
public final s t a t i c i n t D I A _ D E L _ M E S = C a l e n d a r . DAY_OF_MONTH;
public final s t a t i c i n t M E S _ D E L _ A 0 = C a l e n d a r . M O N T H ;
public final s t a t i c i n t AO = C a l e n d a r . Y E A R ;
Se puede observar que una interfaz slo declara los m todos, no los define, y
adem s puede definir constantes. T am bin, cada una de las declaraciones y defi
374 JA V A : C U R SO DE PRO G R A M A CI N
niciones finaliza con un punto y com a (;). T odos los m todos declarados en una
interfaz son im plcitam ente pblicos y abstractos (p u b lic y a b stract); y todas las
constantes son im plcitam ente pblicas, finales y estticas (p u b lic, fin a l y static).
En am bos casos, el uso de estos m odificadores es slo una cuestin de estilo.
C ualquier clase puede tener acceso a las constantes de la interfaz a travs del
nom bre de la m ism a. Por ejem plo:
1 F e c h a . A O
En cam bio, una clase que im plem ente la interfaz puede tratar las constantes
com o si las hubiese heredado; esto es, accediendo directam ente a su nom bre.
import j a v a . u t i 1 . * ;
//////////////////////////////////////////////////////////////////
// C l a s e C C u e n t a A h o r r o : c la s e derivada de CCuenta
//
public c la ss C Cu en taAh o rro e x t e n d s CCuenta implements IFecha
I
II...
public void com isiones!)
I
// S e a p l i c a n m e n s u a l m e n t e p o r e l m a n t e n i m i e n t o d e l a cuenta
i f ( d i a ! ) = = 1) r e i n t e g r o ( c u o t a M a n t e n i m i e n t o ) ;
I
Si una clase im plem enta una interfaz, todas sus subclases heredarn los nue
vos m todos que se hayan im plem entado en la superclase, as com o las constantes
definidas por la interfaz. Por ejem plo, m odifiquem os la clase C C uentaC orrienle
para que utilice tam bin la interfaz Fecha:
import j a v a . t i l .*;
//////////////////////////////////////////////////////////////////
// C l a s e C C u e n t a C o r r i e n t e : c l a s e d e r i v a d a d e C C u e n t a
II
public class CCuentaCorriente extends CCuenta implements IFecha
I
// ...
public void com isiones)
I
// S e a p l i c a n m e n s u a l m e n t e p o r el m a n t e n i m i e n t o de l a c u e n t a
i
n . . .
II...
// I m p l e m e n t a c i n de l o s m t o d o s de l a interfaz IFecha
p u b l i c i n t d 1a ( )
I
GregorianCalendar fechaActual = new G r e g o r i a n C a l e n d a r ):
376 JA VA : C U R S O D E PRO G R A M A CI N
return f e c h a A c t u a l . g e t ( D I A _ D E L _ M E S );
1
public i n t mes O ( return 0; ] // no s e n e c e s i t a
public in t ao() I return 0: I II n o s e n e c e s i t a
I
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// C l a s e C C u e n t a C o r r i e n t e C o n l n : c la se derivada de C C u e n t a C o r r i e n t e
//
public c la ss CCuentaCorrienteConIn extends CCuentaCorriente
I
// .. .
public double inte resesO
(
f C d i a O ! = 1 || e s t a d o ? ' ) < 3000) return 0.0;
II...
C la s e O b je c t
J
Clase CCuenta
J C la s e C B a n c o
J
C la s e C C u e n ta A h o rro
i In te rfa z IF e c h a
C la s e C C u e n ta C o rrie n te
i
C la s e C C u e n ta C o rrie n te C o n ln
)
Probablem ente habr pensado que hubiram os obtenido el m ism o resultado
im plem entado la interfaz Fecha en la superclase C Cuenta. Pues, si es as, tiene
CA PTU LO 10: SU B C LA SE S E IN TERFA CES 3 7 7
razn. El hecho de haber im plem entado la interfaz en las subclases ha sido pura
m ente didctico.
import j a v a . t i l
//////////////////////////////////////////////////////////////////
// C l a s e IFecha: mtodos y c o n s t a n t e s para obtener
// e l d a , mes y a o
//
public abstract class IFecha
I
public final s t a t i c i n t D A _ O E L _ M E S = C a 1e n d a r . D A Y _ 0 F _ M 0 N T H :
public final s t a t i c i n t M E S _ D E L _ A O = C a 1e n d a r . MONTH:
public final s t a t i c i n t AO = C a l e n d a r . Y E A R ;
public a b s t r a c t i n t d i a ( );
public a b str a c t in t mes():
public abstract in t ao():
I
//////////////////////////////////////////////////////////////////
E videntem ente nuestro problem a en concreto tiene una solucin, que es deri
var la clase C Cuenta de la clase abstracta Fecha e im plem entar en C Cuenta los
m todos proporcionados por Fecha. Pero nuestro objetivo no es dar solucin a
este problem a, sino presentar ejem plos adecuados acerca de lo que se quiere ex
plicar.
378 JA V A : C U R SO D E PRO G R A M A CI N
P o r ejem plo, se puede declarar una m atriz clientes que sea de tipo / Fecha y
asignar a cada elem ento un objeto de algunas de las subclases de C C uenta:
I F e c h a c l i e n t e s - new I F e c h a [ 3 ] :
C C u e n t a A h o r r o c l i e n t e O - new C C u e n t a A h o r r o ( ) ;
c lie n te s [0 ] = clienteO;
// .. .
( ( C C u e n t a A h o r r o ) e l i e n t e s [ 0 ] ) . a s i g n a r N o m b r e ( " e l i e n t e O " ):
System .out.p rintln(elienteO .ob tenerN om bre));
II...
U na variable del tipo de una interfaz espera referenciar un objeto que tenga
im plem entada d icha interfaz, de lo contrario el com pilador Java m ostrar un error.
En el ejem plo anterior la variable clientes[O j de tipo Fecha hace referencia a un
objeto C C uentaA horro que im plem enta esa interfaz.
A sim ism o, se puede observar que es posible convertir im plcitam ente referen
cias a objetos que im plem entan una interfaz en referencias a esa interfaz y vice
versa, pero en este caso, explcitam ente. Lgicam ente, con lo que sabemos,
podem os ded ucir que con una referencia a la interfaz slo se tiene acceso a los
m todos y constantes declarados en dicha interfaz.
In te rfa z Ixxx
c C la s e l
J C la s e 3
J C la s e 2
o b j s [ 0 3 - n e w C 1 a s e l ( ) ;
o b j s [ l ] - n e w C l a s e 2 ( ) :
o b j s [ 2 ] = n e w C l a s e 3 ( ) ;
f o r i n t i = 0 : i < o b j s . l e n g t h : i + + )
o b j s [ i ] . m ( ) ; / / i n v o c a a l m t o d o m d e l o b j e t o C l a s e l . C l a s e 2
/ / o C l a s e 3 r e f e r e n c i a d o p o r o b j s C i ]
I
I
C aptar sim ilitudes entre clases no relacionadas sin forzar entre ellas una rela
cin artificial. Una accin de este tipo perm itira incluso, definir una matriz
de objetos de esas clases y aplicar, si fuera necesario, la definicin de poli
m orfism o.
D eclarar m todos que una o m s clases deben im plem entar en determ inadas
situaciones.
Suponga que se ha diseado una clase de objetos que puede tener un com
portam iento especial siem pre que im plem ente unos determ inados mtodos.
Por ejem plo, cuando aprenda sobre applets y subprocesos com probar que
usar un subproceso en un applet im plica que la clase de ste im plem ente la
interfaz R unnable.
Publicar la interfaz de program acin de una clase sin descubrir cm o est im-
plem entada.
C uando una clase im plem ente m ltiples interfaces puede suceder que dos o
m s interfaces diferentes im plem enten el m ism o m todo. Si esto ocurre, proceda
de alguna de las form as indicadas a continuacin:
Si los m todos tienen el m ism o prototipo, basta con definir uno en la clase.
Si los m todos slo difieren en el tipo del v alor retornado, no existe sobrecar
ga y el com pilador produce un error, ya que dos m todos pertenecientes a la
m ism a clase no pueden d iferir slo en el tipo del resultado.
CLASES ANIDADAS
U na clase anidada es una clase que es un m iem bro de otra clase. Por ejem plo, en
el cdigo m ostrado a continuacin, C Fecha es una clase anidada:
U na clase se debe definir dentro de otra slo cuando tenga sentido en el con
texto de la clase que la incluye o cuando depende de la funcin que desem pea la
clase q ue la incluye. Por ejem plo una ventana puede definir su propio cursor: en
este caso, la ventana puede ser un objeto de una clase y el cursor de una clase ani
dada.
Clases internas
C uando un m iem bro de una clase es una clase anidada y no es static recibe el
nom bre de clase interna p o r tratarse de un m iem bro del objeto. Esto significa que
cuando se cree un objeto de la clase externa tam bin se crear uno de la interna.
Por ejem plo, segn la definicin anterior de C Persona y C F echa, el siguiente c
digo crea un objeto o b j de la C Persona que incluye un objeto de la CFecha.
CPersona o bj - new C P e r s o n a O ;
Si una ciase interna est asociada con un objeto, lgicam ente no puede tener
m iem bros static.
public c la ss CPersona
I
p r i v a t e S t r i n g n o mbr e :
p r i v a t e CFecha f e c h a N a c i m i e n t o ;
private c la ss C F ec h a
I
private i n t d 1 a . mes . a o ;
private C F e c h a ( i n t d d , i n t mm, int aa)
I
da = dd : mes = mm; a o = a a :
I
l
public C P e rso n a () I 1
CA PTU LO 10: SU B C LA SE S E IN TERFA CES 3 8 3
C uando com pile la aplicacin Test anterior, podr observar que Java genera,
adem s del fichero Test.class y de C Persona.class. el fichero C Persona$C Fe-
cha.class correspondiente a la clase interna. P or lo tanto, cuando quiera instalar la
aplicacin en o tra m quina no olvide que cada clase interna tiene su propio fiche
ro de clase, y que deben incluirse ju n to con los de las clases de nivel superior. Re
sum iendo, para poder ejecutar la aplicacin Test del ejem plo anterior son
necesarios los ficheros: Test.class, C P ersona.class y C PersonaSC Fecha.class.
C l a s e 2 o b j = new C l a s e 2 ( ) :
o b j . m e t C l a s e 2 ( 1, 2 ) :
publi c c la s s C1ase2
I
p u b l i c v o i d m e t C la s e 2 ( i n t x. final int y)
(
i n t i = x + y;
final int c = x + y :
c la s s Clase3
I
// i n t a x ; II e r r o r : x no e s f i n a l
i n t b = y;
void m etClase3()
I
// System .out.pri n t l n ( b + i): // e r r o r : i no e s f i n a l
S y s t e m . o u t . p r i n t l n t b + c );
1
C l a s e 3 o b j = new C l a s e 3 ( ):
o b j . m e t C l a s e 3 ( ):
Clases annimas
A lgunas veces podem os escribir una clase dentro de un m todo sin necesidad de
identificarla. U na clase definida de esta form a recibe el nom bre de clase annim a.
P or otra parte, para crear con new un objeto de una clase necesitam os conocer
el nom bre de la m ism a. E ntonces para qu se utiliza una clase annim a?
interface Interfaz
I
p u b l ic a b s t r a c t v o i d p ( );
public abstract v o i d m ( ):
CA PITU LO 10: SU B C LA SE S E IN TERFA CES 3 8 5
class Clase2
I
private int i :
// ...
public In te rfa z metClase2() // m t od o de l a clase 2
I
r e t u r n new C l a s e 3 ( );
En este ejem plo se puede observar que la C lase2 define una clase interna Cla-
se3 y un m todo m e tC la se l que devuelve una referencia del tipo Interfaz a un
objeto Clase3 que im plem enta dicha interfaz. El m todo m a in de C la se l pone a
prueba las capacidades de Clase2.
donde Ixxx es el nom bre de la interfaz que im plem enta la clase. Por ejem plo:
Resum iendo, una clase annim a es una form a de evitar el que tengam os que
pensar en un nom bre trivial para una clase pequea en cdigo, utilizada en un lu
gar concreto. Evidentem ente, el precio que se paga es que no podrem os crear o b
jeto s de esta clase fuera del lugar donde haya sido definida.
EJERCICIOS RESUELTOS
Se quiere escribir un program a para m anipular ecuaciones algebraicas o polin-
m icas dependientes de las variables x e y. Por ejem plo:
C ada trm ino del polinom io ser representado por una clase C Term ino y cada
polinom io p o r una clase C P olinom io.
//////////////////////////////////////////////////////////////////
La clase C Term ino representa un trm ino del polinom io, el cual queda per
fectam ente definido cuando se conoce su coeficiente, el grado de la variable x y el
grad o de la variable y: coeficiente, exponenteD eX y exponenteD eY.
Para acceder a los atributos de un trm ino se han im plem entado las funciones
tpicas de asignar y obtener el valor alm acenado en el atributo que se trate en cada
388 JA V A: C U R SO DE PROGRAM A CIN
caso. O tros m todos im plem entados son: un constructor sin argum entos y otro
con argum entos para perm itir construir un objeto C Term ino a partir de unos valo
res determ inados; un constructor copia para poder construir un nuevo trm ino a
partir de otro existente; un m todo copiar para poder copiar un trm ino en otro
existente; y un m todo m ostrarTerm ino para visualizar un trm ino en la pantalla.
Es evidente que extender esta clase a trm inos de polinom ios dependientes de
m s de dos variables no entraa ninguna dificultad; es cuestin de aadir ms
datos m iem bro y las funciones de acceso correspondientes.
import ja va .m a th .*:
//////////////////////////////////////////////////////////////////
// C l a s e C P o l i n o m i o . Un o b j e t o C P o l i n o m i o consta de un o o ms
// o b j e t o s CTermino.
//
public c la ss CPolinomio
1
private C T e r m i n o [ ] t r m i n o s : // m a t r i z de o b j e t o s
private i n t n E l e m e n t o s : // n me r o de e l e m e n t o s de l a m a t r i z
C P o l i n o m i o p o l i n o m i o A = new C P o l i n o m i o ( );
Para increm entar la m atriz de referencias del polinom io en un elem ento, ini
ciado con el valor n u il, escribirem os el m todo unE lem entoM s y para elim inar
un elem ento previam ente establecido a nuil, el m todo unE lem entoM enos. A m
bos m todos se m uestran a continuacin:
vaco al final) y despus busca el lugar donde debe ser insertado el nuevo trm i
no; si ese lugar no es el ltim o, hace un hueco m oviendo un lugar en esta direc
cin los trm inos que hay desde ah hasta el final.
El algoritm o utilizado para saber el lugar que le corresponde al trm ino que se
inserta en orden ascendente prim ero p o r x y despus p o r y, es m uy sencillo: a cada
unidad del exponente de x le dam os un peso ( y a cada unidad del exponente de y
un peso de 1; la sum a de am bas cantidades nos d a el valor utilizado para efectuar
la ordenacin requerida. El valor de k es la potencia de 10 que sea igual o m ayor
que el m ayor de los exponentes de e y del trm ino a insertar.
Para elim inar un trm ino, escribirem os el m todo elim in a r!erm in o que recibe
com o argum ento el ndice del elem ento de la m atriz trm inos del objeto CPoli-
n om io que hace referencia al m ism o. U tilizando ese ndice, se enva el objeto
C Term ino a la basura poniendo a n u il el elem ento que lo referencia y se llam a al
m todo unE lem entoM enos para quitar dicho elem ento de la m atriz y decrem entar
en 1 el nm ero de elem entos de la m ism a. El m todo devuelve tr u e si la opera
cin se realiza satisfactoriam ente y false en caso contrario.
Para obten er el trm ino i del polinom io im plem entam os el m todo trm inoEn.
E ste m todo recibe com o argum ento el ndice i del trm ino del polinom io que se
desea recuperar y devuelve una referencia al m ism o.
p u b l i c CTermino t r m in o E n ( i n t i)
I
// D e v o l v e r l a r e f e r e n c i a al o b j e t o i de l a m atriz
i f ( i > = 0 && i < n E l e m e n t o s )
r e t u r n t rm i n o s [ i ]:
el se
I
System .out.p rintln"nd ice fuera de l i m i t e s " ) :
return n u il;
public C P o l i n o m i o c o p i a r ( C P o l i n o m i o p) // a s i g n a c i n
I
// C o p i a r e l o r i g e n en e l n u e v o d e s t i n o
n E l e m e n t o s = p . n E 1e m e n t o s :
t r m i n o s = new C T e r m i n o E n E l e m e n t o s ] ;
fo r ( i n t i = 0 : i < nElementos: i++)
t r m i n o s E i ] = new C T e r m i n o ( p . t r m i n o s [ i ] ) :
392 JA VA: C U R SO D E PROGRAM A CIN
return this:
I
O bserve que prim ero se construye un nueva m atriz de referencias del m ismo
tam ao que la m atriz origen y despus se asigna a cada uno de sus elem entos, el
correspondiente duplicado del objeto C Term ino (invocando al constructor copia).
Si no duplicram os los objetos C Term ino. esto es, si hiciram os:
los dos polinom ios, origen y destino, haran referencia a los m ism os trm inos; con
lo cual, las m odificaciones realizadas en uno de ellos repercutiran tam bin de la
m ism a form a en el otro.
El siguiente m todo perm ite sum ar dos polinom ios. L a idea bsica es cons
truir un tercer polinom io que contenga los trm inos de los otros dos, pero sum an
d o los coeficientes de los trm inos que se repitan en am bos. L os trm inos en el
polinom io resultante tam bin quedarn ordenados ascendentem ente, por el m ismo
criterio que se expuso anteriorm ente. U na vez finalizada la sum a, se elim inarn
los trm inos que hayan resultado nulos (coeficiente 0). U n ejem plo de cm o invo
car a este m todo puede ser el siguiente:
pR = p A . s u m a r ( p B ) ;
a) Partiendo de los polinom ios p A y p B que se quieren sum ar, obtener un trm i
no de cada uno de ellos.
b) C om parar los dos trm inos (uno de cada polinom io) segn el criterio explica
do cuando se expuso el m todo insertarTerm ino, y alm acenar el m enor en el
polinom io pR.
c) O btener el siguiente trm ino del polinom io al que perteneca el trm ino alm a
cenado en p R . y volver al punto b).
d) C uando no queden m s elem entos en uno de los dos polinom ios de partida, se
copian directam ente en p R todos los elem entos que queden en el otro polino
mio.
d o u b l e coef ' A, c o e f B ;
i n t expXA. e x p Y A . expXB, e x p Y B ;
C P o l i n o m i o pR = new C P o l i n o m i o ( ): II p o l i n o m i o resultante
// S u m a r pA con pB
w h i l e ( i p a < na && i p b < nb )
I
c o e f A = t r m i n o s [ i p a ] . o b t e n e r C o e f i c i e n t e ( );
e x p X A = t r m i n o s [ i p a ] . o b t e n e r E x p o n e n t e D e X );
e xp Y A = t r m i n o s [ i p a ] . o b t e n e r E x p o n e n t e D e Y { ) ;
c o e f B = p B . t r m i n o s f i p b ] . o b t e n e r C o e f i c i e n t e ( );
expXB = p B . t r m i n o s C i p b ] .o b t e n e r E x p o n e n t e D e X ( ) ;
expYB = p B . t r m i n o s t i p b ] .o b t e n e r E x p o n e n t e D e Y ( ) ;
k = 10;
w h i l e ( M a t h . a b s ( e x p X A ) > k || M a t h . a b s ( e x p Y A ) > k ) k = k*10;
if ( expXA e x p X B && e x p Y A = = e x p Y B )
I
pR.insertarTerm ino(new CTerminocoefA+coefB. expXA, expYA));
ipa++: ipb++;
I
else if ( expXA * k + expYA < expXB * k + expYB)
I
p R . i n s e r t a r T e r m i n o n e w C T e r m i n o ( c o e f A . expXA. expYA));
ipa++;
1
el se
I
p R . in s e rt a rT e rm irio n e w C T e r m in o f c o e f B . expXB. expYB));
i pb + + ;
// T r m i n o s r e s t a n t e s en e l pA
w h i l e ( i p a < na )
I
c o e f A = t r m i n o s [ i p a ] . o b t e n e r C o e f i c i e n t e t ):
expXA - t r m i n o s [ i p a ] , o b t e n e r E x p o n e n t e D e X ( ):
e xp Y A - t r m i n o s [ i p a ] . o b t e n e r E x p o n e n t e D e Y ( ) ;
p R . i n s e r t a r T e r m i n o ( n e w C T e r m i n o c o e f A , expXA. expYA));
i pa++:
1
// T r m i n o s r e s t a n t e s en e l pB
w h i l e ( i p b < nb )
I
c o e f B = p B . t r m i n o s [ i p b ] . o b t e n e r C o e f i c i e n t e );
expXB = p B . t r m i n o s t i p b ] . o b t e n e r E x p o n e n t e D e X ( ) ;
expYB = p B . t r m i n o s f i p b ] . o b t e n e r E x p o n e n t e D e Y ( ) ;
p R . i n s e r t a r T e r m i n o ( n e w C T erm in o tco e fB, expXB. e x p Y B ));
i pb + + ;
394 JA V A: C U R SO DE PROGRAM A CIN
// Q u i t a r l o s t r m i n o s c o n c o e f i c i e n t e 0
k - 0;
w hile ( k < pR.nElementos )
I
if ( p R . t r m i n o s [ k ] . o b t e n e r C o e f i c i e n t e ( ) = = 0)
I
pR.elim inarTerm ino(k);
pR.nElem entos--:
I
el se
k++;
1
return pR;
1
El siguiente m todo perm ite m ostrar todos los trm inos del polinom io pasado
com o argum ento.
w h i 1e ( i - - ! = 0 )
t r m i n o s [ i ] . m o s t r a r T e r m i no ( ):
I
E ste otro m todo que se expone a continuacin, devuelve el valor del polino
m io para los valores de x e y pasados com o argum entos.
f o r ( i n t i = 0: i < n E l e m e n t o s : i + + )
v += t r m i n o s t i ] . o b t e n e r C o e f i c i e n t e ( ) *
Math.pow(x. t r m i n o s [ i ] . obtenerExponenteDeX( ) ) *
M a t h .p o w ( y . trmi n o s [ i ] . o b te n e rE x p o n e n te D e Y ( ) ) ;
r e t u r n v;
1
El siguiente program a, utilizando las clases C Term ino y C Polinom io, lee dos
polinom ios, crea un tercero sum a de los dos anteriores y visualiza el polinom io
resultante, as com o su valor para x e y igual a 1.
// Suma de p o l i n o m i o s d e p e n d i e n t e s de d o s v a r i a b l e s .
// E s t a a p l i c a c i n u t i l i z a l a c l a s e L e e r .
//
public class Test
I
C A PTU LO 10: SUBC LA SES E IN TERFACES 3 9 5
// V i s u a l i z a r el p r i m e r s uma nd o
396 JA V A: C U R SO DE PROGRAM ACIN
S y s t e m . o u t . p r i n t l " R o l i n o m i o A: ):
p o l i n o m i o A . m o s t r a r P o l i n o m i o ( ):
S y s t e m . o u t . p r i n t l n );
II V i s u a l i z a r e l s e g u n d o suma nd o
S y s t e m . o u t . p r i n t " P o l i n o m i o B: ):
p o l i n o m i o B . m o s t r a r P o l i n o m i o );
S y s t e m . o u t . p r i n t l n );
// V i s u a l i z a r e l p o l i n o m i o suma
S y s t e m . o u t . p r i n t ( " P o l i n o m i o R: ):
p o l i nomi o R . m o s t r a r P o l i n o m i o );
S y s t e m . o u t . p r i n t l n );
// V i s u a l i z a r e l v a l o r d e l p o l i n o m i o suma p a r a x = 1 e y - 1
S y s t e m . o u t . p r i n t l n P a r a x - 1 e y = 1. e l v a l o r e s : +
p o l i n o m i o R . v a l o r P o l o n o m i o 1. 1 ) ) :
EJERCICIOS PROPUESTOS
2 x 'y - xyz* + 8.25 m s 5xsy - 2 xiy + 7x2 - 3 igual a 5xsy + 7x2 - x y z ' + 5.25
C ada trm ino del polinom io ser representado por una clase C TenninoE nX ,
C Term inoE nX Y o C T enninoE nX Y Z y cada polinom io por una clase CPolinom io.
La clase C Term inoE nX Y se derivar de C T erm inoE nX y la clase C T enninoE nX Y Z
de CTerminoEnXY:
C la s e O b je c t
L C la s e C T e r m i n o E r ^ ^ J {_ C la s e C P o lin o m io
C la s e C T e rm in o E n X Y
L C la s e C T e r m in o E n X Y Z ^
EXCEPCIONES
El lenguaje Jav a incorpora soporte para m anejar situaciones anm alas, conocidas
com o excepciones, que pueden ocurrir durante la ejecucin de un program a.
C on el sistem a de m anipulacin de excepciones de Java, un program a puede co
m unicar eventos inesperados a un contexto de ejecucin m s capacitado para res
ponder a tales eventos anorm ales. Estas excepciones son m anejadas por cdigo
fuera del flujo norm al de control del program a.
Las excepciones proporcionan una m anera lim pia de verificar errores; esto es,
sin abarrotar el cdigo bsico de una aplicacin utilizando sistem ticam ente los
cdigos de reto m o de los m todos en sentencias if y sw itch para controlar los po
sibles errores que se puedan dar. V eam os con un ejem plo, a qu nos estam os refi
riendo:
i n t c d i d o D e E r r o r = 0;
c d i d o D e E r r o r = 1e e r F i c h e r o n o m b r e );
i f ( cdidoDeError != 0 )
I
// O c u r r i un e r r o r a l l e e r el fichero
switch( cdidoDeError )
1
c a s e 1:
// No s e e n c o n t r e l f i c h e r o
// . . .
break;
c a s e 2:
// El f i c h e r o e s t c o r r u p t o
// . . .
break:
c a s e 3:
// El d i s p o s i t i v o no e s t l i s t o
// . . .
398 JA V A: C U R SO DE PRO G R A M A CI N
break;
default:
// O t r o e r r o r
// . . .
I
I
el se
I
// P r o c e s a r los datos ledos del fichero
I
El cdigo del ejem plo anterior trata de leer un fichero alm acenado en el disco
invocando al m todo leerFichero. E ste m todo devuelve un valor 0 si se ejecuta
satisfactoriam ente y un valor distinto de 0 en otro caso. Para analizar este hecho
se ha utilizado una sentencia if. En el caso de que se produzca un error, una sen
tencia sw itc h se encargar de verificar qu es lo que ha ocurrido y tratar de resol
verlo de la m ejor form a posible. Lo que se persigue es que el program a no sea
abortado inesperadam ente por el sistem a, sino disear una continuacin o term i
nacin norm al dentro de lo ocurrido.
O bservar el cdigo que ha sido necesario escribir para tratar un posible error
de no poder leer un fichero del disco. Pensem os cuntos errores m s podran
abortar nuestra aplicacin? Para que esto no suceda se im agina la com plejidad
del cdigo escrito una vez aadido todo el necesario para tratar cada uno de ellos?
El m anejo de excepciones ofrece una form a de separar explcitam ente el cdigo
que m aneja los errores, del cdigo bsico de una aplicacin, hacindola m s legi
ble, lo que desem boca en un buen estilo de program acin. P or ejem plo:
try
(
// C d i g o de l a aplicacin
catch(.clase_de_excepcin e)
{
I I C d i g o de t r a t a m i e n t o d e e s t a excepcin
I
c a t c h o t r a _ c l a s e _ d e _ e x c e p c i n e)
(
// C d i g o de t r a t a m i e n t o para o t r a c l a s e de e x c e p c i n
1
EXCEPCIONES DE JAVA
D urante el estudio de los captulos anteriores, seguro que se habr encontrado con
excepciones com o las siguientes:
T h ro w a b le
J
n Exceptio n
J
E rror
J
R u n tim e E x c e p tio n
J
C la s s N o tF o u n d E x c e p tio n
J
lO E x c e p tio n
J
E O F E x c e p tio n
J
400 JA V A: C U R SO DE PROGRAM A CIN
MANEJAR EXCEPCIONES
C uando un m todo se encuentra con una anom ala que no puede resolver, lo lgi
co es que lance (th ro w ) una excepcin, esperando que quien lo llam directa o
indirectam ente la atrape (catch ) y m aneje la anom ala. Incluso l m ism o podra
atrapar y m anipular dicha excepcin. Si la excepcin no se atrapa, el program a fi
nalizar autom ticam ente.
import j a v a . i o . *:
^ p u b l i c c l a s s Leer
'' I
public static Strin g d a t o ()
I
Strin g sdato - "";
try
I
// D e f i n i r un f l u j o d e c a r a c t e r e s de e n t r a d a : f l u j o E
I n p u t S t r e a m R e a d e r i s r - new I n p u t S t r e a m R e a d e r t S y s t e m . i n ) ;
B u f f e r e d R e a d e r f l u j o E = new B u f f e r e d R e a d e r ( i s r ) :
//
402 JA VA : C U R SO DE PROGRAM A CIN
Las palabras try y catch trabajan conjuntam ente y pueden traducirse as:
p o n er a prueba un fragm ento de cdigo por si lanzara una excepcin; si se eje
cuta satisfactoriam ente, continuar con la ejecucin del program a; si no, atrapar la
excepcin lanzada y m anejarla .
if (error) t h r o w new I O E x c e p t i o n ( ):
public c la s s Test
I
public static void m a in (S trin g [] args)
I
String str;
System .out.print"Dato: "):
s t r - L e e r , d a t o ( );
II...
B u ffe re d R e a d e r.re a d U n e
J
Para im plem entar un m anejador para una clase de excepcin hay que hacer
las do s cosas que se indican a continuacin:
try
I
// ...
s d a t o = f l u j o E . r e a d L i n e ):
I
c a t c h ( I O E x c e p t i on e)
1
S y s t e m . e r r . p r i n t l n ( " E r r o r : " + e .g e t M e s s a g e ) ) ;
I
Por ejem plo, si el p rim er bloque catch especifica un parm etro de la clase
T h ro w ab le . ningn otro bloque que le siga podra alcanzarse; esto es, cualquier
excepcin lanzada sera atrapada por ese prim er bloque, ya que cualquier referen
cia a una subclase puede ser convertida im plcitam ente p o r Java en una referencia
a su superclase directa o indirecta.
try
1
II...
I
catch(EOFException e)
I
II M a n e j a r e s t a c l a s e de e x c e p c i n
I
c a t c h t I O E x c e p t i o n ' e)
I
// M a n e j a r e s t a c l a s e de e x c e p c i n o de a l g u n a de s u s subclases.
// e x c e p t o E O F E x c e p t i o n
I
c a t c h t E x c e p t i o n e)
[
// M a n e j a r e s t a c l a s e de e x c e p c i n o de a l g u n a de s u s subclases,
// e x c e p t o E O F E x c e p t i o n e I O E x c e p t i o n
I
BLOQUE DE FINALIZACIN
Si no se trata de m anejar excepciones, sino de realizar alguna accin por obliga
cin (por ejem plo, liberar algn recurso externo que se haya adquirido, cerrar un
fichero, etc.) ponga el cdigo adecuado dentro de un bloque fin a lly despus del
bloque try o de un bloque catch. El bloque fin a lly deber ser siem pre el ltim o.
L a ejecucin del bloque fin a lly queda garantizada independientem ente de que
finalice o no la ejecucin del bloque try. Q uiere esto decir que aunque se abando
ne la ejecucin del bloque try porque, por ejem plo, se ejecute una sentencia re
tu rn . el bloque fin a lly se ejecuta.
finally
I
// C e r r a r el f i c h e r o
i f ( f c l i != n u i l ) f e 1i . c 1o s e ( ):
I
406 JA V A : C U R SO D E PROGRAM A CIN
El objeto lista de la clase C ListaC lientes encapsula una m atriz que alm acena
r la lista d e los clientes del banco. El m todo a a d ir puede lanzar una excepcin
A r r a y ln d e x O u t O f B o u n d s E x c e p t io n si el ndice utilizado para acceder a los
elem entos de la m atriz encapsulada en el objeto C ListaC lientes tiene un valor fue
ra de los lm ites establecidos. L os m todos P rintW riter y escribir pueden lanzar
una excepcin IO E x c e p t io n si el fichero no puede abrirse, o bien ocurre un error
de escritura. Las excepciones im plcitas com o A r r a y ln d e x O u t O f B o u n d s E x c e p
tion no estam os obligados a m anejarlas, pero las explcitas com o IO E x c e p t io n s.
P o r eso se ha aadido un m anejador para este tipo de excepcin. F inalm ente se ha
aadido un bloque fin a lly para garantizar que, ocurra lo que ocurra, el fichero se
r cerrado cuando se abandone el m todo escribirD atos.
Es realm ente necesario el bloque fin a lly ? En el ejem plo anterior, el m todo
escribirD atos no proporciona un m anejador de excepciones p o r si ocurre un error
durante la ejecucin del m todo aadir. Entonces, si este error sucede cm o ce
rraram os el fichero? L a respuesta es: el bloque fin a lly es lo ltim o que se ejecuta
antes de abandonar el m todo escribirD atos, lo que ocurrir cuando:
En el p rim er caso, despus del bloque try se ejecutar el bloque fin a lly y se
saldr del m todo escribirD atos. En el segundo caso, se ejecutar el bloque catch
proporcionado p o r escribirD atos, despus el bloque fin a lly y se saldr del m to
do. Y en el tercer caso, se ejecutar el bloque catch proporcionado por el sistem a,
despus el bloque fin a lly y se saldr del m todo.
Los bloques try y fin a lly pueden tam bin utilizarse conjuntam ente, sin que
sea necesario incluir un bloque catch.
DECLARAR EXCEPCIONES
Java requiere que cualquier m todo que pueda lanzar una excepcin la declare o
la atrape. Por ejem plo veam os qu ocurre si en el m todo escribirD atos presen
tado en el ejem plo anterior elim inam os el bloque c a tch ? O bservarem os que cuan
do Java com pile este m todo indicar m ediante un m ensaje de error que la
excepcin IO E x c e p t io n no est interceptada ni declarada p o r el m todo escri-
C A PTU LO I I: E X CEPC IO N ES 4 0 7
1. D ar inform acin a los usuarios de la clase que proporciona este m todo sobre
las cosas anorm ales que puede hacer el m todo.
Se puede observar que ahora no hay un bloque catch que intercepte la excep
cin IO E x c e p tio n . Esta form a de proceder obligar a cualquier m todo que invo
que a escribirD atos a atrapar la excepcin. P or ejem plo:
public c la ss C MiC1ase
I
// ...
public v o i d m( i n t a)
I
// ...
if (a 0)
t h r o w new E V a l o r N o V a l i d o ( " E r r o r : v a l o r c e r o " ) :
/ / ...
I
II...
parm etro a del m todo m de C M iC lase sea 0; en este caso, el m todo m lanza
(th ro w ) una excepcin de la clase E V alorN oV alido creando un objeto de esta cla
se. Para crear (new ) ese objeto se invoca al constructor E V alorN oV alido pasando
com o argum ento, en este caso, la cadena Error: valor cero .
Si un m todo m lanza una excepcin debe declararlo, para que los usuarios de
C M iC lase, que es quien proporciona el m todo m , estn inform ados sobre las co
sas anorm ales que puede hacer dicho m todo.
que en la pila de llam adas quedaran otras que pudieran atraparla, no sern tenidas
en cuenta; esto es, slo se ejecuta el m anejador del m todo por el que haya pasado
el flujo de control m s recientem ente.
En este instante tenem os una clase, CM iC lase, cuyo m todo m declara una
excepcin de tipo EV alorN oV alido. Un m todo de cualquier otra clase que utilice
el m todo m de esta clase debe detectar esa posible anom ala, de lo contrario el
com pilador Java m ostrar un error. D icho m todo expresar esa necesidad ence
rrando el cdigo que puede intentar (try ) producir tal anom ala en un bloque try
con un m anejador para esa excepcin. Por ejem plo:
T enga en cuenta que un m anejador tiene alcance a las variables locales del
m todo donde se ha definido pero no a las variables locales al bloque try o a otros
bloques catch.
Segn hem os visto, una excepcin se atrapa en un bloque catch que declare
un argum ento de su clase o superclase; pero com o lo que se lanza es un objeto,
puesto q ue th ro w especifica a continuacin una llam ada al constructor de la clase
de excepcin, si necesitram os transm itir inform acin adicional desde el punto de
lanzam iento al m anejador, lo podem os hacer a travs de argum entos en el cons
tructor.
l i d o O :
II . . .
Segn lo expuesto anteriorm ente, una vez atrapada una excepcin, el m aneja
d o r puede d ecidir volver a lanzarla para q ue sea procesada p o r otro m anejador.
Esto im plica que el m todo declare que puede lanzar ese tipo de excepcin. E n el
ejem plo anterior se puede observar que otroM todo declara que puede lanzar una
excepcin de la clase EValorN oValido.
CA PTU LO 11: EX CEPCION ES 4 1 3
P o r ltim o, no todas las excepciones tienen que servir para m anipular errores.
Puede tam bin m anejar excepciones que no sean errores.
EJERCICIOS RESUELTOS
1. A adir a la aplicacin realizada en el captulo 9 sobre el m antenim iento de una
lista de telfonos, el cdigo necesario para m anejar la excepcin O u t O f M e m o r y -
E r r o r que Jav a lanza cuando un m todo intenta realizar una asignacin dinm ica
de m em oria y no hay disponible un bloque de m em oria del tam ao requerido.
C om o ejem plo de tratam iento de este error vam os a aadir a la clase CLis
taTfnos de la aplicacin lista de telfonos realizada en el captulo 9 un m aneja-
dor para esta clase de excepcin. C argue esta aplicacin, visualice la clase
C ListaTfnos y com pruebe los m todos que utilizan new para reservar m em oria;
concretam ente, cuando se crea un objeto C ListaTfnos y cada vez que se necesita
aum entar o dism inuir el tam ao de la m atriz de objetos C Persona. Para dar solu
cin al problem a propuesto, aadirem os un nuevo m todo a la clase CListaTfnos
denom inado asigtiarM em oria. E ste m todo tendr un parm etro de tipo entero
414 JA V A: C U R SO D E PROGRAM A CIN
que se corresponder con el nm ero de elem entos de la m atriz para los que de
seam os asignar m em oria y devolver una referencia al nuevo bloque de m em oria
asignado. Si no hay un bloque de m em oria del tam ao solicitado, el m anejador de
la excepcin O u tO fM e m o ry E rro r visualizar el m ensaje de error predeterm ina
do y devolver la referencia al bloque de m em oria existente.
publi c C L is t a T f n o s t )
I
// C r e a r una lista vacia
n E l e m e n t o s = 0; _ _ _ _ _ _ _________ __
1istaTelfonos - asignarM em oria(nElem entos);
i f ( 1 i s t a A c t u a l ( i ] ! - n u i l )
1 i s t a T e l f o n o s [ k + + ] - 1 i s t a A c t u a l [ i ] ;
n E l e m e n t o s - - ;
I
// ...
2. En el captulo 5 im plem entam os una clase L eer con los m iem bros siguientes:
M to d o S ig n ific a d o
dato D evuelve un objeto S t r in g correspondiente a la cadena
tecleada.
datoShort D evuelve el dato de tipo sh o rt tecleado, o el valor
S h o r t . M I N _ V A L U E si el dato tecleado no se corresponde
con un short.
datolnt D evuelve el dato de tipo nt tecleado, o el valor In te -
g e r . M I N _ V A L U E si el dato tecleado no se corresponde
con un int.
datoLong D evuelve el dato de tipo lo n g tecleado, o el valor
L o n g . M I N _ V A L U E si el dato tecleado no se corresponde
con un long.
datoF loat D evuelve el dato de tipo float tecleado, o el valor
F lo a t .N a N si el dato tecleado no se corresponde con un
float.
datoD ouble D evuelve el dato de tipo d o u b le tecleado, o el valor D o u -
b le .N a N si el dato tecleado no se corresponde con un d o u
ble.
S y s t e m . o u t . p r i n t l n ( " I n t r o d u c i r d a t o s . F i n a l i z a r con C t r l + Z );
System .out.p rin t("D a to int: ");
w h i l e ( i < 1 00 && ( a [ i ] = L e e r . d a t o l n t l ) ) ! = e o f )
1
i ++ ;
C A PTU LO I I: EXCEPCION ES 4 1 7
catchNumberFormatException e)
I
System .out.p rint"Ese d a t o no e s vlido. Teclee otro: "):
r e t u r n d a t o F l o a t ):
S y s t e m . o u t . p r i n t l n ( I n t r o d u c i r d a t o s . F i n a l i z a r con C t r l + Z " ) ;
S y s t e m . o u t . p r i n t " D a t o f l o a t : );
w h i l e ( i < 100 && F l o a t . i s N a N ( a [ i ] = L e e r . d a t o F l o a t ( ) ) ! = e o f )
I
i++:
S y ste m .o u t.p r i n t ( "Dato float: ");
I
EJERCICIOS PROPUESTOS
1. Im plem entar los m anejadores para el resto de los m todos de la clase L eer de
form a anloga a com o se ha hecho en el ejercicio anterior.
2. La clase C Cuenta que im plem entam os en el captulo 10, tiene un m todo reinte
g ro que m uestra un m ensaje Error: no dispone de saldo cuando se intenta retirar
una cantidad y no hay suficiente saldo. M odifique esta clase para que el m todo
reintegro lance una excepcin ESaldolnsuficiente.
La solucin para hacer que los datos persistan de una ejecucin para otra es
alm acenarlos en un fichero en el disco en vez de en una m atriz en m em oria. E n
tonces, cada vez que se ejecute la aplicacin que trabaja con esos datos, podr leer
del fichero los que necesite y m anipularlos. N osotros procedem os de form a an
loga en m uchos aspectos de la vida ordinaria; alm acenam os los datos en fichas y
guardam os el conjunto de fichas en lo que generalm ente denom inam os fichero o
archivo.
<-
X.
420 JA VA : C U R SO D E PROGRAM A CIN
n om bre
cam po
d ir e c c i n telfono
/
r e g ist ro r e g ist ro
fiel" e r o
---------- /
C ada cam po alm acenar el dato correspondiente. El conjunto de cam pos des
critos form a lo que hem os denom inado registro, y el conjunto de todos los regis
tros form an un fichero que alm acenarem os, por ejem plo, en el disco bajo un
nom bre.
Por lo tanto, para m anipular un fichero que identificam os p o r un nom bre, son
tres las operaciones que tenem os que realizar: ab rir el fichero, escribir o leer re
gistros del fichero y cerrar el fichero. En la vida ordinaria hacem os lo m ism o,
abrim os el cajn que contiene las fichas (fichero), cogem os una ficha (registro)
para leer datos o escribir datos y, finalizado el trabajo con la ficha, la dejam os en
su sitio y cerram os el cajn de fichas (fichero).
P odem os agrupar los ficheros en dos tipos: ficheros de la aplicacin (son los
ficheros .java, .class, etc. que form an la aplicacin) y ficheros de datos (son los
que proveen de datos a la aplicacin). A su vez. Java ofrece dos tipos diferentes
de acceso a los ficheros de datos: secuencial y aleatorio.
el p ro g ra m a le e d ato s
( 1 r ^
P ro g ra m a F ic h e ro 1
L J 1 flujo d e e n tra d a
s \
P ro g ra m a
flujo d e s a lid a
f F ic h e ro
\
1
el p ro g ra m a e s c rib e d ato s
________ )
Entonces, para que un program a pueda obtener inform acin desde un fichero
tiene que abrir un flujo y leer la inform acin en l alm acenada. A nlogam ente,
para que un program a puede enviar inform acin a un fichero tiene que abrir un
flujo y escribir la inform acin en el mismo.
L os algoritm os para leer y escribir datos son siem pre m s o m enos los m is
mos:
L eer E s c rib ir
A b rir un flu jo desde un fich ero A b rir un flu jo hacia un fich ero
M ientras ha ya inform acin M ientras haya inform acin
L eer inform acin E scribir inform acin
C errar e l flujo C errar el flujo
Java im plem enta la jerarq u a de clases p ara la E/S sin incluir dem asiadas ca
pacidades dentro de una clase porque rara vez se necesitan m uchas de ellas al
m ism o tiem po. En cam bio, s se pueden obtener todas esas capacidades superpo
niendo una clase sobre otra. P or ejem plo, en el captulo 5 vim os que la clase
In p u tS tre a m no utiliza un buffer, sin em bargo, la clase B u ffe re d ln p u tS tre a m
aade un buffer a la clase In p u tS tre a m .
U n program a que cree un flujo de alguna de estas clases podr leer o escribir
inform acin en algunos de los m edios especificados: una m atriz en m em oria, un
fichero en el disco o una tubera. U na tubera es un flujo que perm ite com unicar
dos subprocesos para transferencia de inform acin entre uno y otro. V erem os esto
con m s detalle en el captulo dedicado a hilos.
import j a v a . i o . * :
p u b lic c la s s Test
I
public static void m a in (S trin g [] args)
I
c h a r [ ] mi = new c h a r [ 8 0 ] ;
c h a r [ ] m2 = new c h a r [ 8 0 3 :
i n t c a r , i = 0:
// A l m a c e n a r d a t o s en l a m a t r i z mi
f o r ( c a r = a ' ; c a r < = 'z ' : c a r + + )
m l[i++] = (char)car;
// A b r i r un f l u j o , f l u j o E , d e s d e l a m a t r i z mi
C h a r A r r a y R e a d e r f l u j o E = new C h a r A r r a y R e a d e r ( m l ):
// A b r i r un f l u j o , f l u j o S . h a c i a una m a t r i z t e m p o r a l
C h a r A r r a y W r i t e r f l u j o S = new C h a r A r r a y W r i t e r ( ) ;
try
I
// L e e r de f l u j o E y e s c r i b i r en f l u j o S
whi l e ( ( c a r = f l u j o E . r e a d ( ) ) I - -1)
f 1 u j o S . w r i t e ( c a r );
// C o p i a r en m2 l o s d a t o s e n v i a d o s al flujoS
m2 = f l u j o S . t o C h a r A r r a y ( ) ;
System .out.println(m 2);
I
catch ( I O E x c e p t i o n e)
I
System .out.pri ntln (e .g e tM e ssa ge ()):
I
f i n a l ly
I
II C e r r a r l o s f l u j o s
f l u j o E . c l o s e ( ):
f l u j o S . c l o s e ( );
424 JA VA : C U R SO DE PRO G R A M A CI N
C oncatenacin SequencelnputStream
S edacin O bjectlnputStrcam
O bjeciO utputStream
C onversin D atalnputStream
(datos) D ataO utputStream
C ontar L ineN um berR eader LineN um berlnputStrcam
U n program a que cree un flujo de alguna de estas clases podr leer o escribir
inform acin adem s de ejecutar la operacin para la que ha sido diseado. Por
ejem plo, un flujo de la clase P u s h b a c k R e a d e r (derivada de F ilte r R e a d e r que a
su vez se d eriva R e a d e r) es til cuando, por ejem plo, un analizador necesita mirar
el siguiente carcter en la entrada con el fin de determ inar qu hacer a continua
cin; para ello, el analizador leer el carcter y despus lo devolver a la entrada
para que pueda ser ledo por el cdigo que tenga que ejecutarse a continuacin.
M todo Significado
cise C ierra el flujo.
read Lee un nico carcter, o bien una m atriz de caracteres.
un re ad D evuelve a la entrada un nico carcter, o bien todo o parte
de una m atriz de caracteres.
ready D evuelve true si se puede leer del flujo porque hay carac
teres disponibles; en otro caso devuelve false. Este m todo,
heredado de la clase R e ad e r, perm ite realizar operaciones
anlogas al m todo a v a ila b le de la clase In p u tStre a m .
C om o ejem plo, vam os a m odificar la ltim a versin de la clase L eer que rea
lizam os en el captulo anterior, con el fin de aadirla algunas capacidades ms,
com o m irar cul es el siguiente carcter en la entrada, leer un solo carcter o lim
piar el flujo de entrada.
import j a v a . i o . * :
II...
I
InputStreamReader i s r = new I n p u t S t r e a m R e a d e r ( S y s t e m . i n ) ;
Finalm ente, una sentencia com o str = L eer.dato() perm itir leer de flu jo E ca
racteres proporcionados por isr resultantes de la conversin de los bytes que ste
obtiene del origen S ystem .in , segn ilustra la figura siguiente:
C A PTU LO 12: T R A B A JA R C O N FICHEROS 4 2 7
El m todo m irar perm itir conocer cul es el siguiente carcter que se puede
leer del flujo de entrada. Para ello, este m todo leer el prim er carcter disponible
en el flujo y a continuacin lo devolver al m ism o para que est disponible para
u na siguiente lectura. El m todo retom ar ese carcter para que quien lo invoque
pueda analizar cul ser el siguiente carcter que se leer del flujo; si no hubiera
ningn carcter esperar a que el usuario realice una entrada.
try
I
c a r = f 1u j o E . r e a d ( ) ;
f 1u j o E . u n r e a d ( c a r );
1
catchlOException e)
[
System .err,print1n("Error: " + e .g e tM e ssa g e t));
I
return (char)car; // r e t o r n a r e l primer car cter d is p o n ib le
428 JA VA: C U R SO DE PROGRAM A CIN
try
1
car - f 1u j o E . r e a d t );
1
catchtlOException e)
I
Sy ste m .e rr.p rin tln C 'E rro r: " + e .g e tM e ssa g e ()):
1
return (char)car; // d e v o l v e r el dato tecleado
1
El m todo dato ha sido m odificado para que realice la m ism a funcin que
realizaba en su versin anterior; esto es, leer una lnea de texto que devolver en
un objeto de la clase S trin g , entendiendo por lnea de texto la cadena form ada por
los caracteres que hay hasta encontrar uno de los siguientes: V , 'V f o am bos;
estos caracteres sern ledos pero no alm acenados. E sta nueva versin es com o
consecuencia de que la clase P u s h b a c k R e a d e r no tiene el m todo re a d L in e c o
m o ocurra con la clase B u ffe re d R e a d e r.
try
I
// L e e r . La e n t r a d a f i n a l i z a al p u l s a r l a t e c l a E n t r a r
w hile ( ( c a r = f l u j o E . r e a d t )) ! - \ r && c a r ! = - 1 )
s d a t o . a p p e n d ( ( c h a r l e a r );
1 i m p i a r ( );
1
c a t c h t l O E x c e p t i o n e)
I
S y s t e m . e r r . p r i n t l n ( " E r r o r : " + e , g e t M e s s a g e ( 1):
i f (c a r = - -1) re tu rn n u il :
r e t u r n s d a t o . t o S t r i n g t ) ; // d e v o l v e r e l dato tecleado
I
CA PTU LO 12: TRA B A JA R CON FIC H ER O S 4 2 9
p u b lic e l a s s Test
i
p u b lic s t a t ic void m a in (S trin g [] args)
I
c h a r c a r = 0, c e r o = ( c h a r ) ' O ' . nueve = ( c h a r ) ' 9 ' .menos = ( c h a r ) ' - ' :
S t r i n g s = n u l 1;
double d = 0.0;
S y s t e m . o u t . p r i n t l " d a t o : >:
i f ( ( c a r = L e e r . m i r a r ( ) ) >= c e r o && c a r <= nueve || c a r = menos)
d - L e e r . d a t o D o u b l e );
el se
s = L e e r , d a t o ( );
if ( s 1= n u i l )
System .out.println(s):
el se
S y s t e m . o u t .p r i n t l n ( d ) :
La prim era vez que se utilice la clase L eer cuando se ejecute la aplicacin, se
r definido el flujo de entrada referenciado p o r su m iem bro flu jo E , que estar dis
ponible hasta que finalice dicha aplicacin.
Este tipo de acceso generalm ente se u tiliza con ficheros de texto en los que se
escribe toda la inform acin desde el principio hasta el final y se lee de la misma
forma. En cam bio, los ficheros de texto no son los m s apropiados para alm acenar
grandes series de nm eros, porque cada nm ero es alm acenado com o una secuen
cia de bytes; esto significa que un nm ero entero de nueve dgitos ocupa nueve
bytes en lugar de los cuatro requeridos para un entero. De ah que a continuacin
se expongan distintos tipos de flujos: de bytes y de caracteres para el tratam iento
de texto, y de datos para el tratam iento de nm eros.
Flujos de bytes
Los datos pueden ser escritos o ledos de un fichero byte a byte utilizando flujos
de las clases F ile O u tp u tS tr e a m y F ile ln p u tS tre a m .
FileOutputStream
F i 1 e O u t p u t S t r e a m t S t r i ng n o m b r e )
F i l e O u t p u t S t r e a m C S t r i n g nombre, b o o l e a n aadir)
F i l e O u t p u t S t r e a m ( F i 1 e fichero)
El siguiente ejem plo es una aplicacin Java que lee una lnea de texto desde el
teclado y la guarda en un fichero denom inado te.xto.lxt.
4. Escribe explcitam ente la lnea de texto en el flujo (im plcitam ente la escribe
en el fichero). Esto se hace cuando el flujo recibe el m ensaje w rite, lo que
origina que se ejecute el m todo w rite, en este caso con tres parm etros: el
prim ero es una referencia a la m atriz q ue contiene los bytes que deseam os es
cribir, el segundo es la posicin en la m atriz del p rim er byte que se desea es
cribir y el tercero, el nm ero de bytes a escribir.
f s . w r i t e b u f f e r , 0. nbytes);
import j a v a . i o . * :
public c la ss C EscribirB ytes
I
public static v o i d main (StringC] args)
I
FileOutputStream fs = n u il;
b y t e [ ] b u f f e r = new b y t e [ 8 1 ] :
int nbytes:
try
I
S y s t e m . o u t . p r i n 1 1n (
" E s c r i b a e l t e x t o q u e d e s e a a l m a c e n a r en e l fichero:"):
nbytes = S y ste m .in . r e a d (b u f f e r ) ;
f s = new F i l e O u t p u t S t r e a m C t e x t o . t x t " ) :
f s . w r i t e t b u f f e r . 0. n b y t e s ) :
I
catchIOException e)
I
System .out.p r i n t n ( " E r r o r : " + e . t o S t r i n g ));
C uando ejecute la aplicacin escriba una lnea de texto y pulse la tecla Entrar.
A continuacin, en la lnea de rdenes del sistem a, teclee type texto.txt en W in
dow s, o bien cat texto.txt en UNIX, para m ostrar el texto del fichero y com probar
que todo ha funcionado com o esperaba.
En este caso, si el fichero no existe se crea y si existe, los datos que se escri
ban en l se aadirn al final.
432 JA V A: C U R SO D E PROGRAM A CIN
E s una buena costum bre cerrar un flujo cuando y a no se vaya a utilizar ms.
A plicando esta idea en la aplicacin anterior, el cdigo quedara as:
try
I
System .out.println
" E s c r i b a e l t e x t o que d e s e a a l m a c e n a r en e l fichero:"):
n b y t e s - S y s t e m . i n . r e a d b u f f e r ):
f s - new F i 1e O u t p u t S t r e a m " t e x t o . t x t " ) ;
f s . w r i t e b u f f e r . 0, n b y t e s ) ;
I
catchIOException e)
I
System .out.p rintln"Error: + e.t o S t r i n g )):
finally
I
try
I
// C e r r a r e l f i c h e r o
i f ( f s ! - n u l 1 ) f s . c l o s e ):
1
c a t c h I O E x c e p t i o n e)
(
System .out.p rintln ("Error: " + e . t o S t r i n g )):
try
I
System .out.println
" E s c r i b a e l t e x t o q u e d e s e a a l m a c e n a r en e l fichero:"):
n b y t e s = S y s t e m . i n . r e a d b u f f e r ):
f s - new F i 1e O u t p u t S t r e a m t e x t o . t x t " ):
f s . w r i t e b u f f e r . 0, n b y t e s ) :
if (fs !- nu il) fs.c lo se ):
I
II...
A unque esta form a de proceder tam bin es vlida no es tan eficiente com o la
anterior, porque qu sucedera si el m todo w rite lanzara una excepcin? N o se
ejecutara cise, aunque finalm ente el sistem a se encargara de cerrar el flujo.
C A PTU LO 12: TRA BA JA R CON FICHEROS 433
FilelnputStream
F i l e l n p u t S t r e a m S t r i n g nombre)
F i 1 e l n p u t S t r e a m F i l e fichero)
El siguiente ejem plo es una aplicacin Java que lee el texto guardado en el fi
chero texto.txt creado por la aplicacin anterior y lo alm acena en una m atriz de
nom inada buffer.
2. D efine un flujo f e desde un fichero denom inado texto.txt. T enga presente que
si el fichero no existe, se lanzar una excepcin indicndolo.
3. Lee el texto desde el flujo y lo alm acena en buffer. Esto se hace cuando el
flujo recibe el m ensaje read. lo que origina que se ejecute el m todo read, en
este caso con tres parm etros: el prim ero es una referencia a la m atriz que al
m acenar los bytes ledos, el segundo es la posicin en la m atriz del prim er
byte que se desea alm acenar y el tercero, el nm ero m xim o de bytes que se
leern. El m todo devuelve el nm ero de bytes ledos o -1 si no hay m s datos
porque se ha alcanzado el final del fichero.
import j a v a . i o . * :
public c la s s CLeerBytes
434 JA VA : C U R SO DE PROGRAM A CIN
try
I
f e = new F i l e I n p u t S t r e a m C t e x t o . t x t " ) :
n b y t e s = f e . r e a d ( b u f f e r . 0. 8 1 ) :
S t r i n g s t r = new S t r i n g ! b u f f e r . 0. n b y t e s ) :
System .out.p rin tln (str);
I
catch!IOException e)
I
S y s te m .o u t .p r in t ln ("E r r o r : " + e . t o S t r i n g ! ));
I
f i n a 11 y
I
try
1
// C e r r a r e l f i c h e r o
i f (fe != n u i l ) f e . c i s e ! ) :
I
catch! IOException e)
I
System .out.p rintln !"Error: " + e.toString!)):
Clase File
El ejem plo anterior utiliza un S tr in g para referirse al fichero, pero tam bin podra
haber utilizado un objeto de la clase File. U n objeto de esta clase representa el
nom bre de un fichero o de un directorio que puede existir en el sistem a de fiche
ros de la m quina; por lo tanto, sus m todos perm itirn interrogar al sistem a sobre
todas las caractersticas de ese fichero o directorio. A dem s de los m todos a los
que nos referim os, la clase proporciona los constructores siguientes:
public F i l e ( S t r i n g ruta_completa)
public F i l e S t r i n g ruta. S t r i n g n o m b r e )
public F i l e F i l e ruta. S t r i n g n o m b r e )
Nombre d e l f i c h e r o : texto.txt
D i r e c t o r i o padre: proyecto
Ruta r e l a t i v a : proyecto\texto.txt
Ruta a b s o l u t a : C:\java\proyecto\texto.txt
El tercer constructor crea un objeto F ile a partir de otro que represente una
ru ta (absoluta o relativa) y un nom bre de fichero separado. P or ejem plo, el objeto
fic h e ro del ejem plo anterior podra definirse tam bin as:
M todo_____________ Significado______________________________________________
ge tN a m e D evuelve el nom bre del fichero especificado por el objeto
F ile que recibe este m ensaje.
ge tP are nt D evuelve el directorio padre.
g e tP a th D evuelve la ruta relativa del fichero.
g e tA b so lu te P a th D evuelve la ruta absoluta del fichero,
exists D evuelve true si el nom bre especificado p o r el objeto File
que recibe este m ensaje existe.
c a n W r ite r D evuelve true si se puede escribir en el fichero o directorio
especificado por el objeto File.
436 JA VA : CU R SO D E PROGRAM A CIN
M todo Significado
canRead D evuelve true si se puede leer desde el fichero o directorio
especificado por el objeto File.
isFile D evuelve tru e si se trata de un fichero vlido.
isD ire cto ry D evuelve true si se trata de un directorio vlido.
isH id d c n D evuelve true si se trata de un fichero o directorio oculto.
length D evuelve el tam ao del fichero (cuando se trate de un di
rectorio, el valor devuelto es cero).
list D evuelve una m atriz de objetos S t r in g q ue alm acena los
nom bres de los ficheros y directorios que hay en el directo
rio especificado por el objeto File.
m k d ir C rea el directorio especificado p o r el objeto File.
m k d irs C rea el directorio especificado por el objeto F ile incluyen
do los directorios que no existan en la ruta especificada.
delete B orra el fichero o directorio especificado por el objeto File.
C uando se trate de un directorio, ste debe de estar vaco.
d e le te O n E x it Igual que delete. pero cuando la m quina virtual term ina.
create T e n ip F ile C rea el fichero vaco especificado por los argum entos pa
sados, en el directorio tem poral del sistem a.
re n am e T o R enom bra el fichero especificado por el objeto F ile que re
cibe este m ensaje, con el nom bre especificado p o r el objeto
File pasado com o argum ento.
se tR e a d O n ly M arcar el fichero o directorio especificado por el objeto
File de slo lectura.
to S trin g D evuelve la ruta especificada cuando se cre el objeto File.
//
S t r i n g nombreFichero = n u i l :
F i l e f i c h e r o = n u l 1:
f e - new F i l e l n p u t S t r e a m ( f i c h e r o ) ;
n b y t e s = f e . r e a d b u f f e r . 0. 8 1 ) ;
// ...
i
II ...
// ...
Strin g nombrenchero = n u il:
F i l e f i c h e r o = n u l 1;
try
1 _ _____
S y s t e m . o u t . p r i n t t " N o m b r e del f i c h e r o : ):
nbytes = Sy ste m .in . re a d ( b u f f e r ) ;
n o m b r e F i c h e r o = new S t r i n g t b u f f e r , 0 , nbytes-2); // menos C R+ L F
f i c h e r o = new F i 1e ( n o m b r e F i c h e r o ) ;
if (resp == s *)
!
System .out.println
" E s c r i b a e l t e x t o q u e d e s e a a l m a c e n a r en e l f i c h e r o : ):
nbytes = S y ste m .in .r e a d (b u f f e r ) ;
f s = new F i 1 e O u t p u t S t r e a m ( f i c h e r o ) :
f s . w r i t e ( b u f f e r , 0. n b y t e s ) :
I
I
II...
Flujos de caracteres
Una vez que sabem os trabajar con flujos de bytes, hacerlo con flujos de caracteres
es prcticam ente lo m ism o. Esto nos ser til cuando necesitam os trabajar con
texto representado por un conjunto de caracteres A SC II o U nicode. Las clases que
definen estos flujos son subclases de R e ad e r, com o F ile W r if e r y F ileR ead er.
438 JA V A: C U R SO D E PROGRAM A CIN
FileW riter
F i 1e W r i t e r ( S t r i n g nombre)
F i l e W r i t e r t S t r i n g nombre, b o o l e a n aadir)
F i 1 e W r i t e r ( F i 1 e fichero)
import ja v a .i o . * ;
b y t e [ ] b u f f e r = new b y t e [ 8 1 ] ;
int nbytes;
S t r i n g nombreFichero = n u i l ;
F ile fichero = n u il;
try
if (resp == s *)
I
System .out.println
" E s c r i b a e l t e x t o que d e s e a a l m a c e n a r en e l f i c h e r o : ):
n b y t e s = S y s t e m . i n . r e a d ( b u f f e r );
S t r i n g s t r - new S t r i n g ( b u f f e r . 0, n b y t e s ) :
f s = new F i l e W r i t e r ( f i c h e r o ) ;
f s . w r i t e s t r . 0. s t r .1e n g t h ) ) ;
catchIOException e)
1
S y s t e m .o u t . p r i n t l n i " E r r o r : + e . t o S t r i n g ( ) ) ;
)
f i n a 11 y
1
try
I
// C e r r a r e l f i c h e r o
i f ( f s != n u i l ) f s . c l o s e );
1
c a t c h I O E x c e p t i o n e)
[
S y s t e m . o u t . p r i n t n i " E r r o r : " + e . t o S t r i n g ));
FileReader
U n flujo de la clase F ile R e a d e r perm ite leer caracteres desde un fichero. Adem s
de los m todos que esta clase hereda de R e a d e r, la clase proporciona los cons
tructores siguientes:
F i 1e R e a d e r S t r i n g n o m b r e )
F i 1e R e a d e r F i 1e f i c h e r o )
import j a v a . i o . * ;
440 JA V A: C U R S O DF. PROGRAM A CIN
try
I
do
I
S y s t e m . o u t . p r i n t ( " N o m b r e del f i c h e r o : " ) ;
n b y t e s = S y s t e m . i n . r e a d ( n o m F i c h ):
no m b r e F i c h e r o - new S t r i n g ( n o m F i c h , 0. n b y t e s - 2 ) ; // menos CR+LF
f i c h e r o - new F i l e ( n o m b r e F i c h e r o ) :
1
w h i 1e ( ! f i c h e r o . e x i s t s ( ) ) ;
f e - new F i 1 e R e a d e r ( f i c h e r o ) :
n c a r s - f e . r e a d ( b u f f e r , 0. 8 1 ) :
S y s t e m . o u t . p r i n t l n ( b u f f e r );
I
catch(IOException e)
[
System .out.p rintln!"Error: " + e . t o S t r i n g ( ));
I
finally
I
try
I
// C e r r a r e l f i c h e r o
i f ( f e ! = n u i l ) f e . c l o s e ( ):
I
catchIOException e)
I
S y s t e m .o u t .p r in t ln ("E r r o r : " + e .t o S t r i n g ( )):
I
I
I
Flujos de datos
Seguram ente, en alguna ocasin desearem os escribir en un fichero datos de tipos
prim itivos (boolean. byte, double, float, long, in t y sh o rt) para posteriorm ente
C A P T U L O 12: TRA BA JA R CON FIC H ER O S 4 4 1
recuperarlos com o tal. Para estos casos, el paquete ja v a .io proporciona las clases
D a ta ln p u tS tr e a m y D a ta O u tp u tS tr e a m , las cuales perm iten leer y escribir, res
pectivam ente, datos de cualquier tipo prim itivo. Entonces, por qu no se han
analizado previam ente? Pues, sim plem ente porque no pueden utilizarse con los
dispositivos A SC II de E/S estndar. Un flujo D a ta ln p u tS tr e a m slo puede leer
datos alm acenados en un fichero a travs de un flujo D a ta O u tp u tS tr e a m .
O bserve que los flujos de estas clases actan com o filtros; esto es, los datos
obtenidos del origen o enviados al destino son transform ados m ediante alguna
operacin; en este caso, sufren una conversin a un form ato portable (UTF-8:
U nicode ligeram ente m odificado) cuando son alm acenados y viceversa cuando
son recuperados. El procedim iento para utilizar un filtro es bsicam ente as:
DataOutputStream
T odos los m todos proporcionados por esta clase estn definidos en la inter
faz D a ta O u tp u t im plem entada p o r la m ism a.
V eam os un ejem plo. Las siguientes lneas de cdigo definen un filtro que
perm itir escrib ir datos de tipos prim itivos en un fichero datos.dat:
F i l e O u t p u t S t r e a m f o s = new F i l e O u t p u t S t r e a m ( n o m b r e F i c h e r o ) :
D a t a O u t p u t S t r e a m d o s = new D a t a O u t p u t S t r e a m ( f o s );
// A l m a c e n a r e l nombre l a d i r e c c i n y el t e l f o n o en e l f i c h e r o
d o s.w rit e U T F "u n nombre");
d o s . w r i t e U T F ( " u n a d i r e c c i n );
dos.w ri te Lo ng(942334455):
dos.closeO : fos.closeO ;
M todo D escripcin
w rite B oole an Escribe un valor de tipo boolean.
w riteByte Escribe un valor de tipo byte.
w rite Byte s Escribe un S t r in g com o una secuencia de bytes.
w rite C h a r Escribe un valor de tipo char.
w r ite C h a rs Escribe un S t r in g com o una secuencia de caracteres.
w rite S h o rt Escribe un valor de tipo short.
w rite ln t E scribe un valor de tipo int.
w r ite L o n g Escribe un valor de tipo long.
w rite Float E scribe un valor de tipo float.
w rite D o u b le E scribe un valor de tipo double.
w r ite U F T Escribe una cadena de caracteres en form ato U TF-8; los
dos prim eros bytes especifican el nm ero de bytes de da
tos escritos a continuacin.
DatalnputStream
T odos los m todos proporcionados por esta clase estn definidos en la inter
faz D a t a ln p u t im plem entada p o r la m ism a.
V eam os un ejem plo. Las siguientes lneas de cdigo definen un filtro que
perm itir leer datos de tipos prim itivos desde un fichero datos.dat:
F i 1e l n p u t S t r e a m f i s = new F i 1e ! n p u t S t r e a m ( d a t o s . d a t " );
DatalnputStream d i s = new D a t a I n p u t S t r e a m ( f i s ) :
Fi 1e I n p u t S t r e a m f i s = new F i l e l n p u t S t r e a m ( n o m b r e F i c h e r o ) :
D a t a l n p u t S t r e a m d i s = new D a t a I n p u t S t r e a m ( f i s ):
// L e e r e l nombre l a d i r e c c i n y e l t e l f o n o d e l f i c h e r o
nombre = d i s . r e a d U T F );
d i r e c c i n = d i s .readUTF():
t e l f o n o = d i s . r e a d L o n g ):
dis.close O ; fis.close O ;
M todo D escripcin
re a d B o o le a n D evuelve un valor de tipo boolean.
read B yte D evuelve un valor de tipo byte.
re a d Sh o rt D evuelve un valor de tipo short.
read C har D evuelve un v alo r de tipo char.
re a d ln t D evuelve un valor de tipo int.
read Long D evuelve un valor de tipo long.
read F loat D evuelve un valor de tipo float.
re a d D o u b le D evuelve un valor de tipo double.
re a d U F T D evuelve una cadena de caracteres en form ato U TF-8; los
dos prim eros bytes especifican el nm ero de bytes de da
tos que sern ledos a continuacin.
A brim os un flujo desde el fichero del cual querem os leer los datos.
Leem os los datos del fichero y los alm acenam os en variables de nuestro pro
gram a con el fin de trabajar con ellos. Este proceso se hace norm alm ente re
gistro a registro. Para ello, utilizarem os los m todos proporcionados por la
interfaz del flujo.
C erram os el ujo.
S t r i n g n o mbr e , direccin:
long telfono:
Para realizar este ejem plo, escribirem os una clase aplicacin C rearListaTfnos
con dos m todos: crearF ichero y m ain.
El m todo crearF ichero recibe com o parm etro un objeto File que define el
nom bre del fichero que se desea crear y realiza las tareas siguientes:
C rea un flujo hacia el fichero especificado por el objeto F ile que perm ite es
cribir datos de tipos prim itivos utilizando un buffer.
Lee grupos de datos nom bre, direccin y telfono de la entrada estndar y los
escribe en el fichero.
Si durante su ejecucin alguno de los m todos invocados lanza una excep
cin. la vuelve a lanzar para que sea atrapada por el m todo que le invoc.
C rea un objeto F ile a partir del nom bre del fichero ledo desde la entrada es
tndar.
V erifica si el fichero existe.
C A PTU LO 12: TRA BA JA R C O N FIC H ER O S 4 4 5
import j a v a . i o . * ;
public c la ss CrearListaTfnos
I
pu b lic s t a t ic void c r e a r F ic h e r o F ile fichero)
throws IOException
I
P r i n t S t r e a m f l u j o S = S y s t e m . o u t : // s a l i d a e s t n d a r
D a t a O u t p u t S t r e a m d o s = n u i l : / / s a l i d a de d a t o s h a c i a el fichero
char resp;
try
I
// C r e a r un f l u j o h a c i a e l f i c h e r o q u e p e r m i t a e s c r i b i r
// d a t o s de t i p o s p r i m i t i v o s y q u e u t i l i c e un b u f f e r .
d o s = new D a t a O u t p u t S t r e a m n e w B u f f e r e d O u t p u t S t r e a m
new F i l e O u t p u t S t r e a m t f i c h e r o ) ) ) :
// D e c l a r a r l o s d a t o s a e s c r i b i r en e l fichero
S t r i n g n o mb r e , d i r e c c i n :
long te lfo n o:
// L e e r d a t o s de l a entrada estndar y e s c r ib ir lo s
// en e l f i c h e r o
do
1
f l u j o S . p r i n t "nombre: "): no mb r e = L e e r . d a t o O :
f 1u j o S . p r i n t ( " d i r e c c i n : " ) : direccin - Leer.datoO :
flu joS.print"telfono: "); t e l f o n o = L e e r . d a t o L o n g );
// A l m a c e n a r un n o mb r e , una d i r e c c i n y un t e l f o n o en
// e l f i c h e r o
dos.wri teUTFnombre);
dos.w riteUTFdi re c c i n ) :
dos.w riteLong t e l f o n o ) :
if (dos != n u i l ) dos.closet);
try
I
// C r e a r un o b j e t o F i l e q u e i d e n t i f i q u e al fichero
f l u j o S . p r i n t t " N o m b r e del f i c h e r o : " ) ;
nombreFichero = L e e r . d a t o O ;
f i c h e r o = new F i 1e ( n o m b r e F i c h e r o ) ;
// V e r i f i c a r s i e l f i c h e r o existe
char resp = ' s ;
i f ( f i c h e r o . e x i s t s ( ))
I
f l u j o S . p r i n t C E l f i c h e r o e x i s t e des ea s o b r e e s c r i b i r i o ? (s/n) " ) ;
r e s p = L e e r . c a r c t e r ( );
L e e r . 1 i mpi a r ( ) ;
I
if (resp == 's ')
[
crearFichero(fichero);
I
I
catch(IOException e)
1
f l u j o S . p r i n t n ( " E r r o r : " + e.getM essaget));
Lee un grupo de datos nom bre, direccin y telfono desde el fichero y los
m uestra. C uando se alcance el final del fichero Java lanzar una excepcin del
tipo E O F E x c e p tio n , instante en el que finalizar la ejecucin de este mtodo.
Si durante su ejecucin alguno de los m todos invocados lanza una excepcin
IO E x c e p tio n . la pasa para que sea atrapada por el m todo que le invoc.
El m todo m a in recibe com o parm etro el nom bre del fichero que se desea
crear y realiza las tareas siguientes:
import j a v a . i o . * ;
try
I
// C r e a r un o b j e t o F i l e q u e i d e n t i f i q u e al fichero
f i c h e r o = new F i l e t n o m b r e F i c h e r o ) ;
// V e r i f i c a r s i e l f i c h e r o existe
i f ( f i c h e r o . e x i s t s t ))
1
// S i e x i s t e , a b r i r un f l u j o d e s d e e l mismo
d i s = new D a t a I n p u t S t r e a m l n e w B u f f e r e d I n p u t S t r e a m t
new F i l e l n p u t S t r e a m ( f i c h e r o ) ) ) ;
// D e c l a r a r l o s d a t o s a l e e r desde el fichero
S t r i n g n o mb r e , d i r e c c i n :
long te lfono:
do
I
// L e e r un n o mbr e , una d i r e c c i n y un t e l f o n o d e s d e el
// f i c h e r o . C u a n d o s e a l c a n c e e l f i n a l d e l f i c h e r o J a v a
// l a n z a r una e x c e p c i n d e l t i p o E O F E x c e p t i o n .
nombre = d i s . r e a d U T F ( ) :
d i r e c c i n = d i s . r e a d U T F ( );
448 JA VA: C U R SO DE PROGRAM A CIN
t e l f o n o = d i s . r e a d L o n g );
SERIACIN DE OBJETOS
En el apartado anterior hem os aprendido cm o escribir y leer grupos de datos a y
desde un fichero. Pero en un desarrollo orientado a objetos debem os pensar en
objetos; por lo tanto, ese grupo de datos al que nos hem os referido no lo tratare-
C A PTU LO 12: T R A B A JA R CON FICHEROS 4 4 9
P ara poder seriar los objetos de una clase, sta debe de im plem entar la inter
faz Se rializable. Se trata de una interfaz vaca; esto es, sin ningn m todo; su
propsito es sim plem ente identificar clases cuyos objetos se pueden seriar.
El siguiente ejem plo, define la clase C Persona com o una clase cuyos objetos
se pueden seriar:
import j a v a . i o . * ;
C om o la interfaz S e ria liz a b le est vaca no hay que escribir ningn m todo
extra en la clase.
import j a v a . i o . * :
// S e u t i l i z a t a m b i n la clase Leer, m odificada en e s t e c a p i t u l o
public c la ss CrearListaTfnos
I
p u b l i c s t a t i c v o i d c r e a r F i c h e r o ( F i 1e f i c h e r o )
th rows lO E x c e p t io n
I
P r i n t S t r e a m f l u j o S = S y s t e m . o u t ; // s a l i d a e s t n d a r
O b j e c t O u t p u t S t r e a m o o s = n u i l ; / / s a l i d a de d a t o s h a c i a e l fichero
char resp:
CA PTU LO 12: TR A B A JA R CON FICHEROS 451
try
[
// C r e a r un f l u j o h a c i a e l f i c h e r o q u e p e r m i t a e s c r i b i r
// o b j e t o s y d a t o s de t i p o s p r i m i t i v o s .
o o s = new O b j e c t O u t p u t S t r e a m ( n e w F i 1 e O u t p u t S t r e a m f i c h e r o ) );
// D e c l a r a r l o s d a t o s a e s c r i b i r en e l f i c h e r o
S t r i n g n o mbr e , d i r e c c i n ;
long te lfo n o;
// L e e r d a t o s de l a entrada estndar y e s c r ib ir lo s
// en el f i c h e r o
do
I
flujoS.print"nom bre: ); nombre = L e e r . d a t o ) :
flu jo S .p rin t( "d ireccin: "); direccin = Leer.dato):
flu j o S . p r in t ( "telfono: "); t e l f o n o = L e e r . d a t o L o n g );
// C r e a r un o b j e t o C P e r s o n a y a l m a c e n a r l o en e l fichero
oos.w riteO bje ctne w CPersonanombre, d ire c c i n , telfono));
/ / ...
I
w h i 1e ( r e s p = = ' s '):
/ / ...
S t r i n g s t r = ( S t r i n g ) o i s . r e a d U T F );
C P e r s o n a p e r s o n a = ( C P e r s o n a ) o i s . r e a d O b j e c t );
o i s . c l o s e );
452 JA VA : C U R SO DE PRO G R A M A CI N
import j a v a . i o . * ;
public c la ss M ostrarListaTfnos
I
p u b lic s t a t i c void mostrarl;i c h e r o ( S t r i n g nombreFichero)
th rows IO E x c e p tio n
I
P r i n t S t r e a m f l u j o S - S y s t e m . o u t ; // s a l i d a e s t n d a r
O b j e c t l n p u t S t r e a m o i s - n u i l : / / e n t r a d a d e d a t o s d e s d e el f i c h e r o
F ile fichero = nu il: // o b j e t o q u e i d e n t i f i c a e l f i c h e r o
// C r e a r un o b j e t o F i l e q u e i d e n t i f i q u e al fichero
f i c h e r o = new F i 1e ( n o m b r e F i c h e r o ):
// V e r i f i c a r s i e l f i c h e r o existe
i f ( f i c h e r o . e x i s t s ( ))
I
// S i e x i s t e , a b r i r un f l u j o d e s d e e l mismo
o i s - new O b j e c t I n p u t S t r e a m ( n e w F i 1 e I n p u t S t r e a m ( f i c h e r o ) ) :
// D e c l a r a r l o s d a t o s a l e e r d e s d e e l f i c h e r o
CPersona persona:
S t r i n g n o mb r e , d i r e c c i n :
long telfono:
do
I
// L e e r un o b j e t o C P e r s o n a d e s d e e l f i c h e r o . Cuando se
// a l c a n c e e l f i n a l d e l f i c h e r o J a v a l a n z a r una
// e x c e p c i n d e l t i p o E O F E x c e p t i o n .
p e r s o n a = ( C P e r s o r i a ) o i s . r e a d O b j e c t ( ):
// ...
I
w hile (true):
I
el se
f l u j o S . p r i n t l n ( "El f i c h e r o no e x i s t e " ) :
I
c a t c h ( E O F E x c e p t 'i o n e)
1
f 1u j o S . p r i n t l n ( " F i n del listado"):
c a t c h ( C l a s s N o t F o u n d E x c e p t i o n e)
1
f l u j o S . p r i n t l n ( " E r r o r : " + e .g e t M e s s a g e ));
C A P T U L O 12: TRA B A JA R C O N FIC H ER O S 4 5 3
fi nally
I
// C e r r a r e l f l u j o
i f ( o s != n u i l ) o i s . c l o s e O ;
import j a v a . i o . * :
public c la ss CListaTfnos i m p l e m e n t s S e r i a l i z a b l e
1
// ...
I
Pero seriar un objeto C ListaTfnos im plica seriar los objetos C Persona refe
renciados por el prim ero. P or lo tanto, esta segunda clase tam bin tiene que im-
plem entar la interfaz S erializab le:
import j a v a . i o . * :
p u b lic c l a s s CPersona i m p l e m e n t s S e r i a l i z a b l e
I
// ...
I
D espus de realizar estas m odificaciones, slo queda cam biar la clase aplica
cin Test para que guarde la lista, slo si ha sido m odificada, en un fichero deno
m inado listatfnos.dat cuando la aplicacin finalice, y la recupere cuando la
aplicacin se inicie. A continuacin se m uestra el cdigo com pleto de la clase
Test, en el que se resaltan los aadidos m s im portantes que se han realizado:
import j a v a . i o . * :
/////////////////////////////////////////////////////////////////
// A p l i c a c i n l i s t a d e t e l f o n o s . C u a n d o l a a p l i c a c i n f i n a l i z a
// l a l i s t a e s s a l v a d a en un f i c h e r o " l i s t a t f n o s . d a t " y c u a n d o
// s e i n i c i a s e r e c u p e r a de e s e f i c h e r o .
//
public class Test
I
public static i n t men)
I
S y s t e m . o u t . p r i n t t " \ n \ n );
S y s t e m . o u t . p r i n t l n "1. B u s c a r") :
S y s t e m . o u t . p r i n t l n ( 2. B u s c a r s i g u i e n t e " ) :
S y s t e m . o u t . p r i n t l n "3. A a d ir ") ;
S y s t e m . o u t . p r i n t l n i " 4 . E l i m i n a r " ):
S y s t e m . o u t . p r i n t l n "5. S a l i r " ) :
S y s t e m . o u t . p r i n t l n ):
System .out.p rint Opcin: " ) :
i n t op:
do
op - L e e r . d a t o l n t ):
w h i 1e ( o p < 1 || op > 5 ) :
r e t u r n op:
)
// D e f i n i r un f l u j o de c a r a c t e r e s de e n t r a d a : f l u j o E
I n p u t S t r e a m R e a d e r i s r = new I n p u t S t r e a m R e a d e r S y s t e m . i n ) :
B u f f e r e d R e a d e r f l u j o E = new B u f f e r e d R e a d e r i s r );
// D e f i n i r una r e f e r e n c i a a l f l u j o e s t n d a r de s a l i d a : f l u j o S
PrintStream f lu j o S = System.out;
CL1 s t a T f n o s l i s t a t f n o s 2
i n t o p c i n - 0 . p o s = - 1;
S t r in g cadenabuscar = nu il
S t r i n g n o mbr e , d i r e c c i n :
long telfono;
boolean e lim ina d o = f a l s e ;
false:
try
// C r e a r un o b j e t o l i s t a de t e l f o n o s v a c i o ( c o n 0 e l e m e n t o s )
// o c o n e l c o n t e n i d o d e l f i c h e r o l i s t a t f n o s . d a t s i e x i s t e .
F i l e f i c h e r o - new F i 1e ( "1 i s t a t f n o s . d a t " );
if ( fiche ro.e x istsO )
i
l i s t a t f n o s - new C L i s t a T f n o s ( ) :
f l u j o S . p r i n t l n " S e ha c r e a d o una l i s t a de t e l f o n o s n u e v a " ) :
1
else
I
O b j e c t l n p u t S t r e a m o i s = new O b j e c t l n p u t S t r e a m
new F i l e l n p u t S t r e a m ( "1 i s t a t f n o s . d a t " ) ) :
lista tfn o s - (CListaTfnos)ois.readO bjectO ;
o i s . c l o s e ):
f l u j o S . p r i n t l n " S e c a r g l a l i s t a de t e l f o n o s c o n x i t o " ) :
1
do
opcin - m e n ):
switch (opcin)
I
c a s e 1: // b u s c a r
f l u j o S . p r i n t " c o n j u n t o de c a r a c t e r e s a b u s c a r "):
c a d e n a b u s c a r = f 1 u j o E . r e a d L i n e ):
pos - 1 i s t a t f n o s . b u s c a r c a d e n a b u s c a r . 0 ) ;
i f (pos -1)
i f (1 i s t a t f n o s . 1 o n g i t u d ) ! - 0 )
f l u j o S . p r i n t n ( " b s q u e d a f a l l i d a " );
el se
f lu jo S . p r in t ln ( * lis t a vacia"):
else
456 JA V A : C U R SO D E PRO G R A M A CI N
f l u j o $ . p r i n t l n ( 1 i s t a t f n o s . v a l o r E n ( p o s ) . obten er No mbr e * ) ) ;
f l u j o S . p r i n t l n ( l i s t a t f n o s . v a l o r E n ( p o s ) . o b t e n e r D i r e c c i 6 n ( )):
f l u j o S . p r i n t l n d i s t a t f n o s . v a l o r E n ( p o s ) . o b t e n e r T e l f o n o ( )):
1
break:
c a s e 2: // b u s c a r s i g u i e n t e
pos - 1i s t a t f n o s . b u s c a d c a d e n a b u s c a r . pos + l):
i f (pos -1)
i f (1 i s t a t f n o s . 1 o n g i t u d ( ) ! - 0)
f 1u j o S . p r i n t l n ( " b s q u e d a f a l 1 i d a " ):
el se
flu jo S . p r in t ln ( "1 ista v a c ia ');
el se
I
flu jo S . p rin t ln d is ta t fn o s . v a lo rE n (p o s ) . o b te n e rN o m b re ( )):
f l u j o S . p r i n t l n ( 1i s t a t f n o s . v a l o r n ( p o s ) . o b t e n e r D ir e c c i n ( )):
f l u j o S . p r i n t l n d i s t a t f n o s . v a l o r E n ( p o s ) . o b t e n e r T e l f o n o ( )):
1
break:
c a s e 3: // a a d i r
flujoS.print"nombre: " ) : nombre - f l u j o E . r e a d L i n e ( ):
f l u j o S . p r i n t d d i r e c c i n : ); d i r e c c i n - f l u j o E . r e a d L i n e ( ):
flujoS.print("telfono: " ) ; t e l f o n o - L e e r . d a t o L o n g ( );
l i s t a t f n o s . a a d i r ( n e w CPersona( nombre, d i r e c c i n , t e l f o n o ) ) :
lista M o d ific a d a - true:
break:
c a s e 4: // e l i m i n a r
f l u j o S . p r i n t ( " t e l f o n o : " ) : t e l f o n o - L e e r , d a t o L o n g ( ):
e lim in a d o - 1i s t a t f n o s . e l i m i n a r ( t e l f o n o ) :
i f (elim inado)
i
f l u j o S . p r i n t l n ( " r e g i s t r o e l i mi n a d o " ) :
lista M o d ifica d a - true:
I
el se
if ( l i s t a t f n o s . l o n g i t u d ) ! 0)
f l u j o S . p r i n t l n ( " t e l f o n o no e n c o n t r a d o " ) :
el s e
f lu j o S . p r in t ln C li s t a vacia"):
break;
c a s e 5: // s a l i r
// g u a r d a r 1 i s t a
i f (listaM odificada)
I
O b j e c t O u t p u t S t r e a m o u s - new O b j e c t O u t p u t S t r e a m (
new F i 1 e O u t p u t S t r e a m "1 i s t a t f n o s . d a t " ) ) :
ous.w riteO bjectd is t a t f n o s ) ;
ous.closeO :
I
C A PTU LO 12: TRA BA JA R C O N FICHEROS 4 5 7
1 i s t a t f n o s = n u l 1:
I
I
w hile(opcin != 5):
1
catch { IOException e )
[
System .out.p rintlnCError: " + e .g e t M e s s a g e ( ));
)
catch ( C l a s s N o t F o u n d E x c e p t i o n e)
[
S y s t e m . o u t . p r i n t l n E r r o r : " + e .g e tM e ssa g e ()):
La clase RandomAccessFile
Un flujo de esta clase perm ite acceder directam ente a cualquier posicin dentro
del fichero vinculado con l.
458 JA V A : C U R S O D E P R O G R A M A C I N
R a n d o m A c c e s s F i l e ( S t r i n g n o m b r e - f i c h e r o . S t r i n g modo)
R a n d o m A c c e s s F i 1e ( F i 1e o b j e t o - F i l e . S t r i n g modo)
M odo Significado
r read. S lo se perm iten realizar operaciones de lectura.
rw read/w rite. Se pueden realizar operaciones de lectura y de
escritura sobre el fichero.
Por ejem plo, el siguiente fragm ento de cdigo construye un objeto F ile para
verificar si el nom bre especificado para el fichero existe com o tal. Si existe y no
corresponde a un fichero se lanza una excepcin; si existe y se trata de un fichero,
se crea un flujo para escribir y leer a y desde ese fichero; y si no existe, tam bin
se crea el flujo y el fichero.
F i l e f i c h e r o - new F i l e C l i s t a t f n o s . d a t " ) :
i f ( f i c h e r o . e x i s t s ( ) && ! f i c h e r o . i s F i l e ( ) )
t h r o w new I O E x c e p t i o n ( f i c h e r o . g e t N a m e ( ) + no e s un f i c h e r o ) :
R a n d o m A c c e s s F i l e l i s t a T e i f o n o s - new R a n d o m A c c e s s F i l e f i c h e r o . rw ):
gativos. El desplazam iento requerido puede ir m s all del final del fichero; esta
accin no cam bia la longitud del fichero; la longitud del fichero slo cam biar si a
continuacin, realizam os una operacin de escritura.
Con esta clase no tenem os posibilidad de seriar objetos. Los datos deben
guardarse uno a uno utilizando el m todo adecuado de la clase segn su tipo. Por
ejem plo, las siguientes lneas de cdigo escriben en el fichero datos a partir de
la posicin d esp , los atributos no m b re, direccin y telfono relativos a un objeto
CPersona:
CPersona o b j e to :
II...
R a n d o m A c c e s s F i l e f e s = new R a n d o m A c c e s s F i l e ( " d a t o s " . " r w " )
f e s .seek(desp);
fe s.w rite U T F o b je to .o b te n e rN o m b re )):
fes.w ri teUTFlobjeto.obtenerDi r e c c i n ));
f e s . w r i t e L o n g ( o b j e t o . o b t e n e r l e 1 f o n o ( ) ) :
La clase CPersona
La clase C P ersona slo se ve m odificada p o r el hecho de haber aadido un m to
d o denom inado tam ao que devuelve la longitud en bytes correspondiente a los
atributos de un objeto C Persona.
11111111111111111111111111111111111111111111111111111111111111111
II D e f i n i c i n de l a c l a s e CPersona
II
public c la ss CPersona
I
II A t r i b u t o s
p r i v a t e S t r i n g n o mbr e :
private S trin g direccin:
p riv a t e long telfono:
// M t o d o s
public CPersona() 11
public void a s i g n a r T e l f o n o 1o n g t e l )
I
telfono = t e l :
)
public long o b te n e r T e l fo n o )
I
return telfono:
I
La clase CListaTfnos
La interfaz de la clase C ListaTfnos ser prcticam ente la m ism a. D e esta form a un
usuario no diferenciara si est trabajando con una m atriz o con un fichero, ex
cepto en que ahora, al utilizar un fichero, los datos persisten de una ejecucin a
otra de la aplicacin.
Constructor CListaTfnos
F i l e f i c h e r o = new F i 1 e ( "1 i s t a t f n o s . d a t ):
C L i s t a T f n o s l i s t a t f n o s = new C L i s t a T f n o s ( f i c h e r o ) ;
/////////////////////////////////////////////////////////////////
// D e f i n i c i n de l a clase CListaTfnos.
//
import j a v a . i o . * :
pu blic c la ss CListaTfnos
private RandomAccessFile fe s : // f l u j o
private int nregs: // n me r o d e r e g i s t r o s
private i n t tamaoReg - 140 ; // t a m a o d e l r e g i s t r o en b y t e s
public v o i d c e r r a r O th rows IO E x c e p t io n I f e s . c l o s e O : 1
public i n t l o n g i t u d O 1 r e t u r n n r e g s : I // n mero de r e g i s t r o s
// ..
// ...
II . ..
El m todo p o n erV alorE n se ha diseado para que perm ita escribir los atributos de
un objeto C Persona dentro del fichero a partir de una posicin determ inada. Tiene
dos parm etros: el prim ero indica el nm ero de registro que se desea escribir, que
puede coincidir con un registro existente, en cuyo caso se sobreescribir este l
tim o, o bien con el nm ero del siguiente registro que se puede aadir al fichero; y
el segundo, hace referencia al objeto C Persona cuyos atributos deseam os escribir.
El m todo devolver un valor true si se ejecuta satisfactoriam ente y false en otro
caso.
leer). Si el tam ao est dentro de los lm ites perm itidos, sita el puntero de L /E en
la posicin d e inicio correspondiente a ese registro dentro del fichero y escribe los
atributos del objeto uno a continuacin de otro (vea la definicin de seek).
El m todo a a d ir tiene com o m isin aadir un nuevo registro al final del fichero.
Para ello, invoca al m todo ponerV alorE n pasando com o argum entos la posicin
que ocupar el nuevo registro, que coincide con el valor de nregs, y el objeto cu
yos atributos se desean escribir.
Para leer un registro del fichero que alm acena la lista de telfonos, la clase C Lis
taTfnos proporciona el m todo valorEn. Este m todo tiene un parm etro para
identificar el nm ero de registro que se desea leer y devuelve el objeto CPersona
creado a partir de los datos nom bre, direccin y telfono ledos desde el fichero.
S t r i n g n o mbr e , d i r e c c i n :
long te lfo n o:
nombre = f e s . r e a d U T F ( ):
d i r e c c i n = f e s . r e a d U T F ( ):
t e l f o n o = f e s . r e a d L o n g ( ):
pondiente a ese registro dentro del fichero y lee los datos nom bre, direccin y te
lfono (esto se hace enviando al flujo f e s vinculado con el fichero, el mensaje
r e a d U T F , u na vez por cada dato). F inalm ente, devuelve un objeto CPersona
construido a partir de los datos ledos (el valor devuelto ser n u il si el nm ero de
registro est fuera de lmites).
Puesto que el fichero m anipulado se corresponde con una lista de telfonos, pare
ce lgico identificar el registro que se desee elim inar p o r el nm ero de telfono,
ya que ste es nico. Para este propsito escribirem os un m todo elim inar con un
parm etro que alm acene el nm ero de telfono a elim inar y que devuelva un valor
true si la operacin se realiza con xito, o false en caso contrario.
El proceso seguido por el m todo elim inar es leer registros del fichero, em pe
zando por el registro cero, y com probar por cada uno de ellos si el telfono coin
cide con el valor pasado com o argum ento (este proceso recibe el nom bre de
bsqueda secuencial). Si existe un registro con el nm ero de telfono buscado, no
se borra fsicam ente del fichero, sino que se m arca el registro poniendo un cero
com o nm ero de telfono. E sta form a de proceder deja libertad al usuario de la
clase C ListaTfnos para elim inar d e una sola vez todos los registros m arcados al
finalizar su aplicacin, lo que redunda en velocidad de ejecucin, para restaurar
un registro m arcado para elim inar, para crear un histrico, etc.
p o r el nom bre del propietario de ese telfono, aunque tam bin podra realizarse la
bsqueda p o r la direccin. El m todo b u sca r que se expone a continuacin per
m ite realizar la bsqueda por cualquier subcadena perteneciente al nom bre. Para
ello utiliza dos parm etros: la subcadena a buscar y a partir de qu registro del fi
chero se desea buscar. Si la bsqueda term ina con xito, el m todo devuelve el
nm ero del registro correspondiente; en otro caso devuelve el valor -1.
Se observa que el m todo buscar, al igual que el m todo elim inar, realiza una
bsqueda secuencial desde el registro p o s, com probando si el nom bre de alguno
de ellos contiene la subcadena str. L gicam ente, al realizar una bsqueda secuen
cial, el resultado ser el nm ero del p rim er registro que contenga en su nom bre la
subcadena pasada com o argum ento; pero tam bin es evidente que es posible con
tinuar la bsqueda a partir del siguiente registro, invocando de nuevo al m todo
buscar, pasando com o argum entos la m ism a subcadena y el nm ero de registro
siguiente al devuelto en el proceso de bsqueda anterior.
un nuevo co nstructor con un parm etro de tipo F ile (el otro constructor lo elim i
nam os para no com plicar la clase, pero lo podam os h aber conservado).
import j a v a . i o . * ;
//////////////////////////////////////////////////////////////////
// A p l i c a c i n para t r a b a j a r c o n un f i c h e r o accedido aleatoriamente
//
public c la ss Test
I
// D e f i n i r un a r e f e r e n c i a a l f l u j o e s t n d a r de s a l i d a : flujoS
s t a t ic PrintStream f lu j o S = System.out;
s a no s
publi c s t a t ic i nt m en ()
i1
// .
I
publi c s t a t i c vo id m a i n ( S t r i n g [ ] args)
(
i n t o p c i n = 0 , p o s = - 1 ;
S t r in g cadenabuscar = n u il;
S t r i n g n o mbr e , d i r e c c i n :
long t e l f o n o :
boolean e li m i n a d o = f a l s e ;
boolean m o d if ic a d o = f a l s e ;
b o o le a n 1 i s t a M o d i f i cada = f a l s e ;
try
I
// C r e a r un o b j e t o l i s t a de t e l f o n o s v a c i o ( c o n 0 e l e m e n t o s )
// o c o n e l c o n t e n i d o d e l f i c h e r o l i s t a t f n o s . d a t s i e x i s t e .
468 JA V A : C U R SO D E PRO G R A M A CI N
do
o p c i n = m e n ( );
switch (opcin)
i
case 1 // b u s c a r
II .
case 2 // b u s c a r siguiente
// .
case 3 // m o d i f i c a r
// .
case 4 // a a d i r
// .
case 5 // e l i m i n a r
// . ,
case 6 // s a l i r
II .
w h i 1e ( o p c i n != 6):
I
catch ( lOException e)
I
f 1u j o S . p r i n t l n ( " E r r o r : " + e . g e t M e s s a g e ( )):
int op:
do
o p = Leer . d a t o l n t ) ;
E legida una opcin del m en presentado, una sentencia sw itch perm itir eje
cutar el cdigo que dar solucin a la operacin seleccionada. Las opciones Bus
car, B uscar siguiente. A a d ir y E lim inar no han variado respecto a la versin de
las m ism as presentada en el apartado S eriar objetos que referencian a objetos"
expuesto anteriorm ente en este m ism o captulo, a excepcin de que cuando se
m uestra la inform acin de un registro, ahora tam bin se m uestra el nm ero del
m ismo, y de que al salir de la aplicacin, los cam bios debidos a A a d ir o Elim inar
ya han realizados sobre el fichero (ahora se trabaja directam ente sobre el fichero).
El cdigo com pleto lo puede ver en el C D -R O M que acom paa al libro.
M odificar un registro
Una operacin im portante en el trabajo con ficheros que se puede realizar de for
ma rpida y fcil cuando se perm ite el acceso aleatorio al m ism o es m odificar al
guna parte concreta de la inform acin alm acenada en l. En nuestro caso, el
objetivo es m odificar un registro. Para ello vam os a aadir a la clase aplicacin,
un m todo esttico denom inado m odificar con un parm etro que identifique el
nm ero de registro del fichero que se desea m odificar. Si durante la ejecucin no
sabem os con exactitud el nm ero del registro que se desea m odificar, podem os
utilizar las opciones B uscar y B uscar siguiente para obtenerlo.
Una vez realizadas las m odificaciones, si se eligi salir guardando los cam
bios efectuados, el m todo enviar al objeto C ListaTfnos el m ensaje poner-
ValorEn pasando com o argum ento el nm ero de registro que se est
m odificando y el objeto C Persona que aporta los nuevos atributos; el resulta
do es que se sobreescribe en el fichero el registro especificado.
470 JA V A : C U R S O D E P R O G R A M A C I N
// M o d i f i c a r el registro
do
[
f l u jo S. pr i n t ( " \ n \n " )
f l u j o S . p r i n t l n C M o d i f i c a r el d a t o : " ) ;
f l u j o S . p r i n t l n C l . N o m b re");
f lu j oS . p r i n t l n ( " 2 . D i r e c c i n " ) ;
f l u j o S . p r i n t l n "3. T e l f o n o " ) ;
f lu j oS . p r i n t l n ( " 4 . Sal i r y s a l v a r los camb i o s " ) :
f lu j oS . p r i n t l n ( " 5 . S a l i r sin s a l v a r los c a m b i o s " ) ;
f l u j o S . p r i n t l n ( );
f l u j oS .p ri n t ( " O p c i n : ");
op = L e e r , d a t o ! n t ( ):
switch( op )
I
case 1: // m o d i f i c a r n o m b r e
flujoS.print"nombre: ");
n o m br e = L e e r . d a t o ):
obj.asignarNombrenombre):
break;
case 2: // m o d i f i c a r d i r e c c i n
f l u j o S . p r i n t ( " d i r e c c i n : ");
direccin - Leer.dato):
obj.asignarDi reccindi r e c c i n ) ;
break;
c a s e 3: // m o d i f i c a r t e l f o n o
flu joS.print"tel fono: );
t e l f o n o = L e e r . d a t o L o n g );
o b j .a sig n a rT e l fo n o te l fo n o ):
break;
case 4: // g u a r d a r los c a m b i o s
break;
case 5: // s a l i r sin g u a r d a r los c a m b i o s
break;
while op != 4 && op !- 5 ) ;
i t (op = = 4)
C A PTU LO 12: TRA BA JA R CON FICHEROS 4 7 1
1istatfnos.ponerValorEnnreg. obj):
return true:
I
el se
return false;
:
Actualizar el fichero
Los datos del fichero con el que estam os trabajando pueden verse alterados por
tres procesos diferentes: m odificar, a a d ir o elim inar un registro. En el caso de
m odificar o a adir un registro los cam bios son realizados directam ente sobre el
fichero. Pero en el caso de elim inar un registro, ste sim plem ente es m arcado con
un nm ero de telfono 0 para su posterior elim inacin, si se cree conveniente. En
nuestro caso, vam os a escribir en la clase aplicacin un m todo a ctualizar que se
invoque cuando el usuario de la aplicacin seleccione la opcin Salir, con el o b
jeto de actualizar el fichero, elim inando fsicam ente los registros m arcados.
c a s e 6: // s a l i r
// g u a r d a r 1 i s t a
i f (elim inado) a c t u a l i z a r ( f i c h e r o ) :
1 i s t a t f n o s = n u l 1;
i n t n r e g s - 1 i s t a t f n o s . 1 o n g i t u d f );
// C o p i a r en e l f i c h e r o t e m p o r a l t o d o s l o s r e g i s t r o s d e l
// f i c h e r o a c t u a l q u e en s u campo t e l f o n o no t e n g a n un 0
CPersona o b j ;
f o r ( i n t re g _ i = 0: re g _ i < n r e g s : r e g _ i + + )
I
o bj = 1 i s t a t f n o s . v a l o r E n ( r e g _ i ):
i f ( o b j , o b t e n e r T e l f o n o ( ) != 0)
f t e m p . a a d i r ( o b j );
472 JA V A : C U R SO DE PRO G R A M A CI N
1 i s t a t f n o s . c e r r a r ( );
f t e m p . c e r r a r );
f A c t u a l . d e l e t e ( );
i f ( ! f i c h e r o T e m p . r e n a m e T o ( f A c t u a l))
t h r o w new l O E x c e p t i o n t " n o s e r e n o m b r e l fichero");
II C r e a r un f l u j o h a c i a l a i m p r e s o r a
F i l e W r i t e r f l u j o S = new F i 1e W r i t e r ( " L P T l " ) :
f l u j o S . w r i t e t " E s t a l i n e a s e e s c r i b e en l a i m p r e s o r a \ r \ n " );
f l u j o S . w r i t e ( " \ r \ n " ) ; // s a l t a r una l i n e a
L o n g n - new L o n g t 1 2 3 4 5 6 7 8 9 ) :
flujoS.w ritet"Valor: " + n.toStringt) + "\r\n ");
f l u j o S . w r i t e t " \ f ); // s a l t a r a l a p g i n a s i g u i e n t e
f 1u j o S . c l o s e t ): II c e r r a r e l f l u j o
El flujo creado es de la clase F ile W rite r, pero se podra haber creado de otra
clase que perm ita definir flujos de salida, com o F ile O u tp u tS tre a m , D a ta O u t-
p u tS tre a m , R a n d o m A c c e ssF ile , etc. Se puede observar que para obtener datos
im presos legibles se envan cadenas de caracteres a la im presora, ya que se trata
de un dispositivo A SC II. En general podem os enviar datos de tipo c h a r o byte.
c a s e 6 : // i m p r i m i r
i m p r i m i r L i s t a T f n o s t );
break:
c a s e 7: // s a l i r
II ...
CA PTU LO 12: TRA BA JA R C O N FICHEROS 4 7 3
p u b l i c s t a t i c v o i d i m p r i m r L i s t a l f n o s ) th rows IOException
1
// C r e a r un f l u j o h a c i a l a i m p r e s o r a
F i l e W r i t e r f l u j o S = new F i l e W r i t e r ( " L P T 1 " );
String c r l f = \ r \ n " ; // c a m b i a r a l a s i g u i e n t e l i n e a
S t r i n g f f = \ f ; // s a l t a r a l a s i g u i e n t e p g i n a
Integer i; // r e f e r e n c i a a un o b j e t o Integer
L on g 1; // r e f e r e n c i a a un o b j e t o Long
i n t n r e g s = 1 i s t a t f n o s . 1 o n g i t u d ( ) ; // n mero de r e g i s t r o s
EJERCICIOS RESUELTOS
1. E scribir una clase aplicacin denom inada C opiarF ichero que perm ita copiar el
contenido de un fichero en otro. La aplicacin ser invocada de la form a siguien
te:
Este ejem plo utilizar la clase F ile para asegurarse de que el fichero fuente existe
y no est protegido contra lectura. Tam bin utilizar esta clase para asegurarse de
que el fichero destino existe y no est protegido contra escritura, o bien se trata de
un directorio no protegido contra escritura, destino del fichero.
474 JA V A : C U R S O D E P R O G R A M A C I N
Para leer los bytes del fichero fuente y escribirlos en el destino, este ejem plo utili
zar las clases F ile ln p u tS tr e a m y F ile O u tp u tS tre a m , respectivam ente.
Este m todo, bsicam ente chequea la existencia y perm isos d e los ficheros fuente
y destino y copia el fichero origen en el destino; si el fichero destino existe pre
gunta si se desea sobreescribir. E n el caso de que ocurra algn error, este m todo
lanzar una excepcin del tipo EC opiarF ichero indicando lo ocurrido. Finalm en
te, utilizar un bloque fin a lly para cerrar los flujos abiertos.
import j a v a . i o . * :
// D e f i n i c i o n e s de v a r i a b l e s , r e f e r e n c i a s y o b j e t o s
F i l e f i c h F u e n t e = new F i 1e ( f u e n t e );
F i l e f i c h D e s t i n o = new F i 1e ( d e s t i n o ) ;
F ile ln p u tS tre a m fFuente = n u il:
FileOutputStream fD e stin o = n u il;
byte[] buffer:
in t nbytes:
try
I
// A s e g u r a r s e de que " f u e n t e " e s un f i c h e r o , e x i s t e
// y s e p u e d e l e e r .
i f ( f i c h F u e n t e . e x i s t s t ) || ! f i c h F u e n t e . i s F i l e ( ))
t h r o w new E C o p i a r F i c h e r o i " N o e x i s t e e l f i c h e r o + f u e n t e ) :
i f ( ! f i c h F u e n t e . c a n R e a d ( ))
t h r o w new E C o p i a r F i c h e r o ( " E l f i c h e r o + f u e n t e +
no s e puede l e e r " ) :
II S i " d e s t i n o " e x i s t e , a s e g u r a r s e de q u e e s un f i c h e r o que
// s e p u e d e e s c r i b i r y p r e g u n t a r s i s e q u i e r e s o b r e e s c r i b i r .
C A PTU LO 12: TRA BA JA R CON FICHEROS 4 7 5
if ( f i c h D e s t i n o . e x i s t s ( )) // e x i s t e el destino?
if ( f i c h D e s t i n o . i s F i 1e ( )) II e s un f i c h e r o ?
I
if ( ! f i c h D e s t i n o . c a n W r i t e ( ))
t h r o w new E C o p i a r F i c h e r o t " N o s e pu ede e s c r i b i r en +
"el fiche ro " + d e s t in o ) ;
// I n d i c a r que e l f i c h e r o e x i s t e y p r e g u n t a r s i s e d e s e a
// s o b r e e s c r i b i r .
System .out.p rin tt"El fichero " + destino + " existe. " +
"Desea s o b r e e s c r ib i r l o ? (s/n ): ");
// L e e r l a r e s p u e s t a
c h a r r e s p = ( c h a r ) S y s t e m . i n . r e a d t ):
S y s t e m , i n . s k i p( S y s t e m , i n . a v a i l a b l e O ) ;
i f ( r e s p = = n ' || r e s p N )
t h r o w new E C o p i a r F i c h e r o t " C o p i a c a n c e l a d a " ) ;
1
el se
t h r o w new E C o p i a r F i c h e r o ( d e s t i no + " no e s un f i c h e r o " ) ;
I
else // s i " d e s t i n o " no e x i s t e v e r i f i c a r que e l directorio
// p a d r e e x i s t e y no e s t protegido contra escritura
I
F ile dirPadre = d ire c t o rio P a d re t fic h D e st in o );
if ( ! d i r P a d r e . e x i s t s ( ))
t h r o w new E C o p i a r F i c h e r o t " E l d i r e c t o r i o " + d e s t i n o +
" no e x i s t e " ) :
i f ( ! d i r P a d r e .c a n W r i t e ( ))
t h r o w new E C o p i a r F i c h e r o ( " N o s e p u e d e e s c r i b i r en e l " +
"d ire c to rio " + destino):
// P a r a r e a l i z a r l a c o p i a , a b r i r un f l u j o d e e n t r a d a d e s d e
// e l f i c h e r o f u e n t e y o t r o de s a l i d a h a c i a e l d e s t i n o .
f F u e n t e = new F i l e l n p u t S t r e a m ( f i c h F u e n t e ) ;
f D e s t i n o = new F i l e O u t p u t S t r e a m ( f i c h D e s t i n o ) ;
b u f f e r = new b y t e [ 1 0 2 4 ] :
// C o p i a r el fichero f u e n t e en e l destino
w hile (true)
I
nbytes = fF u e n t e .re a d (b u ffe r);
i f ( n b y t e s = = - 1 ) b r e a k : // s e l l e g al final del fichero
f D e s t i n o . w r i t e t b u f f e r . 0. n b y t e s ) :
// C e r r a r c u a l q u i e r f l u j o que e s t a b i e r t o
f i n a 11 y
476 JA VA : C U R SO DE PROGRAM A CIN
try
[
if ( f F u e n t e != n u i l ) f F u e n t e . c l o s e ):
if ( f D e s t i n o ! = n u i l ) f D e s t i n o . e l o s e ( );
I
catchfIOException e)
I
System .out.p r i n t n < " E r r o r : + e .t o S t r in g ());
// F i l e . g e t P a r e n t d e v u e lve n u i l s i el f i c h e r o se e s p e c i f i c a sin
// un d i r e c t o r i o . El m t od o s i g u i e n t e t r a t a e s t e caso.
S t r i n g n o m b r e D i r = f . g e t P a r e n t ( ):
i f ( n o m b r e D i r = = n u l 1)
// El m t o d o g e t P r o p e r t y c o n e l p a r m e t r o " u s e r . d i r d e v u e l v e
// e l d i r e c t o r i o a c t u a l de t r a b a j o ,
r e t u r n new F i 1e ( S y s t e m . g e t P r o p e r t y ( " u s e r . d i r " ) ) ;
else
// D e v o l v e r e l d i r e c t o r i o p a d r e d e l f i c h e r o
r e t u r n new F i 1 e ( n o m b r e D i r );
// m a i n d e b e r e c i b i r d o s p a r m e t r o s : e l f i c h e r o f u e n t e y
// e l d e s t i n o ,
i f ( a r g s . l e n g t h ! = 2)
S y s t e m . e r r . p r i n t n ( " S i n t a x i s : java C o p ia rF ich ero " +
" < f ic h e r o fuente> < f ic h e r o d e s t i n o s " ) :
else
I
ry
catch(IOException e)
// S i s e p r o d u c e un e r r o r d u r a n t e l a c o p i a , se lanzar
// e l s i g u i e n t e t i p o de e x c e p c i n :
class ECopiarFichero extends lOException
I
public E C o p i a r F i c h e r o ( S t r i n g mensaje)
(
s u p e r ( m e n s a j e );
2. Q uerem os escribir una aplicacin denom inada G rep que perm ita buscar palabras
en uno o m s ficheros de texto. C om o resultado se visualizar, por cada uno de
los ficheros, su nom bre, el nm ero de lnea y el contenido de la m ism a para cada
una de las lneas del fichero que contenga la palabra buscada.
a) B uscarC adena para buscar una cadena de caracteres dentro de otra. El prototi
po de este m todo ser:
c) m a in para que utilizando los m todos anteriores perm ita buscar una palabra en
uno o m s ficheros.
Observe que los datos obtenidos del fichero fuente son filtrados dos veces para
poder llegar a utilizar el m todo re a d L in e de B u ffe red R ea d er. Recuerde que este
m todo perm ite leer lneas de texto. C oncretam ente lo que se ha hecho ha sido:
478 JA VA : C U R SO D E PROGRAM A CIN
import j a v a . i o . * ;
ciass Grep 9 H H H H H H H H H H 1 IH 9
i
public static boolean B u s c a r C a d e n a ( S t r i n g ca denal. S t r i n g cadena2)
I
// c a d e n a 2 e s t c o n t e n i d a en c a d e n a l ?
i f ( c a d e n a l.in d e x O f( cadena2) > -1)
return true; // s i
el se
r e t u r n f a l s e ; // no
try
I
II A s e g u r a r s e de q u e e l f i c h e r o , e x i s t e y s e p u e d e leer
i f ( f i c h F u e n t e . e x i s t s t ) || ! f i c h F u e n t e . i s F i 1e ( ) )
I
System .err.println("N o existe el fichero + nom brefich);
return;
I
if ( ! f i c h F u e n t e . c a n R e a d f ))
I
S y s t e m . e r r . p r i n t l n C E l f ic h e r o * + nombrefich +
" no s e p u e d e l e e r );
return;
// A b r i r un f l u j o de e n t r a d a d e s d e e l f i c h e r o f u e n t e
F i l e l n p u t S t r e a m f i s = new F i l e l n p u t S t r e a m ( f i c h F u e n t e ) ;
I n p u t S t r e a m R e a d e r i s r = new I n p u t S t r e a m R e a d e r ( f i s ) ;
f l u j o E - new B u f f e r e d R e a d e r ! i s r ) ;
II B u s c a r c a d e n a en e l fichero fuente
S t r i ng 1 i n e a :
i n t n r o L i n e a = 0;
w hile ((linea = f 1u j o E . r e a d L i n e ( )) != n u il )
CA PTU LO 12: TR A B A JA R CON FIC H ER O S 4 7 9
// S i s e a l c a n z e l f i n a l d e l f i c h e r o ,
// r e a d L i n e d e v u e l v e n u i l
n r o L i n e a + + ; // c o n t a d o r de l n e a s
i f tB uscarCad enat1 i n e a . cadena))
Sy ste m .out.p rin tln tn o m b refich + " " + nroLinea + " +
1 i nea );
catchIOException e)
I
System .out.p r i n t l n ( " E r r o r : " + e.getM essaget));
I
finally
I
// C e r r a r e l flujo
try
I
if (flujoE != n u il ) f l u j o E . c l o s e ( );
1
c a t c h I O E x c e p t i o n e)
1
S y ste m .o u t.p r i n t n ( " E r r o r : " + e . t o S t r i n g ));
if ( a r g s . l e n g t h < 2)
S y s t e m . e r r . p r i n t l n ( " S i n t a x i s : j a v a Grep " + "<cad e n a> " +
" < f i c h e r o 1> < f i c h e r o 2 > . . . " ) ;
el se
1
f o r ( i n t i = 1; i < a r g s . l e n g t h : i + + )
// B u s c a r a r g s C O ] en a r g s [ i ]
B u s c a r E n F i c h ( a r g s [ i ]. a r g s C O ] ) :
3. R ealizar un program a que perm ita crear un fichero nuevo, abrir uno existente,
aadir, m odificar o elim inar registros, y visualizar el contenido del fichero. El
nom bre del fichero ser introducido a travs del teclado. C ada registro del fichero
480 JA V A : C U R S O D E P R O G R A M A C I N
estar form ado p o r los datos referencia y precio. A s m ism o, para que el usuario
pueda elegir cualquiera de las operaciones enunciadas, el program a visualizar en
pantalla un m en sim ilar al siguiente:
1. F i c h e r o nuevo
2. Ab ri r f i ch ero
3. Aadi r r e g i s t r o
4. M odificar re g istro
5. Elim inar regi stro
6. V isu alizar registros
7. Salir
Opcin:
No se perm itir crear un F ichero nuevo cuando exista, ni A b rir un fic h e ro que
no exista. C uando se intente A b rir un fic h e ro que no exista, se ofrecer la posibi
lidad de m ostrar un listado del directorio actual. F inalm ente, la opcin Visualizar
registros perm itir m ostrar aquellos registros cuya referencia sea una especifica
da, o bien contenga una subcadena especificada.
Se deber realizar al m enos un m todo para cada una de las opciones, excepto
para Salir.
A partir de un anlisis del enunciado se deduce que, adem s del objeto aplica
cin (objeto de una clase que denom inarem os Test), potencialm ente existen dos
clases de objetos ms: una que represente al fichero y otra que represente a los re
gistros del fichero.
E scribirem os entonces una clase C Registro p ara m anipular cada uno de los
registros de un fichero y otra C B aseD eD atos con una interfaz pblica que perm ita
realizar las operaciones habituales de trabajo sobre un fichero.
Un constructor sin parm etros y otro con parm etros para poder crear objetos
con unos atributos determ inados.
Los m todos obtenerR eferencia y obtenerP recio para obtener los valores de
los cam pos de un registro (atributos del objeto CRegistro).
Los m todos asignarR eferencia y asignarP recio p ara asignar nuevos valores
a los cam pos de un registro (atributos del objeto CRegistro).
/////////////////////////////////////////////////////////////////
// D e f i n i c i n de l a clase CRegistro
//
public class CRegistro
I
// A t r i b u t o s
private S trin g referencia:
p riv a t e double p re cio :
II M t o d o s
p u b l i c C R e g i s t r o t ) {)
public C R e gistro tStrin g ref. double pre)
I
referen cia - ref:
p r e c i o = pre:
referencia = ref:
public S trin g o b t e n e r R e f e r e n c i a ()
I
return referencia:
p u b lic double o b t e n e r P r e c io t )
I
return precio:
dotarem os a esta clase de cuatro atributos, un objeto F ile que encapsule el nom bre
del fichero actual de trabajo, un flujo vinculado con el fichero, el nm ero de re
gistros del fichero y la longitud estim ada para cada registro; y de los siguientes
m todos:
Un constructor que adm ita com o argum ento un objeto F ile que proporcione el
nom bre de la base de datos.
El m todo elim inar para m arcar un registro del fichero com o elim inado.
Y el m todo actualizar para elim inar fsicam ente del fichero los registros
m arcados p o r el m todo elim inar.
/////////////////////////////////////////////////////////////////
// D e f i n i c i n de l a c l a s e CBaseDeDatos.
//
import j a v a . i o . * ;
p u b l i c c l a s s CBaseDeDatos
I
// A t r i b u t o s
p rivate F ile ficheroActua 1; // o b j e t o F i l e ( n o mb r e d e l f i c h e r o )
p r i v a t e R a n d o m A c c e s s F i 1e f e s ; // f l u j o h a c i a / d e s d e el f i c h e r o
private in t nregs; // n m e r o de r e g i s t r o s
p r i v a t e i n t tamaoReg = 50; // t a ma o d e l r e g i s t r o en b y t e s
// M t o d o s
pu b lic CBaseDeDatos( F i l e fichero) th rows IOException
I
// E x i s t e e l f i c h e r o ?
i f ( f i c h e r o . e x i s t s ( ) && ! f i c h e r o . i s F i 1e ( ))
t h r o w new I O E x c e p t i o n ( f i c h e r o . g e t N a m e ( ) + " no es un f i c h e r o );
II A s i g n a r v a l o r e s a l o s a t r i b u t o s
ficheroActual = fichero:
f e s = new R a n d o m A c c e s s F i 1e ( f i c h e r o , " r w " ) :
C A PTU LO 12: T R A B A JA R C O N FIC H ER O S 4 8 3
// El l t i m o r e g i s t r o no o c u p a e l ta mao e s p e c i f i c a d o .
// P o r e s t a c a u s a u t i l i z a m o s c e i l , p a r a r e d o n d e a r p o r e n c i m a ,
nregs = ( in t ) M a t h . c e i1 ( ( d o u b l e ) f e s . l e n g t h ) / (double)tamaoReg):
S trin g referencia:
double p re cio :
484 JA V A : C U R SO DE PROGRAM A CIN
// L e e r l a i n f o r m a c i n c o r r e s p o n d i e n t e a l registro i.
r e f e r e n c i a = f e s . r e a d U T F );
p r e c i o = f e s . r e a d D o u b l e ( );
// D e v o l v e r e l o b j e t o C R e g i s t r o c o r r e s p o n d i e n t e ,
r e t u r n new C R e g i s t r o ( r e f e r e n c i a . p r e c i o ) ;
I
el s e
I
S y s t e m . o u t . p r i n t l n( " n m e r o de r e g i s t r o fuera de l i m i t e s " ) ;
r e t u r n n u l 1;
// G r a b a r l o
ponerValorEn! re g _ i . obj );
return true:
return false:
// C o p i a r en e l f i c h e r o t e m p o r a l t o d o s l o s r e g i s t r o s del
// f i c h e r o a c t u a l que no e s t n m a r c a d o s p a r a " b o r r a r "
CRegi s t r o o b j ;
f o r ( i n t r e g _ i = 0; r e g _ i < n r e g s ; r e g _ i + + )
I
o bj = v a l o r E n ! r e g _ i );
i f (obj.obtenerReferencia() .com pareTo!"borrar") != 0)
f t e m p . a a d i r ( o b j );
I
// B o r r a r e l f i c h e r o a c t u a l y r e n o m b r a r e l t e m p o r a l c o n el
// no mb r e d e l a c t u a l . P a r a h a c e r e s t a s o p e r a c i o n e s l o s f i c h e r o s
// no p u eden e s t a r en u s o .
t h i s . c e r r a r t ): // c e r r a r el fic h e r o actual
f t e m p . c e r r a r ! ); // c e r r a r el f i c h e r o tem poral
f i c h e r o A c t u a l . d e l e t e ( ) : II b o r r a r el fic h e ro actual
i f ( ! f i c h e r o T e m p . r e n a m e T o ! f i c h e r o A c t u a l ) ) // r e n o m b r a r
t h r o w new I O E x c e p t i o n ! " n o s e a c t u a l i z el f i c h e r o " ) :
V olviendo al enunciado del program a, ste tiene que perm itir a travs de un
m en, crear un fichero nuevo, abrir un fichero existente, aadir, m odificar o eli
m inar un registro del fichero y visualizar un conjunto determ inado de registros. El
m todo m en presentar todas estas opciones en pantalla y devolver com o re
sultado un entero { 1 , 2 , 3 , 4 , 5 , 6 7 ) correspondiente a la opcin elegida por el
usuario. Este m en ju n to con el esqueleto de la clase aplicacin se m uestra a con
tinuacin:
import j a v a . i o . * :
;/////////////////////////////////////////////////////////////////
// A p l i c a c i n p a r a t r a b a j a r c o n un f i c h e r o a c c e d i d o a l e a t o r i a m e n t e
// U t i l i z a l a c l a s e L e e r p a r a l e e r d e l a e n t r a d a e s t n d a r c a d e n a s
// y d a t o s de t i p o s p r i m i t i v o s ,
p u b lic c l a s s Test
486 JA V A : C U R S O D E P R O G R A M A C I N
// D e f i n i r una r e f e r e n c i a a l f l u j o e s t n d a r d e s a l i d a : flujoS
s t a t i c PrintStream f lu j o S = System.out:
s t a t i c CBaseDeDatos a r t c u l o s ;
s t a t i c boolean f i c h e r o A b i e r t o = f a l s e ;
// ...
// ...
II...
// ...
II...
op = L e e r . d a t o I n t ( );
i f ( o p < 1 || op > 7)
f l u j o S . p r i rt ( " O p c i n no v l i d a . Elija otra: ");
1
w h i 1e ( op < 1 || op > 7 ) ;
whi l e ( o p c i n != 7 );
488 JA V A : C U R S O D E P R O G R A M A C I N
catch (IOException e)
I
flujoS.println"Error: " + e.ge tM essage()):
Se puede observar que la clase aplicacin T est define tres atributos: un flujo
hacia la salida estndar, una referencia a la base de datos (fichero) con la que se
va a trabajar y una variable fich ero A b ierto de tipo b o o lean para saber en todo
m om ento si hay o no un fichero abierto (su valor ser tr u e si el fichero est
abierto y false en caso contrario). E sta variable ser utilizada para no crear o abrir
un fichero cuando ya haya uno abierto, y para no intentar aadir, m odificar, eli
m inar o visualizar registros cuando no haya un fichero abierto.
C ada una de las opciones del m en, excepto la opcin Salir, se resuelve eje
cutando un m todo de los expuestos a continuacin.
Nuevo fichero
El m todo nuevoF ich tiene com o m isin crear un fichero vaco cuyo nom bre es
pecificarem os a travs del teclado, slo si dicho fichero no existe; si existe, se so
licitar un nuevo nom bre de fichero. F inalm ente, a partir del fichero especificado
crear un o bjeto artculos de la clase C B aseD eD atos cu y a interfaz nos permitir
operar sobre ese fichero.
f i c h e r o A b i ert.o = t r u e :
A brir fichero
El m todo abrirFich tiene com o m isin abrir un fichero existente cuyo nom bre
especificarem os a travs el teclado. Si el nom bre especificado para el fichero no
se localiza en el directorio actual de trabajo, se dar la posibilidad de visualizar el
contenido de este directorio y de introducir un nuevo nom bre. F inalm ente, a partir
del fichero especificado crear un objeto artculos de la clase C B a s e D e D a t o s c u
ya interfaz nos perm itir operar sobre ese fichero.
F i l e obj = n u i l :
char resp:
while ( ! o b jF ic h e r o .e x i s t s ())
!
f l u j o S . p r i n t l n ( " E s t e f i c h e r o no e x i s t e . " ) ;
f l u j o S . p r i n t t " D e s e a v e r l a l i s t a de f i c h e r o s ? s / n : " ) ;
resp = L e e r . c a r c t e r t );
L e e r . 1 i m p i a r t ):
i f ( resp == n ') return :
// O b t e n e r un l i s t a d o d e l d i r e c t o r i o a c t u a l de t r a b a j o
o b j = new F i 1e ( S y s t e m . g e t P r o p e r t y ( " u s e r . d i r " ) ) :
S t r i n g [] nombresDir = o b j . l i s t O ;
f o r ( i n t i = 0: i < n o m b r e s D i r . 1 e n g t h ; i + + )
flu jo S .p r in t (n o m b r e s D ir [ i ] + ". ");
flu joS.p rintln("\n");
o b j F i c h e r o = new F i 1e ( L e e r . d a t o ( ) ) :
)
a r t c u l o s = new C B a s e D e D a t o s ( o b j F i c h e r o ):
ficheroAbierto = true;
El m todo aadi r R e g tiene com o m isin aadir un registro al final del fichero. Pa
ra ello, solicitar los datos a travs del teclado y enviar al objeto artculos el
490 JA V A : C U R S O D E P R O G R A M A C I N
flujoS.printl"Referencia: ");
referencia = Leer.dato!):
flu joS.printl"Pre cio: ");
p r e c i o = L e e r . d a t o D o u b l e ! );
artculos.aadir(new C R e g istro (re fe re n cia . precio)):
El m todo m odificarR eg tiene com o finalidad perm itir m odificar cualquier regis
tro del fichero actual con el que estam os trabajando. Para ello, solicitar el nm e
ro de registro a m odificar, lo leer, visualizar los cam pos correspondientes, y
presentar un m en que perm ita m odificar cualquiera de esos cam pos:
M o d i f i c a r el dato:
1. R e f e r e n c i a
2. P r e c i o
3. S a l i r y s a l v a r l o s cambios
4. S a l i r s i n s a l v a r l o s cambios
Opcin:
// S o l i c i t a r e l n me r o de r e g i s t r o a m o d i f i c a r
f l u j o S . p r i n t ( " N m e r o de r e g i s t r o e n t r e 0 y +
( a r t c u l o s . l o n g i t u d ! ) - 1) + " : " ) :
n r e g = L e e r . d a t o l n t ! );
// L e e r e l r e g i s t r o
C R e g i s t r o o b j = a r t i c u l o s . v a l o r E n ! n r e g ):
i f ( o bj = nul1 ) return:
CA PTU LO 12: TRA B A JA R C O N FIC H ER O S 4 9 1
// V i s u a l i z a r l o
f l u j o S . p r i n t l n ( o b j .o b t e n e r R e f e r e n c i a ( ) ) ;
f 1u j o S . p r i n t l n ( o b j .o b t e n e r P r e c i o ( ));
// M o d i f i c a r e l registro
do
(
f l u j o S . p r i n t ( " \ n \ n " );
f l u j o S . p r i n t l n C ' M o d i f i c a r el d a t o : " ) :
f l u j o S . p r i n t l n ( " l . R eferen cia''):
flu jo S .p rin tln C '2 . Precio"):
f 1 u j o S . p r i n t l n ( " 3 . S a l i r y s a l v a r l o s c a m b i o s );
f 1u j o S . p r i n t l n ( " 4 . S a l i r s i n s a l v a r l o s c a m b i o s " ) :
f l u j o S . p r i n t l n );
flu joS.p rintC Opcin: " ) ;
op = L e e r . d a t o I n t ( ) ;
switch op )
I
c a s e 1: // m o d i f i c a r r e f e r e n c i a
f 1u j o S . p r i n t ( " R e f e r e n c i a : ");
referencia = Lee r.d atoO ;
o b j . a s i g n a r R e f e r e n c i a ( r e f e r e n c i a );
break;
c a s e 2: II m o d i f i c a r p r e c i o
flujoS.print("Precio: ");
p r e c i o = L e e r . d a t o D o u b l e );
obj.asignarPrecio(precio);
break;
c a s e 3: // g u a r d a r l o s c a m b i o s
break;
c a s e 4 : II s a l i r s i n g u a r d a r l o s c a m b i o s
break;
w h i 1e ( op ! = 3 && op != 4 );
El m todo elim inarR eg perm ite m arcar un registro del fichero com o borrado. Para
m arcar un registro se enviar al objeto artculos el m ensaje elim inar (se ejecuta el
m todo elim inar de su clase) pasando com o argum ento su referencia, la cual se
solicitar a travs del teclado. E ste m todo devolver el m ism o valor retom ado
por el m todo elim inar, tr u e si la operacin se realiza satisfactoriam ente y false
en caso contrario.
492 J A V A : C U R S O D E P R O G R A M A C I N
do
I
nreg = a r t c u lo s . b u s c a r t s t r . nreg+1);
i f (nreg > -1)
I
obj = a r t c u l o s . v a l o r E n ( n r e g ) :
f lu j o S . p r in t ln ( "R e g is t r o : " + nreg);
f 1u j o S . p r i n t l n ( o b j . o b t e n e r R e f e r e n c i a ( ) ) ;
f l u j o S . p r i n t l n ( o b j . o b t e n e r P r e c i o ( ));
f 1u j o S . p r i n t l n ( );
if (obj == n u il)
f 1u j o S . p r i n t l n ( " n o se encontr ningn registro");
EJERCICIOS PROPUESTOS
1. E scribir una aplicacin que perm ita escribir p o r la im presora un fichero de texto.
La aplicacin se ejecutar de la form a siguiente: ja v a im prim ir fich ero , donde im
p rim ir e s el nom bre de la aplicacin y fic h e ro el nom bre del fichero de texto que
se desea im prim ir.
2. R ealizar un program a que perm ita trabajar sobre un fichero que alm acena los
resultados obtenidos despus de m edir las tem peraturas en un punto geogrfico
durante un intervalo de tiem po. El fichero constar de una cabecera definida se
gn la siguiente estructura de datos:
1. F i c h e r o nuevo
2. Ab ri r f i ch ero
3. A a d i r temperatura
4. M o d if i c a r temperatura
5. V i s u a l i z a r l a t e m p e r a t u r a medi a
6. Sal i r
O pci n :
494 JA VA : C U R S O D E PRO G R A M A CI N
3. S uponga que disponem os de un fichero en disco llam ado alum nos, donde cada
registro se corresponde con los atributos de una clase com o la siguiente:
4. S uponga que disponem os en el disco dos ficheros denom inados alum nos y modi
fica cio n es. La estructura de cada uno de los registros para am bos ficheros se co
rresponde con los atributos de una clase com o la siguiente:
public c la ss CRegistro
I
// A t r i b u t o s
p r i v a t e S t r i n g n o mbr e :
p r iv a t e f l o a t nota:
// M t o d o s
// . . .
I
Suponga tam bin que am bos ficheros estn clasificados ascendentem ente por el
cam po nom bre.
R egistros q ue tam bin estn en el fichero alum nos pero que han variado en su
cam po nota.
R egistros nuevos; esto es, registros que no estn en el fichero alum nos.
R egistros que tam bin estn en el fichero alum nos y que deseam os eliminar.
Estos registros se distinguen porque su cam po nota vale -1.
Se pide realizar un program a que perm ita obtener a partir de los ficheros alumnos
y m odificaciones un tercer fichero siguiendo los criterios de actualizacin ante
riorm ente descritos. El fichero resultante term inar llam ndose alumnos.
CA PTU LO 13
F . 1. C c h a U o s / R A -M A
ESTRUCTURAS DINMICAS
La principal caracterstica de las estructuras dinm icas es la facultad que tienen
para variar su tam ao y hay m uchos problem as que requieren de este tipo de es
tructuras. E sta propiedad las distingue claram ente de las estructuras estticas fun
dam entales com o las m atrices. C uando se crea una m atriz su nm ero de elem entos
se fija en ese instante y despus no puede agrandarse o dism inuirse elem ento a
elem ento, conservando el espacio actualm ente asignado; en cam bio, cuando se
crea una estructura dinm ica eso s es posible.
C uando se trabaja con estructuras dinm icas, el com pilador asigna una canti
dad fija de m em oria para m antener la direccin del com ponente asignado dinm i
cam ente, en vez de hacer una asignacin para el com ponente en s. Esto im plica
que debe haber una clara distincin entre datos y referencias a datos, y que conse
cuentem ente se deben em plear tipos de datos cuyos valores sean referencias a
otros datos.
C uando se asigna m em oria dinm icam ente para un objeto de un tipo cualquie
ra, se devuelve una referencia a la zona de m em oria asignada. Para realizar esta
operacin disponem os en Java del operador new (vea en el captulo 4, el apartado
C rear un objeto de una clase ).
496 JA V A : C U R S O D E P R O G R A M A C I N
LISTAS LINEALES
H asta ahora hem os trabajado con m atrices que com o sabem os son colecciones de
elem entos todos del m ism o tipo, ubicados en m em oria uno a continuacin de otro;
el nm ero de elem entos es fijado en el instante de crear la m atriz. Si m s adelante,
d urante la ejecucin del program a, necesitram os m odificar su tam ao para que
contenga m s o m enos elem entos, la nica alternativa posible sera asignar un
nuevo espacio de m em oria del tam ao requerido y adem s, copiar en l los datos
q ue necesitem os conservar d e la m atriz original. La nueva m atriz pasar a ser la
m atriz actual y la m atriz origen se destruir, si ya no fuera necesaria.
Es evidente que cada vez que necesitem os aadir o elim inar un elem ento a
una coleccin de elem entos, la solucin planteada en el prrafo anterior no es la
m s idnea; seguro que estam os pensando en algn m ecanism o que nos perm ita
aadir un nico elem ento a la coleccin, o bien elim inarlo. E ste m ecanism o es
viable si en lugar de trabajar con m atrices lo hacem os con listas lineales. U na lista
lineal es una coleccin, originalm ente vaca, de elem entos u objetos de cualquier
tipo no necesariam ente consecutivos en m em oria, que durante la ejecucin del
program a puede crecer o decrecer elem ento a elem ento segn las necesidades
previstas en el m ism o.
Segn la definicin dada surge una pregunta: si los elem entos no estn conse
cutivos en m em oria cm o pasam os desde un elem ento al siguiente cuando reco
rram os la lista? La respuesta es que cada elem ento debe alm acenar inform acin de
dnde est el siguiente elem ento o el anterior, o bien am bos. E n funcin de la in
form acin que cada elem ento de la lista alm acene respecto a la localizacin de sus
antecesores y/o predecesores, las listas pueden clasificarse en: listas sim plem ente
enlazadas, listas circulares, listas doblem ente enlazadas y listas circulares doble
m ente enlazadas.
Lista lineal
Para co n struir una lista lineal, prim ero tendrem os que definir el tipo de los
elem entos que van a form ar parte de la m ism a. Por ejem plo, cada elem ento de la
lista puede definirse com o una estructura de datos con dos m iem bros: una refe
rencia al elem ento siguiente y una referencia al rea de datos. El rea de datos
puede ser de un tipo predefinido o de un tipo definido p o r el usuario. Segn esto,
el tipo de cada elem ento de una lista puede venir definido de la form a siguiente:
class CElementoLse
1
// A t r i b u t o s
// D e f i n a a q u l o s d a t o s o l a s r e f e r e n c i a s a l o s d a t o s
// . . .
C E l e m e n t o L s e s i g u i e n t e : // r e f e r e n c i a a l s i g u i e n t e e l e m e n t o
// M t o d o s
CE1ementoLse() I) II c o n s t r u c t o r sin parmetros
II...
Se puede observar que la clase C E lem entoLse definir una serie d e atributos
correspondientes a los datos que deseem os m anipular, adem s de un atributo es
pecial, denom inado siguiente, para perm itir que cada elem ento pueda referenciar a
su sucesor form ando a s una lista enlazada.
public e la ss Test
I
public static void m a in {S trin g [] args)
I
C E l e m e n t o L s e p : II r e f e r e n c i a a un e l e m e n t o
// A s i g n a r memo r i a p a r a un e l e m e n t o
p = new C E l e m e n t o L s e ! ) :
// E s t e e l e m e n t o no t i e n e un s u c e s o r
p .siguiente = n u i l ;
// O p e r a c i o n e s c u a l e s q u i e r a
// P e r m i t i r q u e s e l i b e r e l a me m o r i a o c u p a d a por el elemento p
p = nuil:
498 JA V A : C U R S O D E P R O G R A M A C I N
El valor nuil, referencia nula, perm ite crear estructuras de datos finitas. A s
m ism o, suponiendo que p hace referencia al principio de la lista, direm os que di
ch a lista est vaca si p vale nuil. Por ejem plo, despus de ejecutar las sentencias:
p = n u 11: / / l i s t a vacia
p = new C E 1 e m e n t o L s e t ) : // e l e m e n t o p
p.siguiente = n u il; // no h a y s i g u i e n t e elemento
nuil
q = new C E 1 e m e n t o L s e ( ) ; // c r e a r un n u e v o e l e m e n t o
q . s i g u i e n t e = p: // a l m a c e n a r l a l o c a l i z a c i n d e l e l e m e n t o s i g u i e n t e
p = q ; // p h a c e r e f e r e n c i a a l p r i n c i p i o de l a l i s t a
donde q es una referencia a un objeto de tipo C Elem entoLse. A hora tenem os una
lista de dos elem entos. O bserve que los elem entos nuevos se aaden al principio
de la lista.
P ara verlo con claridad analicem os las tres sentencias anteriores. Partim os de
que tenem os una lista referenciada por p con un solo elem ento. La sentencia q =
n ew C E lem entoL sef) crea un nuevo elem ento:
nuil
L a sentencia q. siguiente = p hace que el sucesor del elem ento creado sea el
anteriorm ente creado. O bserve que ahora q.siguiente y p tienen el m ism o valor;
esto es, la m ism a direccin, p o r lo tanto, referencian el m ism o elem ento:
CA PTU LO 13: ESTRU C TU R A S D IN M ICA S 4 9 9
/
nui l
/
n u il
q = q.siguiente;
Q uin es q.sig u ien te! Es el atributo siguiente del objeto referenciado por q que
contiene la direccin de m em oria donde se localiza el siguiente elem ento al refe
renciado p o r p . Si este valor se lo asignam os a q, entonces q referenciar al m ismo
elem ento que referenciaba q. siguiente. El resultado es que q referencia ahora al
siguiente elem ento com o se puede ver en la figura m ostrada a continuacin:
n u il
E sto nos da una idea de cm o avanzar elem ento a elem ento sobre una lista. Si
ejecutam os de nuevo la m ism a sentencia:
q = q.siguiente:
Operaciones bsicas
Las operaciones que podem os realizar con listas incluyen fundam entalm ente las
siguientes:
500 JA V A : C U R S O D E P R O G R A M A C I N
class CElementoLse
I
II A t r i b u t o s
in t dato:
CElementoLse s i g u i e n t e : // referencia al siguiente elemento
II M t o d o s
C E 1 e m e n to L s e () I) // c o n s t r u c t o r s i n p a r m e t r o s
CE1ementoLset i n t d ) // c o n s t r u c t o r c o n p a r m e t r o s
I
d a t o = d:
vam os a ex poner en los siguientes apartados cm o realizar cada una de las opera
ciones bsicas. O bserve que p o r sencillez vam os a trabajar con una lista de ente
ros.
Supongam os una lista lineal referenciada por p. Para insertar un elem ento al prin
cipio de la lista, prim ero se crea el elem ento y despus se reasignan las referen
cias, tal com o se indica a continuacin:
q - new C E 1 e m e n t o L s e t ):
/ /
nuil
C A PTU LO 13: ESTRU C TU R A S D IN M ICA S 5 0 i
q . d a t o = n; // a s i g n a c i n d e v a l o r e s
q . s i g u i e n t e = p: // r e a s i g n a c i n d e r e f e r e n c i a s
P = q;
Esta operacin bsica nos sugiere cm o crear una lista. Para ello, y partiendo
de una lista vaca, no tenem os m s que repetir la operacin de insertar un ele
mento al com ienzo de una lista, tantas veces com o elem entos deseem os que tenga
dicha lista. V em oslo a continuacin:
//////////////////////////////////////////////////////////////////
// C r e a r una l i s t a lineal sim plemente enlazada
//
public class Test
I
public static void main( S t r i n g [] args)
1
C E 1 e m e n t o L s e p , q : // r e f e r e n c i a s
i n t n, e o f = I n t e g e r . M I N _ V A L U E ;
// C r e a r una l i s t a de e n t e r o s
S y s t e m , o u t . p r i n t l n ( " 1n t r o d u c i r d a t o s . Finalizar c o n C t r l + Z . ):
p = n u l 1 : // 1 i s t a vacia
N o tar que el orden de los elem entos en la lista, es inverso al orden en el que
han llegado. A s m ism o, com o es ya habitual, utilizam os la clase L e e r diseada en
el captulo 5 y revisada en el 11 y 12, para leer datos desde el teclado.
502 JA V A: C U R S O DE PROGRAM A CIN
q - new C E 1 e m e n t o L s e ( ):
q . d a t o = x ; // v a l o r i n s e r t a d o
q .siguiente = r.siguiente:
r . s i g u i e n t e - q;
il
q - new C E 1 e m e n t o L s e ( ):
q.dato = r.dato: // c o p i a r m i e m b r o a m i e m b r o un o b j e t o en o t r o
q .siguiente - r.siguiente:
r . d a t o = x; // v a l o r i n s e r t a d o
r .s i gui ente = q :
1
X 1 27
1
1
i \ /
13 27 1 13 X
/ / 1 /
1
q = r . siguiente: / / q r e f e r e n c i a el elemento a b o r r a r
r.sigu ie n te = q.siguiente: II e n l a z a r l o s e l e m e n t o s a n t e r i o r
// y p o s t e r i o r a l b o r r a d o
q = nu il: // o b j e t o re f e re n c ia d o por q a la basura (b o r r a r )
O bserve que para acceder a los m iem bros de un elem ento, ste tiene que estar
referenciado por una variable. Por esta razn, lo prim ero que hem os hecho ha sido
referenciar el elem ento a borrar p o r q.
P ara borrar un elem ento referenciado por r, las operaciones a realizar son las
siguientes:
q = r. sig u ie n te :
r . d a t o = q . d a t o ; // c o p i a r m i e m b r o a m i e m b r o uri o b j e t o en o t r o
r.sig u ie n te = q.siguiente:
q = nu il; // o b j e t o r e f e r e n c i a d o p o r q a l a b a s u r a ( b o r r a r )
S upongam os que hay que realizar una operacin con todos los elem entos de una
lista, cu y o p rim er elem ento est referenciado p o r p. P or ejem plo, escribir el valor
de cada elem ento de la lista. La secuencia de operaciones sera la siguiente:
q = p : // s a l v a r l a referencia al p r i m e r e l e m e n t o de l a lista
w h i l e (q ! = n u i l )
1
System .out.print(q.dato + " ");
q = q .sig u e n te :
I
B orrar todos los elem entos de una lista equivale a enviar a la basura a cada uno de
los elem entos de la m ism a. S upongam os que querem os borrar una lista, cuyo pri
m er elem ento est referenciado por p . La secuencia de operaciones es la siguiente:
q = p: // q r e f e r e n c i a el p r i m e r e l e m e n t o de l a l i s t a
w hile ( q != n u il )
I
p = p . s i g u i e n t e : // p r e f e r e n c i a al s i g u i e n t e elemento
q = nu il: // o b j e t o r e f e r e n c i a d o p o r q a l a b a s u r a
q = p: // q h a c e r e f e r e n c i a a l m i s mo e l e m e n t o q u e p
I
O bserve que antes de borrar el elem ento referenciado por q, hacem os que p
referencie al siguiente elem ento, porque si no perderam os el resto de la lista; la
referenciada p o r q.siguiente. Y por qu perderam os la lista? Porque se pierde la
nica referencia que nos d a acceso a la m ism a. Entonces, para borrar un lista cuyo
prim er elem ento est referenciado p o r p bastara con hacer:
E videntem ente, el proceso anterior no es necesario. Para elim inar una lista
basta con po n er a n u il la variable que hace referencia al p rim er elem ento de la
m ism a, porque esto im plica que todos los elem entos de ella queden desreferencia-
dos y sean enviados a la basura para ser recogidos por el recolector de basura.
S upongam os que querem os buscar un determ inado elem ento en una lista cuyo
prim er elem ento est referenciado p o r p . La bsqueda es secuencial y termina
cuando se encuentra el elem ento, o bien cuando se llega al final de la lista.
C A P T U L O 13: ESTR U C TU R A S DINM ICA S 5 0 5
q = p // q r e f e r e n c i a e l p r i m e r e l e m e n t o de l a lista
S y s t e m . o u t . p r i n t " d a t o a b u s c a r : " ) ; x = L e e r . d a t o l n t ):
w h i l e ( q ! = n u i l && q . d a t o ! = x )
q = q . s i g u i e n t e : // q r e f e r e n c i a al s i g u i e n t e e l e m e n t o
O bserve el orden de las expresiones que form an la condicin del bucle while.
Sabem os que en una operacin & & (A N D ), cuando una d e las expresiones es fal
sa la condicin ya es falsa, por lo que el resto de las expresiones no necesitan ser
evaluadas. De ah que cuando q valga n u il si la expresin q.dato fuera evaluada.
Java lanzara una excepcin N u llP o in te rE x c e p tio n .
La clase la denom inarem os C ListaL inealSE (G a s e Lista L ineal Sim plem ente
Enlazada). D icha clase incluir un atributo p para alm acenar de form a perm anente
una referencia al prim er elem ento de la lista, y una clase interna C E lem ento que
definir la estructura de un elem ento d e la lista, que segn hem os indicado ante
riorm ente ser as:
// M t o d o s
p r i v a t e CElemento) II // c o n s t r u c t o r
I
El constructor dar lugar a una lista vaca. El m todo aadirA lP rincipio per
m itir a adir un nuevo elem ento al principio de la lista, en nuestro caso un valor
de tipo d o u b le recibido com o parm etro por el m todo, y m ostrarTodos perm itir
visualizar p o r pantalla todos los elem entos de la lista, en nuestro caso la lista de
valores de tipo d o u b le que alm acena.
//////////////////////////////////////////////////////////////////
// Lista lineal sim plemente enlazada
//
public class CListaLinealSE
I
// p: r e f e r e n c i a a l p r i m e r e l e m e n t o d e l a lista
p r i v a t e CElemento p = n u i l ;
p u b li c C L i s t a L i n e a l S E () II // c o n s t r u c t o r
// A a d i r un e l e m e n t o al p r i n c i p i o de l a lista
p u b l i c v o i d a a d i r A l P r i n c i p i o t d o u b l e n)
I
C E l e m e n t o q = new C E l e m e n t o O :
q . d a t o = n; // a s i g n a c i n de v a l o r e s
q . s i g u i e n t e = p; // r e a s i g n a c i n de r e f e r e n c i a s
P - q:
I
//////////////////////////////////////////////////////////////////
/// // // // / / / // // / / / // // / / / // // / / / // // / / / // // / / / // // / / // / / / // // / / / /
// C r e a r una l i s t a l i n e a l s i m p l e m e n t e e n l a z a d a
//
public c la s s Test
I
public static void m a in ( S t r in g [ ] args)
I
// C r e a r una l i s t a l i n e a l vacia
CListaLinealSE Ise = new C L i s t a L i n e a l S E ( ):
// L e e r d a t o s r e a l e s y a a d i r l o s a la lista
d o u b l e n;
boolean eof = true:
S y s t e m . o u t . p r i n t l n ( " I n t r o d u c i r d a t o s . F i n a l i z a r c o n C t r l + Z . ):
System .out.pri n t ( "dato: "):
w h ile ( D o u b le . is N a N ( n = L e e r .d a t o D o u b le ( )) != eof)
I
1s e . a a d i r A l P r i n c i p i o ( n ) :
System .out.printt"dato: ");
// M o s t r a r l a l i s t a de d a t o s
System .out.pri n t l n ();
1 s e . m o s t r a r T o d o s t ):
Si en un instante determ inado necesitara borrar todos los elem entos de la lista,
bastara con escrib ir Ise = nuil.
El m todo o btener recibir com o parm etro la posicin del elem ento que se
desea obtener (la prim era posicin es la cero) y devolver com o resultado el dato
alm acenado p o r este elem ento, o bien el valor N aN si la lista est vaca o la posi
cin especificada est fuera de lm ites.
508 J A V A : C U R S O D E P R O G R A M A C I N
C E l e m e n t o q = p: // r e f e r e n c i a al p rim e r elemento
if (i > = 0 )
I
// P o s i c i o n a r s e en e l e l e m e n t o i
f o r ( i n t n = 0 ; q ! = n u i l && n < i ; n++)
q = q.siguiente;
// R e t o r n a r el dato
i f (q != n u i l ) return q.dato:
I
// n d i c e f u e r a de l i m i t e s
r e t u r n Double.NaN;
I
// M o s t r a r l a l i s t a de d a t o s
S y s t e m . o u t . p r i n t l n C );
i n t i = 0;
d o u b l e d = 1s e . o b t e n e r i ) ;
w hile ( Double.isNaN(d))
I
System .out.printd + " );
i ++;
d = 1 s e . o b t e n e r t i );
L o que hace el segm ento de cdigo m ostrado es obtener y visualizar los valo
res de los elem entos 0 , 1 ,2 ,... de la lista Ise h asta que el m todo obtener devuelva
el valor N aN , seal de que se ha llegado al final de la lista.
C A P T U L O 13: ESTR U C TU R A S D IN M ICA S 5 0 9
Sabem os que O b je ct es la superclase de todas las clases; esto es, cuando im-
plem entam os una clase y no se especifica explcitam ente su superclase, dicha cla
se est derivada de O bject. Esto significa que las dos definiciones de clase
siguientes son equivalentes:
T am bin sabem os que Java perm ite convertir im plcitam ente una referencia a
un objeto de una subclase en una referencia a su superclase directa o indirecta.
Por ejem plo, la siguiente lnea convierte una referencia a un objeto de la clase
D o u b le a una referencia a su superclase O bject. E ste ejem plo puede extenderse a
cualquier clase de la biblioteca de Java o definida por el usuario.
O b j e c t d a t o s = new D o u b l e ( n ) ;
Segn esto, para que la clase C L istaL inealSE perm ita listas de objetos de
cualquier tipo, basta con que su clase interna C E lem ento (clase de cada uno de los
elem entos de la lista) tenga un atributo que sea una referencia de tipo O bject. Un
atributo as definido puede referenciar cualquier objeto de cualquier clase.
E sta m odificacin im plica dos cam bios m s: el parm etro del m todo aadir-
A lP rincipio tiene que ser ahora de tipo O bject, y el m todo obtener tiene que de
volver ahora una referencia de tipo O bject.
//////////////////////////////////////////////////////////////////
// L i s t a lineal sim plemente en laz ada
//
public class CListaLinealSE
I
II p: r e f e r e n c i a al p r i m e r e l e m e n t o de l a lista
p r i v a t e CElemento p - n u i l :
public C L ist a L in e a lS E () II // c o n s t r u c t o r
// A a d i r un e l e m e n t o a l p r i n c i p i o d e l a l i s t a
p u b lic void aad r A l P r i n c i p i (O b je c t obj)
I
C E l e m e n t o q = new C E l e m e n t o O :
q .d atos - obj: // a s i g n a c i n de v a l o r e s
q . s i g u i e n t e = p; // r e a s i g n a c i n de r e f e r e n c i a s
p = q:
I
p u b lic Object o b te n e r in t i)
I
i f (p - - n u l 1)
I
System .err.println("1 ista v a c i a " ):
r e t u r n n u l 1;
C E l e m e n t o q = p: II r e f e r e n c i a al prim er elemento
if (i >- 0)
I
// P o s i c i o n a r s e en e l e l e m e n t o i
f o r ( i n t ri = 0: q ! = n u i l && n < i : n + + )
q - q.siguiente:
// R e t o r n a r l o s d a t o s
i f (q ! - n u i l ) r e t u r n q . d a t o s :
I
// n d i c e f u e r a de l i m i t e s
r e t u r n n u l 1;
//////////////////////////////////////////////////////////////////
2. Solicitar datos de tipo d o u b le del teclado y los aadir a la lista, para lo cual
enviar al objeto h e el m ensaje aadirA IP rincipio por cada dato que aada.
Pero com o aadirA IP rincipio tiene un parm etro de tipo O bject, el argu
m ento pasado tiene que ser un objeto; en este caso un objeto que encapsule un
valor de tipo double. Estos objetos son construidos a partir de la clase D o u b le
del paquete ja v a.lan g.
I se . a a d rAl P r i nci pi o(new D o u b l e ( n ));
//////////////////////////////////////////////////////////////////
// C r e a r una lista lineal simplemente enlazada
//
public class Test
I
public static void m a in (S trin g [] args)
I
II C r e a r una l i s t a l i n e a l v a c i a
C L i s t a L i n e a l S E l s e = new C L i s t a L i n e a l S E ( ) :
// L e e r d a t o s r e a l e s y a a d i r l o s a l a l i s t a
d o u b l e n;
boolean eof = true:
S y s t e m . o u t . p r i n t l n ( " l n t r o d u c i r d a t o s . F i n a l i z a r con C t r l + Z . " ) :
System .out.print"dato: "):
w h ile (D o u b le . is N a N n = L e e r . d a t o D o u b le )) ! - eof)
1
lse.aadi rA lP rin cip io (n e w D o u b le (n )):
S y s t e m . o u t . p r i n t l " d a t o : );
// M o s t r a r l a l i s t a de d a t o s
S y s t e m . o u t . p r i n t l n ( ):
512 JA VA: C U R SO DE PRO G R A M A CI N
D o u b l e d = ( D o u b l e ) l s e . o b t e n e r ( i );
wh i l e (d != n u i l )
1
S y s t e m . o u t . p r i n t ( d . d o u b l e V a l u e ( ) + " ):
i ++;
d = ( D o u b l e ) l s e . o b t e n e r ( i );
1
1
if
Para finalizar, vam os a com pletar la clase C L istaL inealSE con otros mtodos
de inters que especificam os en la tabla siguiente:
M to d o S ig n ific a d o
tam ao D evuelve el nm ero de elem entos de la lista. N o tiene pa
rm etros.
a adir A ade un elem ento en la posicin /. T iene dos parm etros:
posicin i y una referencia al objeto a aadir. D evuelve
true si la operacin se ejecuta satisfactoriam ente y false en
caso contrario.
aadirA lP rincipio A ade un elem ento al principio. T iene un parm etro que es
una referencia al objeto a aadir. D evuelve true o false.
igual que aadir.
a adirA lF inal A ade un elem ento al final. T iene un parm etro que es una
referencia al objeto a aadir. D evuelve true o false, igual
que aadir.
borrar B orra el elem ento de la posicin i. T iene un parm etro que
indica la posicin i del objeto a borrar. D evuelve una refe
rencia al objeto borrado o n u il si la lista est vaca o el n
dice est fuera de lm ites.
borrarP rim ero Borra el p rim er elem ento. N o tiene parm etros. D evuelve
una referencia al objeto borrado o n u il si la lista est vaca.
borrar ltim o B orra el ltim o elem ento. N o tiene parm etros. D evuelve
una referencia al objeto borrado o n u il si la lista est vaca.
obtener D evuelve el elem ento de la posicin /, o bien n u il si la lista
est vaca o el ndice est fuera de lmites. T iene un par
m etro que se corresponde con la posicin i del objeto que
se desea obtener.
obtenerP rim ero D evuelve el p rim er elem ento, o bien n u il si la lista est va
ca.
obtener ltim o D evuelve el ltim o elem ento, o bien n u il si la lista est va
ca.
CA PTU LO 13: ESTR U C TU R A S D IN M ICA S 5 1 3
//////////////////////////////////////////////////////////////////
// L i s t a lineal simplemente enlazada
//
public c la ss CListaLinealSE
I
// p: r e f e r e n c i a a l p r i m e r e l e m e n t o de l a lista.
// E s e l e l e m e n t o de c a b e c e r a ,
p r i v a t e CElemento p = n u i l ;
public C ListaLinealSE!) II // c o n s t r u c t o r
return false;
// C r e a r e l e l e m e n t o a a a d i r
C E l e m e n t o q - new C E 1 e m e n t o ! o b j . n u i l ) ;
// S i l a l i s t a no e s t v a c i a , e n c o n t r a r e l p u n t o de i n s e r c i n
C E l e m e n t o e l e m A n t e r i o r = p;
C E l e m e n t o e l e m A c t u a l = p;
// P o s i c i o n a r s e en e l e l e m e n t o i
f o r ( i n t n - 0: n < i : n++)
[
e lem Anterior = elemActual;
ele m Actual = e l e m A c t u a l . s i g u i e n t e ;
I
// Do s c a s o s :
// 1) I n s e r t a r a l p r i n c i p i o d e l a l i s t a
// 2 ) I n s e r t a r d e s p u s d e l a n t e r i o r ( i n c l u y e i n s e r t a r a l f i n a l )
i f ( elem Anterior = e l e m A c t u a l ) // i n s e r t a r a l p r i n c i p i o
I
q . s i g u i e n t e = p:
p = q ; // c a b e c e r a
I
else // i n s e r t a r d e s p u s d e l anterior
(
q . s ig u i e n t e = elemActual:
e l e m A n t e r i o r . s i g u i e n t e = q;
I
return true:
p u b lic Object b o r r a r ( i n t i)
I
// B o r r a r e l e l e m e n t o de l a p o s i c i n i
i n t nmeroDeElementos = tamao();
i f ( i > = n m e r o D e E l e m e n t o s || i < 0)
r e t u r n n u l 1;
// E n t r a r en l a l i s t a y e n c o n t r a r el I n d i c e del elemento
C E l e m e n t o e l e m A n t e r i o r - p;
C E l e m e n t o e l e m A c t u a l - p;
// P o s i c i o n a r s e en e l e l e m e n t o i
f o r ( i n t n = 0: n < i : n + + )
I
elem Anterior = elemActual;
ele mActual = e l e m A c t u a l . s i g u i e n t e ;
I
// D o s c a s o s :
// 1) B o r r a r e l p r i m e r e l e m e n t o de l a l i s t a
// 2 ) B o r r a r e l s i g u i e n t e a e l e m A n t e r i o r ( e l e m A c t u a l )
i f ( e l e m A c t u a l = = p ) // 1)
p = p . s i g u i e n t e ; // c a b e c e r a
e l s e // 2)
e le m A n te rio r.sig u ie n te = elem Actual. s ig u i e n t e ;
r e t u r n e l e m A c t u a l . d a t o s ; II r e t o r n a r el elemento borrad o.
// El e l e m e n t o r e f e r e n c i a d o p o r e l e m A c t u a l s e r e n v i a d o a l a
// b a s u r a ( b o r r a d o ) al q u e d a r d e s r e f e r e n c i a d o . p o r s e r
// e l e m A c t u a l una v a r i a b l e l o c a l .
pu b lic Object b o r r a r lt im o ( )
I
// B o r r a r e l l t i m o e l e m e n t o
re tu rn b o r r a r ! t a m a o t ) - 1);
C E l e m e n t o q = p: // r e f e r e n c i a a l prim er elemento
// P o s i c i o n a r s e en e l e l e m e n t o i
f o r ( i n t n = 0: n < i : n + + )
q = q.siguiente:
// R e t o r n a r l o s datos
return q.datos:
//////////////////////////////////////////////////////////////////
C om o ejercicio, supongam os que deseam os crear una lista lineal sim plem ente
enlazada con la intencin de alm acenar los nom bres de los alum nos de un deter
m inado curso y sus notas de la asignatura de P rogram acin. S egn este enunciado
a qu tipo de objeto liar referencia cada elem ento de la lista? Pues, a objetos
cuya estructura interna sea capaz de alm acenar un nom bre (dato de tipo S t r in g ) y
una nota (dato de tipo d o u b le). A dem s, estos objetos podrn recibir una serie de
m ensajes con la intencin de extraer o m odificar su contenido. L a clase represen
tativa de los objetos descritos la vam os a denom inar C D atos y puede escribirse de
la form a siguiente:
public c la ss CDatos
I
// A t r i b u t o s
p r i v a t e S t r i n g nombre:
p r i v a t e double nota:
// M t o d o s
p u b lic CDatosC) I I // c o n s t r u c t o r s i n p a r m e t r o s
public CDatostString nom, d o u b l e n ) // c o n s t r u c t o r c o n p a r m e t r o s
I
nombre = nom:
n o t a = n:
I
nombre = nom:
)
public v o i d a s i g n a r N o t a ( d o u b l e n)
I
nota - n;
I
public double o b t e n e r N o t a ()
I
return nota:
Slo nos queda realizar una aplicacin que utilizando las clases C ListaLineal
S E y C D atos cree una lista lineal y ponga en prctica las distintas operaciones que
sobre ella pueden realizarse. La figura siguiente m uestra de form a grfica la es
tructura de datos que querem os construir. O bserve que. en realidad, la lista lo que
m antiene son referencias a los datos (objetos C D atos) y no los datos en s, aun
que, p o r sencillez, tam bin resulta aceptable pensar que stos form an parte de la
lista lineal. La variable p es una referencia (ref_e0) al elem ento de ndice 0; este
elem ento m antiene una referencia (ref_e) al elem ento de la lista de ndice 1 y una
referencia (ref_d,) al objeto de datos correspondiente, y as sucesivam ente.
p = ref_e 0
//////////////////////////////////////////////////////////////////
// C r e a r una lista lineal sim plemente en laz ada
//
5 18 JA VA : C U R SO DE PRO G R A M A CI N
public c la ss Test
I
public static void m o st ra rL is ta C L is ta L in e a lS E lse)
I
// M o s t r a r t o d o s l o s e l e m e n t o s d e l a lista
i n t i = 0 , tam = l s e . s i z e ) ;
CDatos obj;
w h i l e ( i < tam)
(
o b j = ( C D a t o s ) l s e . o b t e n e r ( i );
System .out.p rintlni + ".- " + o b j . obte nerNombre ) + " " +
ob j.o b te n e rN o ta)):
i++;
II L e e r d a t o s y a a d i r l o s a l a l i s t a
S t r i n g n o mbr e ;
double nota;
int i = 0 ;
S y s t e m . o u t .p rin t ln ( " In tr o d u c ir datos. F i n a li z a r con C t r l + Z . " ) :
System .out.print"nom bre: "):
w h i le ((nombre = L e e r . d a t o ) ) != n u i l )
I
System .out.p rin t"nota: );
n o t a = L e e r . d a t o D o u b l e ( ):
1s e . a a d i r A lF in a l( n e w CDatosnombre, nota));
System .out.print"nom bre: ");
// A a d i r un o b j e t o a l p r i n c i p i o
ls e . a a d ir A lP r in c ip io n e w C D a t o s " a b c d " . 10));
II A a d i r un o b j e t o en l a p o s i c i n 1
1 s e . a a d i r ( 1. new C D a t o s " d e f g " , 9 . 5 ) ) ;
S y s t e m . o u t . p r i n t l n i " \ n " );
// M o s t r a r e l p r i m e r o
C D a t o s o b j = ( C D a t o s )1 s e . o b t e n e r P r i m e r o ):
Sy ste m .o u t.p rin tln i"P rim e ro : " + obj.obtenerNom bre) + " " +
ob j.o b te n e rN o ta));
// M o s t r a r e l l t i m o
o b j = ( C D a t o s ) l s e . o b t e n e r l t i m o );
CA PTU LO 13: ESTR U C TU R A S D IN M ICA S 5 1 9
// B o r r a r e l e l e m e n t o de n d i c e 2
obj = ( C D a t o s ) l s e . b o r r a r { 2 ) :
i f ( o b j = = n u l 1)
S y s t e m . o u t . p r i n t l n ( " E r r o r : e l e m e n t o no b o r r a d o ) :
// M o d i f i c a r e l e l e m e n t o de I n d i c e 1
obj = ( C D a t o s ) 1 s e . o b t e n e r ( 1 ) ;
obj,asignarNota(9);
// M o s t r a r t o d o s
System .out.pri n t l n ( " L i s t a : " ) :
m ostrarLista(lse);
Clase LinkedList
L a clase L in k e d L is t pertenece a la biblioteca de Java; est incluida en el paquete
java.util. T iene unas caractersticas sim ilares a nuestra clase C ListaLinealSE . La
tabla siguiente m uestra algunos de los m todos proporcionados por esta clase:
M to d o S ig n ific a d o
LinkedList Es el constructor de la clase. T iene uno sin parm etros.
size D evuelve un valor de tipo in t correspondiente al nm ero de
elem entos de la lista. N o tiene parm etros.
add A ade un elem ento en la posicin i. T iene d os parm etros:
posicin i y una referencia de tipo O b je c t al objeto a aa
dir. N o devuelve ningn valor.
addFirst A ade un elem ento al principio. T iene un parm etro que es
una referencia de tipo O b je c t al objeto a aadir. N o de
vuelve ningn valor.
addLast A ade un elem ento al final. T iene un parm etro q ue es una
referencia de tipo O b je ct al objeto a aadir. N o devuelve
ningn valor.
remove B orra el elem ento de la posicin i. T iene un parm etro de
tipo int que se corresponde con la posicin i del objeto a
borrar. D evuelve una referencia de tipo O b je c t al objeto
borrado o lanza una excepcin si la lista est vaca o el n
dice est fuera de lm ites.
520 JA V A : C U R S O D E P R O G R A M A C I N
M to d o S ig n ific a d o
rem oveFirst B orra el prim er elem ento. N o tiene parm etros. Devuelve
una referencia de tipo O b je c t al objeto borrado o lanza una
excepcin si la lista est vaca.
rem oveLast B orra el ltim o elem ento. N o tiene parm etros. Devuelve
una referencia de tipo O b je c t al objeto borrado o lanza una
excepcin si la lista est vaca.
get D evuelve una referencia de tipo O b je c t correspondiente al
elem ento de la posicin i, o bien lanza una excepcin si la
lista est vaca o el ndice est fuera de lm ites. T iene un
parm etro de tipo in t correspondiente a la posicin i del
objeto que se desea obtener.
getF irst D evuelve una referencia de tipo O b je c t correspondiente al
p rim er elem ento o lanza una excepcin si la lista est vaca.
N o tiene parm etros.
getLast D evuelve una referencia de tipo O b je c t correspondiente al
ltim o elem ento o lanza una excepcin si la lista est vaca.
N o tiene parm etros. ________________
// L e e r d a t o s y a a d i r l o s a l a l i s t a
S t r i n g n o mbr e ;
double nota;
i n t i = 0:
System .out.p r i n t l n ( " In tro d u c ir datos. F in a liz a r con C t r l + Z . " ) :
S y s t e m . o u t . p r i n t ( " n o m b r e : ):
w h i le ((nombre = L e e r . d a t o O ) != n u i l )
I
System .out.print( "n o ta: ):
n o t a = L e e r . d a t o D o u b l e );
lse .a d d L a st(n e w CDatos(nombre. nota));
S y s t e m . o u t . p r i n t ( " n o m b r e : );
// A a d i r un o b j e t o al p r i n c i p i o
I s e .addFirst(new C D a to s ( "a b c d ". 10)):
II A a d i r un o b j e t o en l a p o s i c i n 1
l s e . a d d d , new C D a t o s ( " d e f g . 9 . 5 ) ) ;
S y s t e m . o u t . p r i n t l n ( \ n " );
// M o s t r a r e l p r i m e r o
C D a t o s o bj = ( C D a t o s ) 1 s e . g e t F i r s t ( );
S y s te m .o u t .p rin tln "P rim e r o : " + o b j .obtenerNombre() + " +
obj.obtenerN ota());
// M o s t r a r e l l t i m o
o bj = ( C D a t o s ) l s e . g e t L a s t ):
S y s t e m . o u t . p r i n t l n ( 1 t i m o : + o b j .obtenerNombre() + " +
obj.obtenerNota());
// M o s t r a r t o d o s
S y s t e m . o u t . p r i n t l n ( " L i s t a : ):
m o stra rL i s t a ( 1s e ) ;
// B o r r a r el e l e m e n t o de I n d i c e 2
o b j = ( C D a t o s ) 1 s e . r e m o v e ( 2 );
// M o d i f i c a r e l e l e m e n t o de i n d i c e 1
o bj = ( C D a t o s ) 1 s e . g e t ( 1 ) ;
obj.asignarN ota(9);
// M o s t r a r t o d o s
S y ste m .o u t.p r i n t l n ( " Li s t a : " ) :
m o stra rL i s t a ( 1s e ) :
522 J A V A : C U R S O D E P R O G R A M A C I N
LISTAS CIRCULARES
U na lista circular es una lista lineal en la que el ltim o elem ento apunta al prim e
ro. E ntonces es posible acceder a cualquier elem ento de la lista desde cualquier
punto dado. L as operaciones sobre una lista circular resultan m s sencillas, ya que
se evitan casos especiales. P or ejem plo, el m todo a a d ir de la clase CListaLi-
n ea lS E expuesta anteriorm ente contem pla dos casos: insertar al principio de la
lista e insertar a continuacin de un elem ento. C on una lista circular, estos dos ca
sos se reducen a uno. La siguiente figura m uestra cm o se ve una lista circular
sim plem ente enlazada.
C uando recorrem os una lista circular, direm os que hem os llegado al final de
la m ism a cuando nos encontrem os de nuevo en el punto de partida, suponiendo,
desde luego, que el punto de partida se guarda d e alguna m anera en la lista; por
ejem plo, con una referencia fija al m ism o. E sta referencia puede ser al primer
elem ento de la lista; tam bin puede ser al ltim o elem ento, en cuyo caso tambin
es conocida la direccin del p rim er elem ento. O tra posible solucin sera poner un
elem ento especial identificable en cada lista circular com o lugar de partida. Este
elem ento especial recibe el nom bre de elem ento de cabecera de la lista. Esto pre
senta, adem s, la ventaja de que la lista circular no estar nunca vaca.
Com o ejem plo, vam os a construir una lista circular con una referencia fija al
ltim o elem ento. U na lista circular con una referencia al ltim o elem ento es equi
valente a una lista lineal recta con dos referencias, una al principio y otra al final.
Para co n struir una lista circular, prim ero tendrem os que definir la clase de
objetos que van a form ar parte de la m ism a. P or ejem plo, cada elem ento de la lista
puede definirse com o una estructura de datos con dos m iem bros: una referencia al
elem ento siguiente y otra al rea de datos. El rea de datos puede ser de un tipo
predefinido o de un tipo definido por el usuario. S egn esto, el tipo de cada ele
m ento de la lista puede venir definido de la form a siguiente:
// M t o d o s
p r v a t e C E l e m e n t o O I I // c o n s t r u c t o r
p r i v a t e C E l e m e n t o t O b j e c t d, C El em en to s ) // c o n s t r u c t o r
I
d a t o s = d;
s i g u i e n t e = s;
V em os que p o r tratarse de una lista lineal sim plem ente enlazada, aunque sea
circular, la estructura de sus elem entos no varan con respecto a lo estudiado ante
riorm ente.
Podem os autom atizar el proceso de im plem entar una lista circular diseando
una clase C L istaC ircularSE (C lase Lista C ircular Sim plem ente Enlazada) que
proporcione los atributos y m todos necesarios para crear cada elem ento de la
lista, as com o para perm itir el acceso a los m ism os. E sta clase nos perm itir pos
teriorm ente d eriv ar otras clases que sean m s especficas; p o r ejem plo, una clase
para m anipular p ila s o una clase para m anipular colas. E stas estructuras de datos
las estudiarem os un poco m s adelante.
Clase CListaCircularSE
La clase C ListaC ircularSE que vam os a im plem entar incluir un atributo ltim o
que valdr n u il cuando la lista est vaca y cuando no, referenciar siem pre a su
ltimo elem ento; una clase interna, C E lem ento, que definir la estructura de los
elem entos; y los m todos indicados en la tabla siguiente:
M to d o S ig n ific a d o
obtener D evuelve el elem ento de la posicin i, o bien n u il si la lista
est vaca o el ndice est fuera de lm ites. Tiene un par
m etro correspondiente a la posicin / del objeto que se de
sea obtener.
lllllllllllllllllllllllllllllllllllllllllllllllllllllllltlllllllll
II L i s t a lineal circular sim plemente en laza da
//
public c la ss CListaCircularSE
I
// l t i m o : r e f e r e n c i a e l l t i m o e l e m e n t o .
// l t i m o . s i g u i e n t e r e f e r e n c i a a l p r i m e r e l e m e n t o de l a lista,
p r i v a t e CElemento l t i m o = n u i l ;
public in t tamaoO
I
// D e v u e l v e el n me r o de e l e m e n t o s de l a l i s t a
i f ( l t i m o = = n u i l ) r e t u r n 0:
C E l e m e n t o q = l t i m o . s i g u i e n t e : // p r i m e r e l e m e n t o
i n t n 1: // n me r o d e e l e m e n t o s
w h i 1e ( q ! = l t i m o )
I
n++;
q = q. s i g u i e n t e :
)
return n;
I
C A PTU LO 13: ESTRU C TU R A S DINM ICA S 5 2 5
p u b lic Object b o r r a r O
I
// D e v u e l v e una r e f e r e n c i a a l o s d a t o s del p r i m e r e l e m e n t o de
// l a l i s t a y b o r r a e s t e e l e m e n t o ,
i f ( ltim o == n u l1 )
I
System .err.println "Lista vac1a\n" ):
return n u il:
CElemento q = l t i m o . s i g u i e n t e ;
O b je ct obj = q . d a t o s :
526 JA VA: C U R SO D E PROGRAM A CIN
i f ( q == ltimo )
ltimo = n u il;
el se
ltim o.siguiente = q.siguiente;
re tu rn obj;
// El e l e m e n t o r e f e r e n c i a d o p o r q e s e n v i a d o a l a b a s u r a , al
// q u e d a r d e s r e f e r e n c i a d o c u a n d o f i n a l i z a e s t e m t o d o p o r s e r
// q una v a r i a b l e 1 o c a l .
C E l e m e n t o q = l t i m o . s i g u i e n t e ; // p r i m e r e l e m e n t o
// P o s i c i o n a r s e en e l e l e m e n t o i
f o r ( i n t n = 0; n < i ; n + + )
q = q.siguiente;
// R e t o r n a r l o s datos
return q.datos:
llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
//////////////////////////////////////////////////////////////////
// C r e a r un a lista lineal circular simplemente enlazada
//
public c la ss Test
I
public static void m o st ra rL is t a ( C L is t a C irc u la rS E Icse)
I
// M o s t r a r t o d o s l o s e l e m e n t o s de l a lista
i n t i = 0. tam = 1 e s e . t a m a o ( );
CDatos obj;
// L e e r d a t o s y a a d i r l o s a l a l i s t a
S t r i n g n o mbr e :
double nota:
i n t i = 0:
System .out.p r i n t n ( " In t r o d u c ir datos. F i n a li z a r con C t r l + Z . " ) :
System .out.print"nom bre: ");
w h i l e ( ( n o m b r e = L e e r . d a t o O ) !*= n u i l )
I
System .out.p rint"nota: );
n o t a = L e e r . d a t o D o u b l e ):
1e s e . a a d i r A l F i n a l ( n e w C D a t o s ( n o m b r e . nota)):
System .out.print("nom bre: ");
I
// A a d i r un o b j e t o a l p r i n c i p i o
lcse .a a d irA lP rin c ip io (n e w C D a to s("a b e d ", 10)):
S y s t e m . o u t . p r i n t l n ( \ n " ) ;
// M o s t r a r l a 1 i s t a
S y s t e m . o u t . p r i n t n ( " L i s t a : );
m o s t r a r L i s t a ( 1e s e ) :
// B o r r a r e l e l e m e n t o p r i m e r o
C D a t o s o bj = ( C D a t o s ) l c s e . b o r r a r ( );
// M o s t r a r l a l i s t a
S y s te m .o u t.p rin tln ("L is ta :");
m o strarLista(lcse);
I
PILAS
Una p ila es una lista lineal en la que todas las inserciones y supresiones se hacen
en un extrem o de la lista. U n ejem plo de esta estructura es una pila de platos. En
ella, el aadir o q uitar platos se hace siem pre p o r la parte superior de la pila. Este
528 JA V A: C U R SO DF. PRO G R A M A CI N
tipo de listas recibe tam bin el nom bre de listas U F O (last in fir s t out - ltim o en
entrar, prim ero en salir).
Las operaciones de m eter y sacar en una pila son conocidas en los lenguajes
ensam bladores com o p u sh y p o p , respectivam ente. La operacin de sacar un ele
m ento de la pila suprim e dicho elem ento de la misma.
Para trabajar con pilas podem os disear una clase C P ila (C lase P ila) derivada
de la clase base C ListaC ircularSE , que soporte los siguientes m todos:
//////////////////////////////////////////////////////////////////
// P i l a : l i s t a en l a q u e t o d a s l a s i n s e r c i o n e s y s u p r e s i o n e s se
// h a c e n en un e x t r e m o de l a mi s ma.
//
public class CPila extends CListaCircularSE
(
publ i c C P i l a O I)
p u b l i c O b j e c t s a c a r D e P i 1a ( )
(
return b o r r a r t );
1
I
//////////////////////////////////////////////////////////////////
Para m eter el elem ento referenciado por el parm etro obj en la pila, el m todo
m eterE nP ila invoca al m todo aadrA lP rincipio de la clase base C ListaCircu-
la rS E ; y para sacar el elem ento de la cim a de la pila y elim inarlo de la m ism a, el
m todo sacarD eP ila invoca al m todo borrar de la clase base.
COLAS
U na cola es una lista lineal en la que todas las inserciones se hacen por un extre
m o de la lista (por el final) y todas las supresiones se hacen p o r el otro extrem o
(por el principio). Por ejem plo, una fila en un banco. E ste tipo de listas recibe
tam bin el nom bre de listas F IF O (first in ftr s t out - prim ero en entrar, prim ero en
salir). Este orden es la nica form a de insertar y recuperar un elem ento de la cola.
U na cola no perm ite acceso aleatorio a un elem ento especfico. Tenga en cuenta
que la operacin de sacar elim ina el elem ento de la cola.
Para trabajar con colas podem os disear una clase C Cola (C lase Cola) deri
vada de la clase base C ListaC ircularSE , que soporte los siguientes m todos:
//////////////////////////////////////////////////////////////////
// C o l a : l i s t a en l a que t o d a s l a s i n s e r c i o n e s s e h a c e n p o r un
// e x t r e m o de l a l i s t a ( p o r e l f i n a l ) y t o d a s l a s s u p r e s i o n e s se
530 J A V A : C U R S O D E P R O G R A M A C I N
P ara m eter el elem ento referenciado por el parm etro o b j en la cola, el mto
d o m eterE nC ola invoca al m todo aadirA lF inal de la clase b ase CListaCircular-
S E ; y para sacar el elem ento de la cola y elim inarlo de la m ism a, el mtodo
sacarD eC ola invoca al m todo borrar de la clase base.
EJEMPLO
El siguiente ejem plo m uestra cm o u tilizar la clase C ListaC ircularSE y sus deri
vadas C Pila y C Cola. P rim eram ente cream os una pila y una cola de objetos de la
clase C D atos y a continuacin cream os una lista circular. Para com probar que las
listas se han creado correctam ente, m ostram os a continuacin los contenidos de
las m ism as. A dem s, para certificar que cuando se saca un elem ento de una pila o
de una cola ste es elim inado, intentam os m ostrar por segunda vez el contenido de
las m ism as; el resultado es un m ensaje d e que estn vacas.
En este ejem plo aparece tam bin por prim era vez el operador in s ta n c e o f cuya
sintaxis es la siguiente:
CA PTU LO 13: ESTRU C TU R A S D IN M ICA S 5 3 1
//////////////////////////////////////////////////////////////////
/ / P i l a s y c o l a s
//
p u b l i c c l a s s T e s t
I
p u b l i c s t a t i c v o i d m o s t r a r L i s t a C L i s t a C i r c u l a r S E l i s t a )
(
/ / M o s t r a r t o d o s l o s e l e m e n t o s d e l a l i s t a
i n t i - 0 . t a m = 1 i s t a . t a m a o t ) :
C D a t o s o b j :
w h i l e ( i < t a m )
I
if (lista i n s t a n c e o f CPila)
obj - ( C D a t o s ) ( ( C P i l a ) l i s t a ) . s a c a r D e P i l a ( ) :
e l s e if ( l i s t a i n s t a n c e o f CCola)
obj = ( C D a t o s ) ( ( C C o l a ) l i s t a ) . s a c a r D e C o l a ( ) :
e l s e
I
i++:
c o n t i n u e ;
S y s t e m . o u t . p r i n t l n ( i + " + o b j . o b t e n e r N o m b r e ) + " +
o b j . o b t e n e r N o t a ) ) ;
i ++;
I
i f ( t a m = 0 ) S y s t e m . o u t . p r i n t l n " 1 i s t a v a c i a ) :
p u b l i c s t a t i c v o i d m a i n S t r i n g [ ] a r g s )
I
/ / C r e a r u n a p i l a y u n a c o l a v a c i a s
C P i la pila - n e w C P ila):
CCola cola = n e w C C o l a );
II L e e r d a t o s y a a d i r l o s a a m b a s
S t r i n g n o m b r e :
d o u b l e n o t a :
i n t i = 0 :
532 JA V A : C U R SO DE PRO G R A M A CI N
// M o s t r a r l a p i l a
S y s t e m . o u t . p r i n t n ( " \ n P i 1a : " ) :
m ostrarLista(pila):
// M o s t r a r l a p i l a p o r s e g u n d a vez
S y s t e m . o u t . p r i n t l n ( " \ n P i 1a : );
mostrarLi s t a ( p ila ) :
// M o s t r a r l a c o l a
Syste m .o u t.p rin tln ("\n C o la :");
m ostrarLista(cola);
// M o s t r a r l a c o l a p o r s e g u n d a vez
System .out.pri n t ln ( "\ n C o la : ") ;
m ostrarLista(cola);
// C r e a r una l i s t a c i r c u l a r
C L i s t a C i r c u l a r S E l c s e = new C L i s t a C i r c u l a r S E ( ) ;
1 e s e . a a d i r A l F i n a l ( n e w C D a t o s ( "1 e s e " , 1 0 ) ) :
// M o s t r a r l a l i s t a c i r c u l a r
System .out.pri n t l n " \ n lc s e : "):
mostrarLi s t a ( lc s e );
1
I '
se m ostrarn los siguientes resultados, los cuales indican que el operador in sta n -
ceo f ha funcionando correctam ente discrim inando la clase de objeto que se desea-
CA PTU LO 13: ESTRU C TU R A S D IN M ICA S 5 3 3
ba m ostrar en cada instante, y que las operaciones de sacar en las pilas y colas
elim inan el objetado sacado de las m ism as.
Pila:
0.- A l u mn o 3 9 . 5
1. - A l u mn o 2 8 . 5
2.- Al umno 1 7. 5
Pila:
lista vacia
Col a :
0.- A l u mn o 1 7.5
1 . A l u m n o 2 8.5
2 .- Alu m n o 3 9.5
Col a :
l i s t a vacia
1e s e :
Las operaciones sobre una lista doblem ente enlazada norm alm ente se realizan
sin ninguna dificultad. S in em bargo, casi siem pre es m ucho m s fcil la m anipu
lacin de las m ism as cuando existe un doble enlace entre el ltim o elem ento y el
prim ero, estructura que recibe el nom bre de lista circular doblem ente enlazada.
Para m overse sobre una lista circular, es necesario alm acenar de alguna m anera
un punto de referencia; p o r ejem plo, m ediante una referencia al ltim o elem ento
de la lista.
Para co n struir una lista de este tipo, prim ero tendrem os que definir la clase de
objetos q ue van a form ar parte de la m ism a. P or ejem plo, cada elem ento de la lista
puede definirse com o una estructura de datos con tres m iem bros: una referencia al
elem ento siguiente, otra al elem ento anterior y o tra al rea de datos. El rea de
datos puede ser de un tipo predefinido o de un tipo definido p o r el usuario. Segn
esto, el tipo de cada elem ento de la lista puede venir definido de la form a si
guiente:
// M t o d o s
p rivate CElementoO 11 // c o n s t r u c t o r
I
P odem os autom atizar el proceso de im plem entar una lista circu lar doblem ente
enlazada, diseando una clase C ListaC ircularD E (C lase Lista C ircular D oble
m ente Enlazada) que proporcione los atributos y m todos necesarios para crear
cada elem ento de la lista, as com o para perm itir el acceso a los m ism os. La clase
que diseam os a continuacin cubre estos objetivos.
Clase CListaCircularDE
La clase C ListaC ircularD E que vam os a im plem entar incluir los atributos lti
m o , actual, nrneroD eElem entos y posicin. El atributo ltim o valdr n u il cuando
la lista est vaca y cuando no, referenciar siem pre a su ltim o elem ento; actual
hace referencia al ltim o elem ento accedido; nrneroD eElem entos es el nm ero
de elem entos que tiene la lista y posicin indica el ndice del elem ento referencia-
CA PTU LO 13: ESTR U C TU R A S DINM ICA S 5 3 5
do p o r actual. A sim ism o, incluye una clase interna, C Elem ento, que definir la
estructura de los elem entos, y los m todos indicados en la tabla siguiente:
M to d o S ig n ificad o
C ListaC ircularD E Es el constructor. Inicia ltim o y actual a nuil, nm eroD e
Elem entos a 0 y posicin a -1 (la posicin del prim er ele
m ento de la lista es la 0).
tam ao D evuelve el nm ero de elem entos de la lista. No tiene pa
rm etros.
insertar A ade un elem ento a continuacin del referenciado por
actual. El elem ento aadido p asa a ser el elem ento actual.
T iene un parm etro que es una referencia de tipo O b je c t al
objeto a aadir. N o devuelve ningn valor.
borrar B orra el elem ento referenciado p o r actual. N o tiene par
m etros. D evuelve una referencia al objeto borrado o n u il si
la lista est vaca.
irA lSiguiente A vanza la posicin a ctu a l al siguiente elem ento. Si esta po
sicin coincide con nm eroD eE lem entos-1, perm anece en
ella. N o tiene parm etros y no devuelve ningn valor.
irA lA nterior R etrasa la posicin actual al elem ento anterior. Si esta p o
sicin coincide con la 0, perm anece en ella. N o tiene par
m etros y no devuelve ningn valor.
irAlPrincipio Hace que la posicin actual sea la 0. N o tiene parm etros y
no devuelve ningn valor.
irA lF inal H ace que la posicin actual sea la nm eroD eE lem entos-1.
N o tiene parm etros y no devuelve ningn valor.
ir A l A vanza la posicin a ctu a l al elem ento de ndice i (el prim er
elem ento tiene ndice 0). N o tiene parm etros y devuelve
tr u e si la operacin de m over se realiza con xito o false si
la lista est vaca o el ndice est fuera de lmites.
obtener D evuelve el elem ento referenciado p o r actual, o bien nuil
si la lista est vaca. No tiene parm etros.
obtener(i) D evuelve el elem ento de la posicin i, o bien n u il si la lista
est vaca o el ndice est fuera de lm ites. T iene un par
m etro correspondiente a la posicin i del objeto q ue se de
sea obtener.
m odificar Establece nuevos datos para el elem ento actual. T iene un
parm etro que es una referencia de tipo O b je c t al nuevo
objeto. N o devuelve ningn valor.
/////////////////////////////////////////////////////////////////
// La c l a s e l i s t a c i r c u l a r d o b l e m e n t e e n l a z a d a p e r m i t e m a n i p u l a r
// l o s e l e m e n t o s q u e componen una l i s t a de e s t e t i p o .
//
public class CListaCircularDE
I
p r i v a t e CElemento l t i m o ;
// r e f e r e n c i a a l l t i m o e l e m e n t o de l a l i s t a
p r i v a t e CElemento a c t u a l :
// r e f e r e n c i a a l e l e m e n t o a c t u a l en e l q u e e s t a m o s
p r i v a t e long nmeroDeElementos:
// n mero de e l e m e n t o s q u e t i e n e l a l i s t a
p riv a t e long p o sic i n :
// p o s i c i n d e l e l e m e n t o a c t u a l
// M t o d o s
p riva te CElementoO II // c o n s t r u c t o r
p u b l i c 1o ng t a m a o ( )
I
// P e r m i t e s a b e r e l t a ma o d e l a lista
re tu rn nmeroDeElementos:
// L a s d o s l i n e a s s i g u i e n t e s i n i c i a n una l i s t a c i r c u l a r .
ltim o .a n te rio r = ltimo:
ltim o .sig u ie n te = ltimo:
ltim o.datos = obj: // a s i g n a r d a t o s .
actual = ltimo:
posicin = 0L : II ya h a y un e l e m e n t o en l a l i s t a .
:
else II e x i s t e una l i s t a
I
q = new C E 1 e m e n t o t ):
// I n s e r t a r e l n u e v o e l e m e n t o d e s p u s d e l actual,
a c t u a l . s i g u i e n t e . a n t e r i o r = q:
q .sig u ie n te = a c t u a l.s ig u ie n t e :
a c t u a l . s i g u i e n t e = q:
q .a n te rio r = actual:
q.datos = o b j ;
// A c t u a l i z a r p a r m e t r o s .
posic1n++;
// S i e l e l e m e n t o a c t u a l e s e l l t i m o , el nuevo elemento
// p a s a a s e r e l a c t u a l y e l l t i m o ,
i f ( actual = ltimo )
l t i m o = q;
n m e r o D e E l e m e n t o s + + : // in c re m e n t a r el n me r o de e l e m e n t o s .
p u b lic Object b o r r a r t )
I
// El m t od o b o r r a r d e v u e l v e l o s d a t o s d e l e l e m e n t o
// r e f e r e n c i a d o p o r a c t u a l y l o e l i m i n a de l a l i s t a
// ( a l q u e d a r d e s r e f e r e n c i a d o e s e n v i a d o a l a b a s u r a )
C E l e m e n t o q:
Object obj:
i f ( l t i m o == n u i l ) r e t u r n ( n u i l ): II l i s t a v a c i a ,
i f ( a c t u a l = = l t i m o ) // s e t r a t a del l t i m o elemento.
I
if( nmeroDeElementos 1L ) // h a y un s o l o e l e m e n t o
I
obj = l t i m o . d a t o s :
l t i m o = a c t u a l - n u l 1:
nmeroDeElementos - 0 L :
posicin = -1L :
I
538 J A V A : C U R S O D E P R O G R A M A C I N
else // ha y ms de un e l e m e n t o
I
actual = ltim o .a n te rio r;
ltim o .s ig u ie n te .a n t e rio r = actual:
actual .sig u ie n te = ltim o .sig u ie n te :
obj = l t i m o . d a t o s ;
ltimo = actual ;
p o sici n --;
n m e r o D e E l e m e n t o s - -;
I // f i n d e l b l o q u e e l s e
I // f i n d e l b l o q u e i f ( a c t u a l = = l t i m o )
e l s e // el e l e m e n t o a b o r r a r n o e s e l l t i m o
I
q = actual.siguiente:
a c t u a l . a n t e r i o r . s i g u i e n t e = q:
q.a nterio r = a c t u a l.a n t e r io r ;
obj = a c t u a l . d a t o s :
a c t u a l = q:
n m eroDeEle m e ntos--;
I
return obj:
1
public void i r A l P r i n c i p i o ()
I
// Hace q u e l a p o s i c i n a c t u a l sea el principio de l a lista,
actual = ltim o .sig u ie n te :
p o s i c i n = 0L:
C A PTU LO 13: ESTRU C TU R A S DINM ICA S 5 3 9
public void i r A l F i n a l ()
(
// El f i n a l de l a l i s t a e s a h o r a l a posicin actual,
actual = ltimo:
p o s i c i n - n m e r o D e E l e m e n t o s - 1:
i r A l P r i nci p i o ( );
// P o s i c i o n a r s e en e l e l e m e n t o i
f o r ( l o n g n = 0; n < i ; n++)
i r A l S i g u i e n t e ( );
return true:
p u b lic Object o b te n e r)
I
// El m t o d o o b t e n e r d e v u e l v e l a r e f e r e n c i a a los datos
// a s o c i a d o s c o n e l e l e m e n t o a c t u a l .
i f ( l t i m o = = n u i l ) r e t u r n n u i l : // l i s t a vacia
return a c tu a l.d a to s:
a c t u a l. d a t o s = pNuevosDatos:
//////////////////////////////////////////////////////////////////
C rea una lista vaca (ltim o = actual = nuil). En todo m om ento, el ltim o
elem ento de la lista est apuntado por ltim o, y a ctu a l apunta al elem ento
sobre el que se realizar la siguiente operacin.
Ejemplo
El siguiente ejem plo m uestra cm o utilizar la clase C ListaC ircularD E . Prim era
m ente cream os un objeto Icile, correspondiente a una lista circular doblem ente
enlazada, en la que cada elem ento alm acenar un referencia a un objeto C D atos', y
a continuacin realizam os varias operaciones de insercin, m ovim iento y borrado,
para finalm ente visualizar los elem entos de la lista y com probar si los resultados
son los esperados.
//////////////////////////////////////////////////////////////////
II L i s t a circular doblemente en la za da
//
public class Test
I
public static void m o s t r a r L is t a ( C L is t a C ir e u la r D E lista)
I
// M o s t r a r todos l o s e l e m e n t o s de l a lista
CA PTU LO 13: ESTR U C TU R A S DINM ICA S 5 4 1
l o n g i - 0, tam - 1 i s t a . ta m a o ():
CDatos obj:
w h i l e ( i < tam)
(
o b j - ( C O a t o s )1 i s t a . o b t e n e r t i );
System .out.println(i + + obj.obtenerNom bre() + +
o b j.o b t e n e rN o ta ()):
i++:
1
if (tam 0) S y s t e m . o u t . p r i n t l n ( "1 i s t a v a c i a ):
1
// I n s e r t a r e l e m e n t o s
lcde.insertar(new CDatos("alum nol . 7.8)):
lcde.insertartnew C 0atos("a lum no2". 6.5)):
lcde.insertarfnew CDatos("alum no3". 10)):
1c d e . in s e r t a r ( n e w C D a t o s ( " a l u m n o 4 " , 8.6)):
// I r a l e l e m e n t o de l a posicin 2
1cd e .i r A l (2):
// B o r r a r e l e l e m e n t o a c t u a l (posicin 2)
l c d e . b o r r a r ( );
// I r al a n t e r i o r
lcde.i r A l (1);
1c d e . i n s e r t a r ( n e w C D atos("nuevo alumno3", 9.5)):
// I r a l f i n a l
l c d e . i r A l F i n a K );
lcde.insertarnew CDatosf"alum no5". 8 .5 )):
// I r a l a n t e r i o r
l c d e . i r A l A n t e r i o r ( ):
l c d e . m o d i f i c a r n e w C O a t o s ( a l u m n o 4 . 5 . 5 ) ) :
// M o s t r a r l a l i s t a
S y s t e m . o u t . p r i n t l n ( " \ n l i s t a : ):
m o strarlista(lcd e );
542 JA V A : C U R S O D E P R O G R A M A C I N
ARBOLES
Un rbol es una estructura no lineal form ada por un conjunto de nodos y un con
ju n to de ramas.
En un rbol existe un nodo especial denom inado raz. A s m ism o, un nodo del
que sale alguna ram a, recibe el nom bre de nodo de bifurcacin o nodo ram a y un
nodo que no tiene ram as recibe el nom bre de nodo term inal o nodo hoja.
nivel 0
nivel 1
nivel 2
A rbol
El nivel de un nodo respecto al nodo raz se define diciendo que la raz tiene
nivel 0 y cu alquier o tro nodo tiene un nivel igual a la distancia de ese nodo al no
do raz. El m xim o de los niveles se denom ina p rofu n d id a d o altura del rbol.
Es til lim itar los rboles en el sentido de que cada nodo sea a lo sum o de
grado 2. De esta form a cabe distinguir entre subrbol izquierdo y subrbol dere
cho de un nodo. Los rboles as form ados, se denom inan rboles binarios.
CA PITU LO 13: ESTR U C TU R A S D IN M ICA S 5 4 3
rboles binarios
Un rbol binario es un conjunto finito de nodos que consta de un nodo raz que
tiene dos subrboles binarios denom inados subrbol izquierdo y subrbol d ere
cho.
Las expresiones algebraicas, debido a que los operadores que intervienen son
operadores binarios, nos dan un ejem plo de estructura en rbol binario. La figura
siguiente nos m uestra un rbol que corresponde a la expresin aritm tica:
(a + b * c ) / ( d - e / f )
Expresin algebraica
// Nodo d e un r b o l b i n a r i o
p r i v a t e c l a s s CNodo
I
// A t r i b u t o s
p riv a t e Object datos; // r e f e r e n c i a a l o s d a t o s
p r i v a t e CNo do i z q u i e r d o : // r a i z d e l s u b r b o l izquierdo
p r i v a t e CNo do d e r e c h o ; // r a i z d e l s u b r b o l derecho
// M t o d o s
public CNodoO II // c o n s t r u c t o r
544 JA V A : C U R S O D E P R O G R A M A C I N
// Nodo de un r b o l b i n a r i o
p r i v a t e c l a s s CNodo
1
// A t r i b u t o s
p r iv a t e Object datos; // r e f e r e n c i a a l o s d a t o s
p r i v a t e CNodo i z q u i e r d o : // r a z d e l s u b r b o l izquierdo
p r i v a t e CNodo d e r e c h o : II r a z d e l s u b r b o l derecho
// M t o d o s
public CNodoO II // c o n s t r u c t o r
II M t o d o s d e l rbol binario
Si el rbol est vaco, raz es igual a n u il; en otro caso, raz es una referencia
al nodo raz del rbol y segn se puede observar en el cdigo anterior, este nodo
tiene tres atributos: una referencia a los datos y dos referencias m s, una a su su
brbol izquierdo y otra a su subrbol derecho.
B sicam ente se pueden u tilizar tres form as para recorrer un rbol binario:
prcarden, inorden y postorden. C uando se utiliza la form a preorden, prim ero se
visita la raz, despus el subrbol izquierdo y por ltim o el subrbol derecho; en
cam bio, si se utiliza la form a inorden, prim ero se visita el subrbol izquierdo,
despus la raz y por ltim o el subrbol derecho; y si se utiliza la form a postor-
den, prim ero se visita el subrbol izquierdo, despus el subrbol derecho y por l
tim o la raz.
C A PTU LO 13: ESTR U C TU R A S D IN M ICA S 5 4 5
R: r a z p r e o r d e pnre o rd e: n : R , I, D
I: s u b rb o l i z q u i e r d o i n o r d e in onrd e :n : I, R , D
D : s u b rb o l d e re c h o p o s to rd
r d e n : I, D , R
Preorden: / + a * b c - d / e f
Inorden: a + b * c / d - e / f
Postorden: a b c * + d e f / - /
Illllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
II C l a s e r b o l binario.
//
public class CArbolBinario
I
// A t r i b u t o s d e l r b o l binario
p r i v a t e CNodo r a z : // r a i z del rbol
// Nodo de un r b o l b i n a r i o
p r i v a t e c l a s s CNodo
II A t r i b u t o s
p riva te Object datos; II r e f e r e n c i a a l o s d a t o s
p r i v a t e C No do i z q u i e r d o : 1/ r a z d e l s u b r b o l i z q u i e r d o
p r i v a t e C No do d e r e c h o : // r a z d e l s u b r b o l d e r e c h o
II M t o d o s
p u b l i c C N o d o ) 11 II c o n s t r u c t o r
546 J A V A : C U R S O D E P R O G R A M A C I N
// M t o d o s d e l r b o l b i n a r i o
public C A rb o lB in a rio () II // c o n s t r u c t o r
p u b lic vo id preorden(CNodo r)
I
if ( r 1- n u il )
(
// E s c r i b i r a q u l a s o p e r a c i o n e s a r e a l i z a r
// c o n e l n o d o r e f e r e n c i a d o r
p r e o r d e n ( r . i z q u i e r d o ) ; // s e v i s i t a e l s u b r b o l izquierdo
preorden( r.d e re ch o ): // s e v i s i t a e l s u b r b o l derecho
/////////////////////////////////////////////////////////////////
da; esto es, si la clave buscada es m enor que la clave del nodo en el que estam os,
pasam os al subrbol izquierdo de este nodo para continuar la bsqueda, y si es
mayor, pasam os al subrbol derecho. Este proceso contina hasta encontrar la
clave o hasta llegar a un subrbol vaco, rbol cuya raz tiene un valor nuil.
Clase CArbolBinB
La clase C A rbolB inB que vam os a im plem entar incluir un atributo protegido raz
para referenciar la raz del rbol y cuatro constantes pblicas relacionadas con los
posibles errores que se pueden d ar relativos a un nodo: C O RREC TO . NO _D A-
TO S, YA_EX1STE y N O _E X ISTE . El atributo raz valdr n u il cuando el rbol est
vaco. A sim ism o, incluye una clase interna, C N odo, que definir la estructura de
los nodos, y los m todos indicados en la tabla siguiente:
/////////////////////////////////////////////////////////////////
// C l a s e a b s t r a c t a : r b o l b i n a r i o de b s q u e d a . P a r a u t i l i z a r l o s
// mtodos p r o p o r c i o n a d o s p o r e s t a c l a s e , te ndrem os que c r e a r
// una s u b c l a s e de e l l a y r e d e f i n i r l o s m t o d o s :
// comparar, p r o c e s a r y v i s i t a r l n o r d e n .
II
public abstract class CArbolBinB
CA PTU LO 13: ESTR U C TU R A S D IN M ICA S 5 4 9
// A t r i b u t o s d e l r b o l b i n a r i o
p r o t e c t e d CNodo r a z = n u i l ; // r a z del rbol
// Nodo de un r b o l b i n a r i o
p r i v a t e c l a s s CNodo
// A t r i b u t o s
p riv a te Object datos; // referen cia a lo s datos
p r i v a t e CNodo i z q u i e r d o ; // r a z del su b r b o l i z q u i e r d o
p r i v a t e C No do d e r e c h o ; // r a z del su b r b o l derecho
// M t o d o s
p u b lic CNodo) I ) // c o n s t r u c t o r
// M t o d o s d e l r b o l b i n a r i o
publi c CArbolBi nB() I I // c o n s t r u c t o r
// El m t o d o s i g u i e n t e d e b e s e r r e d e f i n i d o en una s u b c l a s e p a r a
// q u e p e r m i t a c o m p a r a r d o s n o d o s d e l r b o l p o r e l a t r i b u t o
// q u e n e c e s i t e m o s en c a d a momento.
p u b li c a b s t r a c t i n t com p a ra r(0 b ject o b j l , O bject o b j 2);
// El m t o d o s i g u i e n t e d e b e s e r r e d e f i n i d o en una s u b c l a s e p a r a
// q u e p e r m i t a e s p e c i f i c a r l a s o p e r a c i o n e s q u e s e d e s e e n
// r e a l i z a r con e l n o do v i s i t a d o ,
p u b lic a b str a c t void p ro c e sa r(0 b je c t o b j):
// El m t o d o s i g u i e n t e d e b e s e r r e d e f i n i d o en una s u b c l a s e p a r a
// que i n v o q u e a " i n o r d e n " c o n l o s a r g u m e n t o s d e s e a d o s ,
p u b l i c a b s t r a c t v o i d v i s i t a r l n o r d e n ( );
CNo do a c t a 1 = n u i l ;
if ( nodoRaiz )
a c t u a l = r a z ; // p a r t i r d e l a r a z
el se
a c t u a l = r; // p a r t i r de un n o d o c u a l q u i e r a
i f ( a c t u a l != n u i l )
I
i n o r d e n ( a c t u a l . i z q u i e r d o , f a l s e ) : // v i s i t a r s u b r b o l i z q .
// P r o c e s a r l o s d a t o s d e l n o d o v i s i t a d o
p r o c e s a r ( a c t u a l . d a t o s );
i n o r d e n ( a c t u a l . d e r e c h o , f a l s e ) : II v i s i t a r s u b r b o l d c h o .
/////////////////////////////////////////////////////////////////
El parm etro obj se refiere al objeto de datos, que suponem os apuntado por
un nodo del rbol, al que deseam os acceder. Este m todo devuelve un valor nuil
si el objeto referenciado p o r o b j no se localiza en el rbol, o bien una referencia al
objeto de datos del nodo localizado.
P o r definicin de rbol de bsqueda, sabem os que sus nodos tienen que estar
ordenados utilizando com o clave alguno de los atributos de obj. Segn esto, el
m todo buscar se escribe aplicando estrictam ente esa definicin; esto es, si la cla
ve buscada es m enor que la clave del nodo en el que estam os, continuam os la
bsqueda en su subrbol izquierdo y si es m ayor, entonces continuam os la bs
queda en su subrbol derecho. E ste proceso contina hasta encontrar la clave, o
bien hasta llegar a un subrbol vaco (subrbol cu y a raz tiene un v alor n u il), en
CA PTU LO 13: ESTR U C TU R A S DINM ICA S 5 5 1
cuyo caso se inserta en ese lugar un nuevo nodo que alm acenar la referencia obj
al objeto de datos.
Para saber si una clave es igual, m enor o m ayor que otra invocarem os al m
todo com parar pasando com o argum entos los objetos de datos que contienen los
atributos que se desean com parar. C om o tales atributos, dependiendo de la aplica
cin, pueden ser bien de algn tipo num rico, o bien de tipo alfanum rico o alfa
btico, la im plem entacin de este m todo hay que posponerla al diseo de la
aplicacin que utilice esta clase, razn p o r la que com parar ha sido definido com o
un m todo abstracto. Para ello, com o verem os un poco m s adelante, derivarem os
una nueva clase de sta, y redefinirem os este m todo.
El proceso realizado por este m todo lo prim ero que hace es verificar si ya
hay un nodo con estos datos en el rbol (para realizar esta operacin se sigue el
552 JA V A : C U R SO DE PROGRAM A CIN
// C o m i e n z a l a b s q u e d a p a r a ve rificar si ya h a y un n o d o con
// e s t o s d a t o s en e l r b o l
w h i l e ( a c t u a l ! = n u l 1)
1
if ((nComp = co m p a r a r ( o b j , a c t u a l . d a t o s )) = = 0)
b r e a k : // s e e n c o n t r e l n o do
el se
I
ltim o = actual :
i f ( nComp < 0 ) // b u s c a r en e l subrbol izquierdo
actual = a ctu a l.izq u ie rd o :
else // b u s c a r en e l subrbol derecho
actual = actual.derecho;
En el ejem plo que m uestra la figura anterior, se desciende por el rbol hasta
encontrar el nodo a borrar (17). La variable actual representa la raz del subrbol
en el que contina la bsqueda; inicialm ente su valor es raz. La variable m arcado
apunta al nodo a borrar una vez localizado, el cual es sustituido por su sucesor a
la derecha (21) pasando su subrbol izquierdo (13) a serlo ahora del nodo m s a la
izquierda (18) en el subrbol derecho (21). C uando finalice la ejecucin del m to
do, el nodo que queda referenciado por m arcado ser enviado a la basura, ya que
m arcado es una variable local y desaparecer. El proceso detallado, se presenta a
continuacin y contem pla los casos m encionados:
R esum iendo, el m todo borrar prim ero localiza el nodo a borrar y lo marca
(queda referenciado por m arcado). D espus analiza si ste tiene descendientes y
cuntos; en funcin de esto obtiene su sucesor (queda referenciado p o r sucesor).
Finalm ente, rehace los enlaces dejando fuera el nodo m arcado para borrar. Dicho
nodo ser enviado a la basura en el instante en que finaliza el m todo borrar.
if ( actual != nu il ) // s e e n c o n t r e l nodo
I
marcado = a c t u a l ;
i f (( a c t u a l . i z q u i e r d o = n u i l && a c t u a l . d e r e c h o = n u i l ))
// s e t r a t a de un n o d o t e r m i n a l ( n o t i e n e d e s c e n d i e n t e s )
sucesor = n u l1 ;
e l s e i f ( a c t u a l . i z q u i e r d o = = n u i l ) // n o d o s i n s u b r b o l i z q .
sucesor = actual.derecho;
e l s e i f ( a c t u a l . d e r e c h o n u i l ) // n o d o s i n s u b r b o l d e r e c h o
sucesor = a c t u a l. iz q u ie rd o ;
else // n o do con s u b r b o l i z q u i e r d o y d e r e c h o
I
// R e f e r e n c i a d e l s u b r b o l d e r e c h o d e l nodo a b o r r a r
sucesor = actual = a c t u a l.derecho;
CA PTU LO 13: ESTRU C TU R A S DINM ICA S 5 5 5
// D e s c e n d e r a l n o d o ms a l a i z q u i e r d a en e l s u b r b o l
// d e r e c h o de e s t e n o d o ( e l de v a l o r ms p e q u e o ) y h a c e r
// que e l s u b r b o l i z q u i e r d o d e l n o d o a b o r r a r s e a a h o r a
// e l s u b r b o l i z q u i e r d o de e s t e n o do ,
w h i l e ( a c t u a l . i z q u i e r d o != n u i l )
actual = a c t u a l. izquierdo:
a c t u a l. izquierdo = m arcado.izquierdo:
I
// E l i m i n a r e l n o d o y r e h a c e r lo s enlaces
i f ( l t i m o != nul 1 )
I
if ( nAnteriorComp < 0 )
ltim o.izquierdo = sucesor:
el se
ltimo.derecho = sucesor:
I
el se
ra iz = sucesor:
r e t u r n m a r c a d o . d a t o s : ; // CORRECTO
// " m a r c a d o " s e r e n v i a d o a l a b a s u r a
I
e l s e // e l n odo b u s c a d o no e s t en e l rbol
r e t u r n n u i l ; // N 0 _ E X I S T E
i
Pensem os ahora en el proceso que deseam os realizar con cada nodo accedido.
En el ejem plo, sim plem ente nos lim itarem os a m ostrar los datos nom bre y nota.
556 JA V A : C U R S O D E P R O G R A M A C I N
Segn esto, el m todo p ro cesa r obtendr los datos nom bre y nota del objeto
C D atos pasado com o argum ento y los m ostrar.
Finalm ente, escribirem os el m todo visitarlnorden para que perm ita recorrer,
en nuestro caso, el rbol en su totalidad.
/////////////////////////////////////////////////////////////////
// C l a s e d e r i v a d a de l a c l a s e a b s t r a c t a C A r b o l B i n B . Redefine los
// m t o d o s : c o m p a r a r , p r o c e s a r y v i s i t a r l n o r d e n .
//
public class CArbolBinarioDeBusqueda extends CArbolBinB
I
// P e r m i t e c o m p a r a r d o s n o d o s d e l r b o l p o r e l atributo n o mbr e ,
p u b l i c i n t c o m p a r a r ( O b j e c t o b j l . O b j e c t o b j 2>
I
String s t r l = new S t r i n g ( ( ( C D a t o s ) o b j l ) . o b t e n e r N o m b r e ( ) ) :
String s t r 2 = new S t r i n g t ( ( C D a t o s ) o b j 2 ) . o b t e n e r N o m b r e ) ) :
return strl.com pareTo(str2):
// P e r m i t e m o s t r a r l o s d a t o s d e l nodo v i s i t a d o ,
p u b lic void p ro ce sa r(O b je c t obj)
I
S t r i n g nombre = new S t r i n g l ( ( C D a t o s ) o b j ) . o b t e n e r N o m b r e ( ) ) :
d o u b l e n o t a = ( ( C D a t o s ) o b j ) . o b t e n e r N o t a );
System .out.println(nom bre + " " + nota):
// V i s i t a r l o s n o d o s d e l r b o l ,
p u b lic void vi s i t a r I n o r d e n ( )
I
// S i e l s e g u n d o a r g u m e n t o e s t r u e , l a v i s i t a c o m i e n z a
// en l a r a z i n d e p e n d i e n t e m e n t e d e l p r i m e r a r g u m e n t o .
inorden(nul1 , t r u e ) ;
)
I
/////////////////////////////////////////////////////////////////
A hora puede com probar de una form a clara que los m todos com parar, p ro
cesar y visitarlnorden dependen del tipo de objetos que alm acenem os en el rbol
q ue construyam os. Por esta razn no pudieron ser im plem entados en la clase
C ArbolBinB, sino que hay que im plem entarlos para cada caso particular.
O bserve que com o los parm etros de los m todos com parar y p ro cesa r son
genricos, referencias de tipo O b je c t, deben convertirse explcitam ente en refe
rencias a la clase de objetos que realm ente representan; en nuestro caso a referen
cias a objetos de la clase CD atos, de lo contrario no tendrem os acceso a los
m todos explcitos de esta clase.
C A PTU LO 13: ESTR U C TU R A S D IN M ICA S 5 5 7
2. Solicitar parejas de datos nom bre y nota, a partir de las cuales construir los
objetos C D atos que aadirem os com o nodos en el arbolbb.
4. Finalmente, m ostrar los datos alm acenados en el rbol para com probar que to
do ha sucedido com o esperbam os.
//////////////////////////////////////////////////////////////////
// C r e a r un r b o l binario de b s q u e d a
II
p u b lic c l a s s Test
I
public static void m a in S t r in g [ ] args)
i
CArbolBinarioDeBusqueda a r b o l b b = new C A r b o l B i n a r i o D e B u s q u e d a ):
II L e e r d a t o s y a a d i r l o s al rbol
S t r i n g nombre:
double nota:
i n t i - 0 , c o d;
if (cod = = C A rb o lB i n a r i o D e B u s q u e d a . Y A _ E X I S T E )
I
// S i y a e x i s t e , d i s t i n g u i m o s d o s c a s o s :
// 1. n o t a n u e v a > = 0 : c a m b i a m o s l a n o t a
// 2. n o t a n u e v a < 0 : b o r r a m o s e l n o do
C D a t o s d a t o s = ( C D a t o s ) a r b o l b b . b u s c a r n e w C Da t o s t n o mb r e , n o t a ) ) :
i f ( n o t a > - 0)
datos.asignarN ota(nota);
el se
I
if ( a r b o lb b . b o r r a r n e w CDatostnombre, n o t a )) = nu il)
S y s t e m . o u t . p r i n t l n " n o b o r r a d o p o r q u e no e x i s t e ):
el se
S y s t e m . o u t . p r i n t l n " n o d o b o r r a d o " );
// M o s t r a r l o s n o d o s d e l r b o l
S y s t e m . o u t . p r i n t l n ( " \ n A r b o l : ):
r b o l b b . v i s i t a r i orden ( ) :
I
E sto puede realizarse fcilm ente distribuyendo los nodos, segn se leen,
equitativam ente a la izquierda y a la derecha de cada nodo. El proceso recursivo
que se indica a continuacin, es la m ejor form a de realizar esta distribucin. Para
un nm ero dado n de nodos y siendo n i (nodos a la izquierda) y n d (nodos a la de
recha) d o s enteros, el proceso es el siguiente:
C ada nodo del rbol consta de los siguientes m iem bros: d a to s, referencia al
subrbol izquierdo y referencia al subrbol derecho.
// A t r i b u t o s
p riv a t e Object datos: // r e f e r e n c i a a l o s d a t o s
p r i v a t e CNodo i z q u i e r d o : r a i z del s u b r b o l i z q u i e r d o
p r i v a t e CNodo d e r e c h o : // r a z d e l s u b r b o l d e r e c h o
// M t o d o s
p u b lic CNodo) I 1 // c o n s t r u c t o r
Clase CArboIBinE
La clase C ArboIB inE que vam os a im plem entar incluir un atributo protegido raz
para referenciar la raz del rbol. El atributo raz valdr n u il cuando el rbol est
vaco. A sim ism o, incluye la clase interna C N odo que define la estructura de los
nodos, y los m todos indicados en la tabla siguiente:
/////////////////////////////////////////////////////////////////
// C l a s e a b s t r a c t a : r b o l b i n a r i o p e r f e c t a m e n t e e q u i l i b r a d o .
// P a r a u t i l i z a r l o s m t o d o s p r o p o r c i o n a d o s p o r e s t a c l a s e .
C A P T U L O 13: ESTRU C TU R A S D IN M ICA S 5 6 1
II t e n d r e m o s que c r e a r una s u b c l a s e de e l l a y r e d e f i n i r l o s
// m t o d o s : l e e r D a t o s . c o m p a r a r , p r o c e s a r y v i s i t a r n o r d e n .
//
public abstract class CArbolBinE
I
// A t r i b u t o s d e l r b o l b i n a r i o
p r o t e c t e d C Nod o r a i z = n u i l ; // r a i z del rbol
// Nodo d e un r b o l b i n a r i o
p r i v a t e c l a s s CNodo
I
II A t r i b u t o s
p riv a t e Object datos: // r e f e r e n c i a a l o s d a t o s
p r i v a t e C Nod o i z q u i e r d o ; // r a z d e l s u b r b o l i z q u i e r d o
p r i v a t e CNodo d e r e c h o : // r a i z d e l s u b r b o l d e r e c h o
// M t o d o s
publi c CNodo) i I // c o n s t r u c t o r
// M t o d o s d e l r b o l b i n a r i o
public C A rb o lB inE O II // c o n s t r u c t o r
// El m t od o s i g u i e n t e d e b e s e r r e d e f i n i d o en l a s u b c l a s e p a r a
// q u e p e r m i t a l e e r l o s d a t o s q u e s e r n r e f e r e n c i a d o s p o r un
// n o d o d e l r b o l . D e v u e l v e e l o b j e t o d e d a t o s ,
p u b lic a b stra c t Object le e r D a t o s ) ;
// El m t od o s i g u i e n t e d e b e s e r r e d e f i n i d o en una s u b c l a s e p a r a
// q u e p e r m i t a c o m p a r a r d o s n o d o s d e l r b o l p o r e l a t r i b u t o
// q u e n e c e s i t e m o s en c a d a momento.
p u b lic a b stra c t in t comparar(Object o b jl. Object obj2):
II El m t od o s i g u i e n t e d e b e s e r r e d e f i n i d o en l a s u b c l a s e p a r a
// q u e p e r m i t a e s p e c i f i c a r l a s o p e r a c i o n e s que s e d e s e e n
// r e a l i z a r c o n el n o d o v i s i t a d o ,
pu b lic ab stract void procesarO bject obj):
// El m t o d o s i g u i e n t e d e b e s e r r e d e f i n i d o en l a s u b c l a s e para
// q u e i n v o q u e a " i n o r d e n " c o n l o s a r g u m e n t o s d e s e a d o s ,
p u b l i c a b s t r a c t v o i d v i s i t a r l n o r d e n ):
CNodo n o d o = n u l 1:
i n t n i = 0 . nd = 0:
if { n 0 )
r e t u r n n u l 1:
562 JA VA: C U R SO D E PROGRAM A CIN
el se
I
ni - n / 2: // n o d o s d e l s u b r b o l i z q u i e r d o
nd - n - n i - 1; // n o d o s d e l s u b r b o l d e r e c h o
n o d o - new C N o d o ( ) ;
nodo.datos = le e rD a t o sO ;
n o d o . i z q u i e r d o = c o n s t r u ' r A r b o l ( n i ):
nodo.derecho = c o n s t r u r A r b o l( n d ) :
r e t u r n nodo;
public v o id c o n s t r u r A r b o l E q u i 1i b r a d o ( i n t n)
I
raz - construirA rbol(n);
if ( actual != n u il && d a t o s [ 0 ] == nu il )
!
buscar(obj, a ctu a l.izq u ie rd o , datos, pos):
i f ( comparar! o bj. a c t u a l . d a t o s ) = = 0 )
if (pos[0]-- 0)
datos[0] = actual.datos: // n o d o e n c o n t r a d o
buscar(obj, actual.derecho, datos, pos):
I
if ( nodoRaiz )
a c t u a l = r a z : // p a r t i r de l a r a i z
el se
a c t u a l - r; // p a r t i r de un n o d o c u a l q u i e r a
i f ( a c t u a l != n u l 1 )
I
i n o r d e n ( a c t u a l . i z q u i e r d o , f a l s e ) ; // v i s i t a r s u b r b o l i z q .
// P r o c e s a r l o s d a t o s d e l n o d o v i s i t a d o
p r o c e s a r e a c t u a l . d a t o s );
i n o r d e n ( a c t u a l . d e r e c h o , f a l s e ) : // v i s i t a r s u b r b o l d e h o .
/////////////////////////////////////////////////////////////////
CNodo c o n s t r u r A r b o l ( i n t n)
Este m todo tiene un parm etro entero que se corresponde con el nm ero de
nodos del rbol y devuelve una referencia al nodo raz del rbol construido. En
realidad direm os que devuelve una referencia a cada subrbol construido lo que
perm ite realizar los enlaces entre nodos. O bserve que para cada nodo se ejecutan
las dos sentencias siguientes:
n o d o . i z q u i e r d o = c o n s t r u r A r b o l ( n i );
nodo.derecho - c o n s t r u i r A r b o l ( n d ) :
que asignan a los atributos izquierdo y derecho de cada nodo, las referencias de
sus subrboles izquierdo y derecho, respectivam ente.
tro a un objeto que encapsule los datos a buscar, y otra con un parm etro m s, la
posicin del nodo a partir de la cual se q uiere realizar la bsqueda. D e esta form a
se puede bu scar un nodo aunque su clave de bsqueda est repetida.
El m todo leerD atos obtendr los datos nom bre y n o ta , a p artir de ellos cons
truir un objeto C D atos y devolver el objeto construido p ara su insercin en el
rbol. Los m todos com parar, p ro cesa r y visitarlnorden se definen igual que en
la clase C A rbolBinarioD eBusqueda.
/////////////////////////////////////////////////////////////////
// C l a s e d e r i v a d a de l a c l a s e a b s t r a c t a C A r b o I B i n E . R e d e f i n e los
// m t o d o s : l e e r D a t o s . c o m p a r a r , p r o c e s a r y v i s i t a r I n o r d e n .
//
public c la ss C A rb o lB in a rio E q u i1ibrado extends CArboIBinE
I
// L e e r l o s d a t o s q u e s e r n referenciados p o r un n o d o d e l rbol,
p u b lic Object lee rD atost)
I
S t r i n g nombre:
double nota;
S y s t e m . o u t . p r i n t ( " n o m b r e : " ) ; no mb r e = L e e r . d a t o O :
System .out.printf"nota: "); n o t a = L e e r . d a t o D o u b l e ( );
r e t u r n ( O b j e c t M n e w C D a t o s ( nombre. n o t a ) ) :
)
// P e r m i t e c o m p a r a r d o s n o d o s d e l r b o l p o r e l atributo no mbre,
p u b lic i n t comparar(Object o b j l. Object obj2)
I
String strl = new S t r i n g ( ( ( C D a t o s ) o b j 1 ) . o b t e n e r N o m b r e ) ) :
C A PTU LO 13: ESTRU C TU R A S D IN M ICA S 5 6 5
String s t r 2 = new S t r i n g ( ( C D a t o s ) o b j 2 ) . o b t e n e r N o m b r e ) ) :
return stri.com pareTo(str2):
I
// P e r m i t e m o s t r a r l o s d a t o s d e l n o do v i s i t a d o ,
p u b lic void p ro ce sa r(O b je c t obj)
I
S t r i n g nombre = new S t r i n g t ( ( C D a t o s ) o b j ) . o b t e n e r N o m b r e ) ) :
d o u b l e n o t a = ( ( C D a t o s ) o b j ) . o b t e n e r N o t a ( ):
System .out.println(nom bre + " " + nota):
I
// V i s i t a r l o s n o d o s d e l r b o l ,
pu b lic void v i s i t a r l n o r d e n )
I
// S i e l s e g u n d o a r g u m e n t o e s t r u e . l a v i s i t a c o m i e n z a
// en l a r a i z i n d e p e n d i e n t e m e n t e d e l p r i m e r a r g u m e n t o .
inorden(nul1 , t r u e ) :
/////////////////////////////////////////////////////////////////
Finalm ente, escribirem os una aplicacin Test que. utilizando la clase CAr-
bolB inarioE quilibrado, cree un objeto arbolbe correspondiente a un rbol binario
de bsqueda en el que cada nodo haga referencia a un objeto CDatos. De forma
resum ida la aplicacin T est:
//////////////////////////////////////////////////////////////////
// C r e a r un r b o l binario perfectamente e q u i l i b r a d o de n nodos
//
pub'l i c c l a s s Test
I
public s t a t ic void m a i n t S t r i n g n args)
I
C A r b o l B i n a r i o E q u i l i b r a d o a r b o l b e = new C A r b o l B i n a r i o E q u i 1i b r a d o ( ):
566 JA V A : C U R S O D E P R O G R A M A C I N
i n t nmeroDeNodos;
S y s t e m . o u t . p r i n t ( " N m e r o de n o d o s : ):
nmeroDeNodos = L e e r . d a t o l n t ) :
rbol b e .c o n s t r u r A r b o l E q u i 1i brado nmeroDeNodos):
S y s t e m . o u t . p r i n t l n );
// B u s c a r d a t o s
S t r i n g nombre:
S y s t e m . o u t . p r i n t " n o m b r e a b u s c a r : " ) : nombre = L e e r . d a t o O :
CDatos obj = ( C D a t o s ) a r b o l b e . b u s c a r ( n e w CDato sno m bre, 0 ) ) :
i f ( obj != n u i l )
S y s t e m . o u t . p r in t ln o b j .obtenerNombre) + " +
o bj.obten erN ota));
el se
S y s t e m . o u t . p r i n t n i " La b s q u e d a f a l l " ) ;
// M o s t r a r l o s n o d o s d e l r b o l
System .out.printlni"\n A rb o l:"):
a r b o l b e . v i s i t a r l n o r d e n );
Las clases H a sh ... proporcionan conjuntos de datos que no perm iten duplica
dos y que utilizan algoritm os hash para el alm acenam iento de los datos y para su
posterior acceso.
EJERCICIOS RESUELTOS
1. R ealizar una aplicacin que perm ita crear una lista lineal de elem entos de cual
quier tipo clasificados ascendentem ente. La lista vendr definida por un objeto de
una clase abstracta que denom inarem os C L istaU nealSE O (G a s e L ista Lineal
Sim plem ente E nlazada O rdenada) y cada elem ento de la lista ser un objeto de la
clase siguiente:
private c la ss CElemento
I
// A t r i b u t o s
p r iv a t e Object datos;
p r i v a t e CElemento s i g u i e n t e : // s i g u i e n t e elemento
// M t o d o s
// . . .
1
El atributo elem A ctual har referencia al elem ento accedido y elem A nterior al
anterior al actual, excepto cuando el elem ento actual sea el prim ero, en cuyo caso
am bas referencias sealarn a ese elem ento. T am bin incluir los m todos:
T odos los m todos expuestos, excepto listaV acfa, deben actualizar las refe
rencias elem A ctual y elem Anterior.
568 J A V A : C U R S O D E P R O G R A M A C I N
El m todo com parar debe ser redefinido p o r el usuario en una subclase para
especificar el tipo de com paracin que se desea realizar con dos elem entos de la
lista. Segn esto, debe devolver un entero indicando el resultado de la com para
cin ( - 1 , 0 0 1 si o b jI< o b j2 , o b jl ==obj2, o o b jl> o b j2 , respectivam ente). Este
m todo es invocado directam ente por el m todo bu sca r e indirectam ente por los
m todos a adir y borrar, que invocan a buscar.
El m todo listaV aca devuelve true si la lista est vaca y false en caso con
trario.
El m todo borrar borra un elem ento de la lista. T iene un parm etro para al
m acenar una referencia de tipo O b je c t a los datos que perm itirn localizar en la
lista el elem ento que se desea borrar. D evuelve una referencia al rea de datos del
elem ento borrado, o bien nu il si la lista est vaca.
El m todo obtenerP rim ero devuelve una referencia al rea de datos del ele
m ento prim ero, o bien n u il si la lista est vaca.
//////////////////////////////////////////////////////////////////
// C l a s e a b s t r a c t a C L i s t a L i n e a l S E O :
// L i s t a l i n e a l simplemente enlazada ordenada ascendentemente.
//
public abstract class CListaLinealSEO
I
// p: r e f e r e n c i a a l p r i m e r e l e m e n t o de la lista,
p r i v a t e CElemento p = n u i l : // e l e m e n t o de c a b e c e r a
p r i v a t e CElemento e l e m A n t e r i o r = n u i l : // elemento a n t e r i o r
p r i v a t e CElemento ele mActual = nuil: // elemento actual
p u b l i c C L i s t a L i n e a l S E O ) {) // c o n s t r u c t o r
// El m t od o s i g u i e n t e d e b e s e r r e d e f i n i d o en una s u b c l a s e p a r a
// q u e p e r m i t a c o m p a r a r d o s e l e m e n t o s de l a l i s t a p o r el a t r i b u t o
// q u e n e c e s i t e m o s en c a d a momento.
pu b lic a b s t r a c t in t comparar(Object o b j l. Object obj2):
// S i l a l i s t a r e f e r e n c i a d a p o r p e s t v a c a , r e t o r n a r ,
i f ( 1i s t a V a c a () ) r e t u r n n u i l :
// S i l a l i s t a no e s t v a c a , e n c o n t r a r e l e l e m e n t o .
e l e m A n t e r i o r = p;
e l e m A c t u a l = p;
// P o s i c i o n a r s e en e l e l e m e n t o b u s c a d o .
w h i l e ( e l e m A c t u a l ! = n u i l && c o m p a r a r ( o b j . e l e m A c t u a l . d a t o s ) > 0)
I
elem Anterior = elemActual:
elemActual = e l e m A c t u a l . s i g u i e n t e :
I
if ( ele m Actual != n u i l )
return elem Actual.datos;
el se
return n u l1 :
1
570 JA V A : C U R S O D E P R O G R A M A C I N
// S i l a l i s t a no e s t v a c i a , e n c o n t r a r e l p u n t o d e i n s e r c i n
b u s c a r ( o b j ) ; // e s t a b l e c e l o s v a l o r e s d e e l e m A n t e r i o r y elemActual
// Do s c a s o s :
// 1) I n s e r t a r al p r i n c i p i o d e l a l i s t a
// 2 ) I n s e r t a r d e s p u s d e l a n t e r i o r ( i n c l u y e i n s e r t a r a l f i n a l )
i f ( e l e m A n t e r i o r = = e l e m A c t u a l ) // i n s e r t a r a l p r i n c i p i o
[
q . s i g u i e n t e = p;
p = q ; // c a b e c e r a
e le m A n t e r i o r = ele mActual = p; // a c t u a l i z a r referencias
I
else // i n s e r t a r d e s p u s d e l anterior
I
q . s ig u i e n t e = elemActual;
e l e m A n t e r i o r . s i g u i e n t e = q:
e l e m A c t u a l = q ; // a c t u a l i z a r referencia
// S i l a l i s t a no e s t v a c i a , b u s c a r e l e l e m e n t o .
b u s c a r ( o b j ) ; // e s t a b l e c e l o s v a l o r e s de e l e m A n t e r i o r y elemActual
// D o s c a s o s :
// 1) B o r r a r e l p r i m e r e l e m e n t o de l a l i s t a
// 2 ) B o r r a r e l s i g u i e n t e a e l e m A n t e r i o r ( e l e m A c t u a l )
i f ( e l e m A c t u a l = = p ) // 1)
p = p . s i g u i e n t e : // c a b e c e r a
e l s e // 2)
ele m A nte rior.sig u ie n te = elem Actual.s ig u ie n t e ;
CA PTU LO 13: ESTRU C TU R A S DINM ICA S 5 7 1
p u b lic Object o b t e n e r S ig u i e n t e )
I
// D e v o l v e r una r e f e r e n c i a a l o s d a t o s d e l e l e m e n t o s i g u i e n t e
II al a c t u a l y h a c e r que s t e s e a e l a c t u a l .
// S i l a l i s t a e s t v a c i a , d e v o l v e r n u i l ,
i f ( l is t a V a c ia ) ) return n u il;
// A v a n z a r un e l e m e n t o
e lem Anterior = elemActual;
ele m Actual = e l e m A c t u a l . s i g u i e n t e ;
i f ( elemActual != n u l 1 )
return elem Actual.datos:
el se
r e t u r n n u l 1:
//////////////////////////////////////////////////////////////////
nombre = nom;
return nombre:
public void a s i g n a r N o t a ( d o u b l e n)
I
n o t a = n;
p u b li c double o b te n e rN o ta ()
I
return nota;
Finalm ente, realizam os una aplicacin que utilizando la clase anterior cree
una lista lineal sim plem ente enlazada y ordenada, de objetos CDatos:
I II I //// // // //////////////////////////////////////////////////////
// C r e a r una l i s t a l i n e a l s i m p l e m e n t e e n l a z a d a
II
public class Test
I
public static void m o strarLista(C ListaLin ealSEO rden ada Ise)
I
II M o s t r a r ^ t o d o s l o s e l e m e n t o s d e l a l i s t a
C D a t o s o b j = ( C D a t o s ) l s e . o b t e n e r P r i m e r o ( ):
C A P T U L O 13: ESTRUCTURAS DINM ICA S 5 7 3
i n t i - 1:
whi 1 e ( o b j ! - n u l 1)
I
System .out.p rintln(i++ + + obj.obtenerNom bre() + " " +
o b j.o b t e n e rN o ta ()):
obj - ( C D a t o s ) l s e . o b t e n e r S i g u i e n t e O ;
// L e e r d a t o s y a a d i r l o s a l a l i s t a
CDatos obj;
S t r i n g n o mbr e :
double nota:
i n t i - 0:
S y s t e m . o u t .p rin t ln ( In tr o d u c ir datos. F i n a li z a r con C t r l + Z . ):
S y s t e m . o u t . p r i n t " n o m b r e : ):
w h i l e ((nombre - L e e r . d a t o O ) ! - n u i l )
I
System .out.print"nota: "):
n o t a - L e e r , d a t o D o u b l e ( ):
lse.aa dir(n ew CDatos(nombre. n o ta )):
S y s t e m . o u t . p r i n t " n o m b r e del alumno a b o r r a r : "):
1
S y s t e m . o u t . p r i n t l n( \ n " ):
// B o r r a r un e l e m e n t o d e t e r m i n a d o
S y s t e m . o u t . p r i n t ( " n o m b r e de l alumno a b o r r a r : " ) :
n o mb r e - L e e r . d a t o O :
obj - ( C D a t o s ) l s e . b o r r a r ( n e w CDatos(nom bre. 0 ) ) ;
i f (obj == n u i l )
S y s t e m . o u t . p r i n t l n ( " E r r o r : e l e m e n t o no b o r r a d o ):
// M o d i f i c a r un e l e m e n t o
S y s t e m . o u t . p r i n t ( " n o m b r e de l alumno a m o d i f i c a r : " ) :
n o mb r e - L e e r . d a t o O :
obj - (C D ato s)1se .b u scar(n e w CDatos(nombre. 0 ) ) :
S y s t e m . o u t . p r i n t l n ( " N o m b r e : " + obj .o b te n e rN o m b re O +
n o t a : " + o b j . o b t e n e r N o t a O ):
S y s t e m . o u t . p r i n t ( " n o t a nueva: ):
n o t a - L e e r , d a t o D o u b l e ( ):
obj.asignarNota(nota):
// M o s t r a r t o d o s
S y ste m .o u t.p rin tln ("L ista :"):
m o s t r a r L i s t a ( 1s e ) :
574 J A V A : C U R S O D E P R O G R A M A C I N
2. E scribir una aplicacin para que utilizando una pila, sim ule una calculadora capaz
de realizar las operaciones de * y /. L a m ayora de las calculadoras aceptan la
notacin infija y unas pocas la notacin p ostfija. E n estas ltim as, para sum ar 10
y 20 introduciram os prim ero 10, despus 20 y p o r ltim o el +. C uando se intro
ducen los operandos, se colocan en una pila y cuando se introduce el operador, se
sacan dos operandos de la pila, se calcula el resultado y se introduce en la pila. La
ventaja de la notacin postfija es que expresiones com plejas pueden evaluarse f
cilm ente sin m ucho cdigo. La calculadora del ejem plo propuesto utilizar la no
tacin postfija.
Para realizar esta aplicacin utilizarem os las clases C Pila derivada de CLis
taC ircularSE, C D atos y C Leer. C om o estas clases ya han sido im plem entadas, en
este ejercicio nos lim itarem os a u tilizar los recursos que proporcionan.
//////////////////////////////////////////////////////////////////
// C a l c u l a d o r a u t i l i z a n d o una p i l a . E s t a a p l i c a c i n , adems de l a s
// c l a s e s n e c e s a r i a s de l a b i b l i o t e c a de J a v a , u t i l i z a l a s c l a s e s :
// C P i l a d e r i v a d a de C L i s t a C i r c u l a r S E . C D a t o s y C L e e r .
//
public class Test
I
private static C P i l a p i l a = new C P i l a O : // p i l a de o p e r a n d o s
private static d o u b l e f ] operando - (0. 0 ) : // o p e r a n d o 0 y 1
S y s t e m . o u t . p r i n t l n ( " F o r m a de i n t r o d u c i r l o s d a t o s : " ) ;
S y s te m .o u t.p r i n t l n ( " > p r i m e r operando 1 [ E n t r a r ] " ) ;
S y s t e m . o u t . p r i n t l n ( " > s e g u n d o operando 2 [ E n t r a r ] " ) ;
S y s t e m . o u t . p r i n t l n ( > o p e r a d o r [ E n t r a r ] \ n " )
Sy ste m .o u t.p rin tln "P a ra s a l i r pulse q \n ");
do
I
try
(
S y s t e m . o u t . p r i n t ( " > );
oper * L e e r .d a t o O ; // l e e r un o p e r a n d o o un o p e r a d o r
switch ( o p e r.c h a r A t (O )) // v e r i f i c a r e l p r i m e r c a r c t e r
1
case
o b t e n e r O p e r a n d o s ( );
S y s t e m . o u t . p r i n t l n ( o p e r a n d o [ 0 ] + o p e r a n d o f l ] );
p i 1 a . m e t e r E n P i 1 a ( new D o u b l e ( o p e r a n d o [ 0 ] + o p e r a n d o [ l ] ) ) ;
break;
case - ' :
o b t e n e r O p e r a n d o s ( ):
System .out.println(operando[0] - o p e ra n d o [l]);
p i 1a .m e t e r E n P i 1a(new D o u b l e ( o p e r a n d o [ 0 ] - o p e r a n d o [ l ] ) ) :
break;
case
o b t e n e r O p e r a n d o s );
System .out.p rintln(op erand o[0] * operando[1]):
p ila .m e te rE n P ila n e w D o u b le (o p e ra n d o [0 ]*o p e ra n d o [l]));
break;
case
o b t e n e r O p e r a n d o s ):
i f ( o p e r a n d o f l ] = = 0)
I
System .out.println"\nError: d ivisin por c e r o ") ;
break;
I
System .out.println(operando[0] / operandofl]);
p i 1 a . m e t e r E n P i 1 a (new Do ub l e ( o p e r a n d o [ 0 ] / o p e r a n d o [ l ] ) ) ;
break;
case q :
// s a l i r
break;
default : // e s un o p e r a n d o
p i l a . m e t e r E n P i l a n e w D o u b l e ( o p e r ) );
c a t c h ( N u m b e r F o r m a t E x c e p t i o n e)
1
S y s t e m . o u t . p r i n t ( " E r r o r : d a t o no e s vlido. Teclee o tr o : ");
I
576 JA VA : C U R SO D E PROGRAM A CIN
c a t c h l N u l 1P o in t e rE x c e p tio n e)
I
S y s t e m . o u t . p r i n t t " E r r o r : t e c l e e " + ( 2 - p i 1a . t a m a o t ) ) +
" operando(s) ms");
1
I
w hile (oper.charAt(O) != q );
3. Escribir una aplicacin que perm ita calcular la frecuencia con la que aparecen las
palabras en un fichero de texto. L a form a de invocar al program a ser:
donde fich ero _ d e_ texto es el nom bre del fichero de texto del cual deseam os obte
ner la estadstica.
nombre = 1
obtener = 1
palabras = 1
p er mi t a = 1
programa = 1
que = 2
queremos = 1
ser = 1
e stadstica = 1
texto = 2
un = 1
una = 1
Total palabras: 44
C A PTU LO 13: ESTRU C TU R A S DINM ICA S 5 7 7
Segn lo expuesto, cada nodo del rbol tendr que hacer referencia a un rea
de datos que incluya tanto la palabra com o el nm ero de veces que apareci en el
texto. Estos datos sern los atributos de una clase C D atos definida as:
// M t o d o s
public CDatosO I) // c o n s t r u c t o r s i n parmetros
public in t obtenerContador()
(
return contador:
578 JA V A : C U R S O D E P R O G R A M A C I N
/////////////////////////////////////////////////////////////////
// C l a s e d e r i v a d a d e l a c l a s e a b s t r a c t a C A r b o l B i n B . Redefine los
// m t o d o s : c o m p a r a r , p r o c e s a r y v i s i t a r l n o r d e n .
//
public c la ss CArbolBinarioDeBusqueda extends CArbolBinB
I
public int t o t a l P a l a b r a s = 0:
public int t o t a l P a l a b r a s D i f e r e n t e s = 0:
// P e r m i t e c o m p a r a r d o s n o d o s d e l r b o l p o r e l atributo
// nombre.
p u b l i c i n t co m p ara rtO b je ct o b j l . O b je ct o b j 2)
I
String s t r l = new S t r i n g t ( ( C D a t o s ) o b j 1 ) . o b t e n e r P a l a b r a < ) ) ;
String s t r 2 = new S t r i n g ( ( C D a t o s ) o b j 2 ) . o b t e n e r P a l a b r a ( ) ) :
return s t r l . c o m p a r e T o ( s t r 2 );
// P e r m i t e m o s t r a r l o s d a t o s d e l nodo v i s i t a d o ,
p u b lic void p ro ce sa r!O b je c t obj)
I
S t r i n g p a l a b r a = new S t r i n g ( ( ( C D a t o s ) o b j ) . o b t e n e r P a l a b r a ( ) ) ;
i n t c o n t a d o r = ( ( C D a t o s ) o b j ) . o b t e n e r C o n t a d o r );
S y s t e m . o u t . p r in t n ( p a l abra + " = " + co n ta d o r):
t o t a l Pal a b r a s + = c o n t a d o r ;
total PalabrasDi ferentes++;
I I V i s i t a r l o s nodos del r b o l,
p u b l i c v o i d vi s i t a r I n o r d e n ( )
I
// S i e l s e g u n d o a r g u m e n t o e s t r u e . l a v i s i t a c o m i e n z a
// en l a r a z i n d e p e n d i e n t e m e n t e d e l p r i m e r a r g u m e n t o ,
inordentnul1 . t r u e ) :
/////////////////////////////////////////////////////////////////
renciado por el nodo visitado, contabiliza el nm ero total de palabras del texto
procesado y el nm ero total de palabras diferentes (esto es, com o si todas hubie
ran aparecido slo una vez en el texto). El resto de los m todos ya fueron explica
dos al h ablar de rboles binarios de bsqueda.
El m todo leerFichero abre el fichero y lo lee lnea a lnea. C ada lnea leda
ser pasada com o argum ento al m todo palabras para su descom posicin en pala
bras con el fin de aadirlas al rbol binario de bsqueda que ha sido declarado
com o un atributo de la clase aplicacin. Para descom poner una lnea en palabras
utilizarem os los recursos proporcionados por la clase S trin g T o k e n iz e r del pa
quete til de Java (esta clase fue explicada en el captulo 7).
import j a v a . i o . * :
import j a v a . u t i 1 . * ;
//////////////////////////////////////////////////////////////////
// U t i l i z a r un r b o l de b s q u e d a p a r a o b t e n e r l a f r e c u e n c i a c o n l a
// q u e a p a r e c e n l a s p a l a b r a s en un f i c h e r o d e t e x t o .
// E s t a a p l i c a c i n , a d ems de l a s c l a s e s n e c e s a r i a s de l a
// b i b l i o t e c a de J a v a , u t i l i z a l a s c l a s e s : C A r b o l B i n a r i o D e B u s q u e d a
// d e r i v a d a de C A r b o l B i n B y C D a t o s .
//
public class Palabras
I
p riv a te s t a t ic CArbolBinarioDeBusqueda arbolbb -
new C A r b o l B i n a r i o D e B u s q u e d a ( ):
S t r in g palabra:
CDatos o b j :
580 JA V A : C U R S O D E P R O G R A M A C I N
try
I
// A s e g u r a r s e de q u e e l f i c h e r o , e x i s t e y s e p u e d e l e e r
i f ( f i c h F u e n t e . e x i s t s t ) || ! f i c h F u e n t e . i s F i 1e ( ) )
1
System .err.printlnt"N o existe el fichero " + nombrefich)
return;
I
if ( f i c h F u e n t e . c a n R e a d t ))
I
S y s t e m . e r r . p r i n t l n t " E l f i c h e r o " + nombrefich +
" no s e p u e d e l e e r " ) ;
return;
// A b r i r un f l u j o de e n t r a d a d e s d e e l f i c h e r o f u e n t e
F i l e l n p u t S t r e a m f i s = new F i 1e l n p u t S t r e a m t f i c h F u e n t e )
I n p u t S t r e a m R e a d e r i s r = new I n p u t S t r e a m R e a d e r t f i s );
f l u j o E = new B u f f e r e d R e a d e r ( i s r );
// B u s c a r c a d e n a en e l fichero fuente
S trin g linea;
catch(IOException e)
I
S ystem .out. p rin t l n ( "E rro r: + e .getM essage());
CA PTU LO 13: ESTR U C TU R A S DINM ICA S 5 8 1
finally
I
// C e r r a r el flujo
try
I
if (flujoE != n u i l ) f l u j o E . c l o s e t ):
)
c a t c h ( I O E x c e p t i o n e)
I
System .out.p rintln"Error: + e . t o S t r i n g ( ));
I
I
I
if ( a r g s . l e n g t h < 1)
System .err.println("Sintaxis: j a v a P a l a b r a s < f i c h e r o _ d e _ t e x t o > " ):
el se
1e e r F i c h e r o ( a r g s [ 0 ] ):
EJERCICIOS PROPUESTOS
1. Se quiere escribir un program a para m anipular ecuaciones algebraicas o polin-
m icas dependientes de las variables x e y . P or ejem plo:
C ada trm ino del polinom io ser representado por un objeto de una clase
CTerm ino y cada polinom io por un objeto que sea una lista lineal sim plem ente
enlazada ordenada, de elem entos CTermino.
2. En un fichero tenem os alm acenados los nom bres y las notas m edias de los alum
nos de un determ inado curso. L a estructura de cada uno de los registros del fiche
ro se corresponde con los atributos de una clase com o la siguiente:
public c la ss CRegistro
i
// A t r i b u t o s
p r i v a t e S t r i n g nombre:
p r i v a t e f l o a t nota:
// M t o d o s
// . ..
1
Q uerem os leer los datos de este fichero para construir una estructura de datos
en m em oria que se ajuste a un rbol binario d e bsqueda perfectam ente equili
brado. Para ello, es aconsejable ordenar el fichero antes de crear el rbol. Esto fa
cilita la creacin del rbol binario con los dos requisitos im puestos: que sea de
bsqueda y perfectam ente equilibrado. En este ejercicio supondrem os que parti
m os de un fichero ordenado. M s adelante, en el captulo de A lgoritm os" vere
mos cm o se ordena un fichero.
c r e a r el su b r b o l i z q u i e r d o
l e e r un r e g i s t r o d e l f i c h e r o y a s i g n r s e l o al nodo a c t u a l
c r e a r el sub rb o l derecho
V em os que prim ero hay que construir el subrbol izquierdo, despus la raz y
p o r ltim o el subrbol derecho. C om o las claves contenidas en el fichero estn o r
denadas, la clave m enor se alm acenar en el nodo m s a la izquierda y la m ayor
en el nodo m s a la derecha, dando as lugar a un rbol de bsqueda, adem s de
perfectam ente equilibrado.
C A PTU LO 13: ESTR U C TU R A S DINM ICA S 5 8 3
3. El filtro so rt lee lneas de texto del fichero estndar de entrada y las presenta en
orden alfabtico en el fichero estndar de salida. El ejem plo siguiente m uestra la
form a de u tilizar sort:
sort
l o que puede h a c e r s e
en c u a l q u i e r momento
no s e h a r
en n i n g n momento.
(eof)
en c u a l q u i e r momento
en n i n g n momento,
l o q u e puede h a c e r s e
no s e h a r
Se desea escribir un program a de nom bre O rdenar, que acte com o el filtro
sort. Para o rdenar las distintas lneas vam os a ir insertndolas en un rbol binario
de bsqueda, de tal form a que al recorrerlo podam os presentar las lneas en orden
alfabtico. El program a se ejecutar utilizando la siguiente sintaxis:
Si se especifica el atributo opcional -r, las lneas del fichero sern presentadas
en orden alfabtico descendente; si no se especifica, entonces se presentarn en
orden alfabtico ascendente.
CA PTU LO 14
F.J.Cebalos/RA-MA
ALGORITMOS
En este captulo vam os a exponer cm o resolver problem as m uy com unes en pro
gram acin. El prim ero que nos vam os a plantear es la recursin; se trata de un
problem a cuyo planteam iento form a parte de su solucin. El segundo problem a
que vam os a ab ordar es la ordenacin de objetos en general; la ordenacin es tan
com n que no necesita explicacin; algo tan cotidiano com o una gua telefnica,
es un ejem plo de una lista clasificada, El localizar un determ inado telfono exige
una bsqueda p o r algn m todo; el problem a de bsqueda ser el ltim o que re
solverem os.
RECURSIVIDAD
Se dice que un proceso es recursivo si form a parte de s m ism o, o sea que se defi
ne en funcin de s m ism o. E jem plos tpicos de recursin los podem os encontrar
frecuentem ente en problem as m atem ticos, en estructuras de datos y en m uchos
otros problem as.
que alm acenarlo para recuperarlo cuando se acabe la nueva ejecucin del proceso
y haya que reanudar la antigua.
U n ejem plo es el m todo de A ckerm an, <4, el cual est definido para todos los
valores enteros no negativos m y n de la form a siguiente:
A ( O . n ) - n+1
A(m.O) = A ( m - 1 . 1 ) ( m > 0)
A(m.n) = A (m -1 , A ( m , n - 1 )) ( m . n > 0)
<mtodo A ( m . n ) >
I F (m e s i g u a l a 0 ) THEN
d e v o l v e r como r e s u l t a d o n+1
E LSE I F (n es ig u a l a 0) THEN
d e v o l v e r como r e s u l t a d o A(m -l.l)
ELSE
d e v o l v e r como r e s u l t a d o A(m -1.A(m .n-l))
ENDIF
END K m t o d o A ( m , n ) >
public c la ss CRecursion
I
// M t o d o r e c u r s i v o d e A c k e r m a n :
// A ( O . n ) = n+1
// A(m.O) = A ( m - l . l ) (m > 0)
// A(m.n) = A ( m - l , A ( m , n - l )) (m.n > 0)
p u b l i c s t a t i c i n t A c k e r m a n ( i n t m. i n t n)
I
if (m = 0)
return n+1;
else i f ( n = = 0)
return A c k e r i n a n t m - 1. 1):
else
return Ackerman(m-1. Ackerman(m,n-1));
La m ejor form a de hacer esto es utilizar una pila, con el fin de alm acenar los
valores m y n cada vez que se invoque el m todo para una nueva ejecucin y to
m ar estos valores de la cim a de la pila, cuando esta nueva ejecucin finalice, con
el fin de reanudar la antigua.
< m t o d o A ( m , n ) >
U t i l i z a r una p i l a p a r a a l m a c e n a r l o s v a l o r e s d e m y n
I n i c i a r la p i l a c o n l o s v a l o r e s m.n
DO
Tomar l o s d a t o s d e l a p a r t e s u p e r i o r d e la p i l a
F (m e s i g u a l a 0 ) THEN
Amn = n+1
I F ( p i l a no v a c i a )
s a c a r d e l a p i l a l o s v a l o r e s : m, n
m e t e r en l a p i l a l o s v a l o r e s : m. Amn
ELSE
d e v o l v e r como r e s u l t a d o Amn
ENDIF
E LSE I F (n e s i g u a l a 0 ) THEN
meter en la p i l a l o s v a l o r e s : m-1,1
ELSE
m e t e r en l a p i l a l o s v a l o r e s : m - 1, Amn
m e t e r en la p i l a l o s v a l o r e s : m.n-1
ENDIF
WHILE ( t r u e )
END S m t o d o A ( m . n ) >
588 JA V A : C U R S O D E P R O G R A M A C I N
// M t o d o s
public COatostint im, int in) // c o n s t r u c t o r con p a r m e t r o s
I
m = im:
n - in;
I
A B C
l 1
I ]
< m t o d o m o v e r ( n _ d i s c o s . A. B. C)>
IF (r_discos es m a y o r q u e 0) THEN
m o v e r ( n _ d i s c o s - I . A. C. B)
m o v e r ( d i s c o _ n . A. B, C)
m o v e r ( n _ d i s e o s - 1 . B. A. C)
ENDIF
E N D < m t o d o mo ve r>
public c la ss C Ha n o i
I
private static i n t m o v i m i e n t o s = 0:
Nmero de d i s c o s : 3
mover d i s c o de A a C
mover d i s c o de A a B
mover d i s c o de C a B
mover d i s c o de A a C
mover d i s c o de B a A
mover d i s c o de B a C
mover d i s e o de A a C
ORDENACIN DE DATOS
Uno de los procedim ientos m s com unes y tiles en el procesam iento de datos, es
la ordenacin de los m ism os. Se considera ordenar al proceso de reorganizar un
conjunto dado de objetos en una secuencia determ inada. El objetivo de este pro
ceso generalm ente es facilitar la bsqueda de uno o m s elem entos pertenecientes
a un conjunto. Son ejem plos de datos ordenados las listas de los alum nos m atri
culados en una cierta asignatura, las listas del censo, los ndices alfabticos de los
libros, las guas telefnicas, etc. Esto quiere decir que m uchos problem as estn
relacionados de alguna form a con el proceso de ordenacin. Es p o r lo que la or
denacin es un problem a im portante a considerar.
La ordenacin, tanto num rica com o alfanum rica, sigue las m ism as reglas
que em pleam os nosotros en la vida norm al. Esto es, un dato num rico es m ayor
que otro cuando su valor es m s grande, y una cadena de caracteres es m ayor que
otra cuando est despus p o r orden alfabtico.
592 J A V A : C U R S O D E P R O G R A M A C I N
Mtodo de la burbuja
Hay m uchas form as de ordenar datos, pero una de las m s conocidas es la ordena
cin por el m todo de la burbuja.
2. R epetim os el punto 1, ahora para los n-1 prim eros elem entos de la lista. Con
esto conseguim os llevar el valor m ayor de stos a la posicin n-1.
3. R epetim os el punto 1, ahora para los n-2 prim eros elem entos de la lista y as
sucesivam ente.
EN D I F
i - i+1
E N DDO
n - n-1
ENDDO
END <clasificar>
La clase siguiente incluye el m todo o rdenar que utiliza este algoritm o para
ordenar una m atriz de tipo d o u b le o de tipo S trin g .
/////////////////////////////////////////////////////////////////
// O r d e n a c i n p o r e l m t o d o de l a b u r b u j a . E l m t od o " o r d e n a r " se
// s o b r e c a r g a d o s v e c e s : una p a r a o r d e n a r una m a t r i z de t i p o
// d o u b l e y o t r a p a r a o r d e n a r un a m a t r i z de t i p o S t r i n g .
//
public c la ss CMatriz
(
public static void ordenar(double[] m)
I
d o u b l e a ux ;
i n t i , nmero_de_elementos = m .le n g th :
boolean s = true:
public s t a t ic void o r d e n a r ( S t r i n g [ ] m)
1
S t r i n g a ux :
i n t i . nmero_.de_el e m e n t o s m. l e n g t h ;
boolean s = true:
if ( m [ i - 1 ] .compareTo(m[i]) > 0)
I
// p e r m u t a r l o s e l e m e n t o s ( i -1) e (i)
aux = m [ i - 1 ] ;
mC i -1 ] = m [ i ] :
m [i] = aux;
s = true: I I permutacin
/////////////////////////////////////////////////////////////////
O bserve que inicialm ente vale fa lse para cada iteracin y tom a el valor tru e
cuando al m enos se efecta un cam bio entre dos elem entos. Si en una exploracin
a lo largo de la lista no se efecta cam bio alguno, s perm anecer valiendo false, lo
que indica que la lista est ordenada, term inando as el proceso.
// M a t r i z de c a d e n a s de c a r a c t e r e s
S t r i n g f ] s = I " c c c " . " b b b . a a a " . " e e e " . " d d d " 1;
CA PTU LO 14: A LG O RITM O S 5 9 5
CM atriz.ordenar(s):
f o r ( i n t i = 0: i < s . l e n g t h ; i + + )
S y ste m .o u t.p rin t(s[i] + " ");
S y s t e m . o u t . p r i n t l n );
Mtodo de insercin
El algoritm o para este m todo de ordenacin es el siguiente: inicialm ente, se o r
denan los dos prim eros elem entos de la m atriz, luego se inserta el tercer elem ento
en la posicin correcta con respecto a los dos prim eros, a continuacin se inserta
el cuarto elem ento en la posicin correcta con respecto a los tres prim eros ele
m entos ya ordenados y as sucesivam ente hasta llegar al ltim o elem ento de la
m atriz. Por ejem plo:
Valores iniciales:
Valores ordenados:
II D e s d e e l segundo elemento
f o r ( i = 1; i < n_elementos: i++)
[
x = m[ i ] ;
k = i - 1;
// P a r a k 1. s e ha a l c a n z a d o e l extremo i z q u i e r d o ,
w h i 1e ( k >=0 && x < m [ k ] )
I
m [ k + l ] = m [ k ]; // h a c e r h u e c o p a r a insertar
k --:
1
m[k+l] = x; // i n s e r t a r x en s u l u g a r
Mtodo quicksort
El m todo de ordenacin quicksort, est generalm ente considerado com o el m ejor
algoritm o de ordenacin disponible actualm ente. El proceso seguido por este al
goritm o es el siguiente:
2. Se divide la m atriz en dos partes: una con todos los elem entos m enores que el
valor seleccionado y otra con todos los elem entos m ayores o iguales.
3. Se repiten los puntos 1 y 2 para cada una de las partes en la que se ha dividido
la m atriz, hasta que est ordenada.
CA PTU LO 14: A LG O RITM O S 5 9 7
< m t o d o q s m a t r i z "a")>
Se e l i g e un val or x d e la m a t r i z
D O M H I L F ( "a" no e s t d i v i d i d o en dos p a r t e s )
[ d i v i d i r "a" en dos p a r t e s : a _ i n f y a _ s u p ]
a _ i n f c o n los e l e m e n t o s a, < x
a _ s u p c o n los e l e m e n t o s a > - x
F.NDDO
IF ( e x i s t e a _ i n f ) THFN
qs( a _ i n f )
FND1F
IF ( e x i s t e a _ s u p ) THFN
qs( a_sup)
FNDIF
F N D <qs>
// M t o d o r e c u r s i v o qs
p riv a te s t a t ic void q s ( S t r i n g [ ] m, int inf, int sup)
I
i n t i z q . der;
S t r i n g mi t a d . x;
i z q - i n f ; d er = sup;
mitad = m [ ( i z q + d e r ) / 2];
do
I
w hile (m [izq].compareTo(mitad) < 0 88 i z q < su p ) izq++;
w hile (mitad.compareTo(m[der]) < 0 88 d e r > i n f ) der--;
i f ( i z q <= der)
x - m[ i z q ] ; m [ i z q ] - m[der]; m [ d e r ] = x;
izq++; d e r -- ;
w h i l e ( i z q <= d e r ) ;
i f ( i n f < d e r) qs(m. inf. der);
i f ( i z q < sup) qs(m. izq. sup);
598 J A V A : C U R S O D E P R O G R A M A C I N
O bservam os que cuando el v alo r m itad se corresponde con uno de los valores
de la lista, las condiciones izq < sup y d er > i n f de las sentencias
Para experim entarlo, pruebe com o ejem plo la lista de valores I 1 3 1 1 y elija
m ita d = 2 fijo. En este caso las sentencias anteriores seran as:
// M t o d o no r e c u r s i v o q s
p r i v a t e s t a t i c v o i d q s N R ( S t r i n g [ ] m, int inf, int sup)
I
C P i l a p i l a = new C P i l a O : II p i l a de e l e m e n t o s ( i n f . s u p )
CDatos dato: II e n c a p s u l a l o s a t r i b u t o s i n f y s u p
i n t i z q , d e r . p
S t r i n g m i t a d , x;
// I n i c i a r l a p i l a c o n l o s v a l o r e s : i n f . s up
p i 1 a . m e t e r E n P i 1a ( n e w C D a t o s ( i n f , s u p ) ) ;
do
CA PTU LO 14: A LG O RITM O S 5 9 9
// Tomar l o s d a t o s i n f . s u p de l a p a r t e s u p e r i o r de l a pila
d a t o = ( C D a t o s ) p i l a . s a c a r D e P i l a ( );
i n f - d a t o . o b t e n e r l n f ( ) ; s u p = d a t o . o b t e n e r S u p ( );
do
[
// D i v i s i n de l a m a t r i z en d o s p a r t e s
i z q - i n f ; d e r = sup:
mitad - m [ ( i z q + d e r ) / 2 ];
do
I
w h i l e ( m[ i z q ] . c o m p a r e T o ( m i t a d ) < 0 && i z q < s u p ) izq++;
w h i l e ( m i t a d . c o m p a r e T o ( m [ d e r ] ) < 0 && d e r > i n f ) der--;
i f ( iz q <= der)
I
x = m [izq]; m [izq] - m[der]; m [ d e r ] = x;
izq++; d e r --;
w h i 1e ( i z q < = d e r ) :
i f ( i z q < sup)
1
II M e t e r en l a p i l a l o s v a l o r e s : i z q . sup
pila.m eterEnPila(new CDatostizq. sup)):
I
/* inf = inf; */ sup - der:
)
w hile (in f < der);
I
w hile (pila.tam a o() != 0 ) :
1
En esta solucin observam os que despus de cada paso se generan dos nuevas
sublistas. U na de ellas la tratam os en la siguiente iteracin y la otra la pospone
mos, guardando sus lm ites i n f y sup en una pila. El m todo qsN R utiliza la clase
CPila, im plem entada en el captulo de E structuras dinm icas, para crear una
pila que alm acene los valores i n f y sup a los que nos hem os referido anteriorm en
te. Estos lm ites son los atributos de objetos de una clase C D atos definida as:
BSQUEDA DE DATOS
Bsqueda secuencial
Este m todo d e bsqueda, aunque vlido, es el m enos eficiente. Se basa en com
p arar el valor que se desea buscar con cada uno de los valores de la m atriz. La
m atriz no tiene p o r qu estar ordenada.
Bsqueda binaria
Un m todo eficiente de bsqueda, que puede aplicarse a las m atrices clasificadas,
es la bsqueda binaria. Si partim os de que los elem entos de la m atriz estn alm a
cenados en orden ascendente, el proceso de bsqueda binaria puede describirse
as: se selecciona el elem ento del centro o aproxim adam ente del centro de la m a
triz. Si el valor a bu scar no coincide con el elem ento seleccionado y es m ayor que
l, se contina la bsqueda en la segunda m itad de la m atriz. Si, por el contrario,
el valor a buscar es m enor que el valor del elem ento seleccionado, la bsqueda
contina en la prim era m itad de la m atriz. En am bos casos, se halla de nuevo el
elem ento central, correspondiente al nuevo intervalo de bsqueda, repitindose el
ciclo. El proceso se repite hasta que se encuentra el valor a buscar, o bien hasta
que el intervalo de bsqueda sea nulo, lo que querr decir que el elem ento busca
do no figura en la matriz.
i f ( m .le n g th = = 0) r e t u r n -1:
i n t m i t a d , i n f = 0, s u p = m . l e n g t h - 1;
602 JA V A : C U R S O D E PROGRAM A CIN
do
mitad - ( i n f + sup) / 2;
i f (v > m[mi t a d ] )
i nf = m i t a d + 1;
el se
sup = mi t a d - 1;
1
while ( m[mitad] ! = v && i n f < = s u p ) ;
if ( m [ m i t a d ] = = v)
r e t u r n mitad;
el se
re tu rn -1;
Bsqueda de cadenas
Uno de los m todos m s eficientes en la bsqueda de cadenas dentro de un texto
es el algoritm o B oyer y M oore. La im plem entacin bsica de este m todo cons
truye una tabla delta que se utilizar en la tom a de decisiones durante la bsqueda
de una subcadena. D icha tabla contiene un nm ero de entradas igual al nm ero de
caracteres del cdigo que se est utilizando. P or ejem plo, si se est utilizando el
cdigo de caracteres ASCII la tabla ser de 256 entradas. C ada entrada contiene el
v alo r delta asociado con el carcter que representa. P or ejem plo, el valor delta
asociado con A estar en la entrada 6 5 y el valor delta asociado con el espacio en
blanco, en la entrada 32. El valor delta para un carcter, es la posicin de la ocu
rrencia m s a la derecha de ese carcter respecto a la posicin final en la cadena
buscada. L as entradas correspondientes a los caracteres que no pertenecen a la ca
dena a buscar, tienen un valor igual a la longitud de esta cadena.
P or lo tanto, para definir la tabla delta para una determ inada subcadena a bus
car, construim os una m atriz con todos sus elem entos iniciados a la longitud de di
cha cadena, y luego, asignam os el v alo r delta para cada carcter de la subcadena,
as:
f o r ( i = 0; i < l o n g it u d _ c a d e n a _ p a t r n ; i + + )
d e l t a [ c a d e n a _ p a t r n [ i ] ] = 1o n g i t u d _ c a d e n a _ p a t r n - i - 1;
V eam os un ejem plo. S uponga que se desea buscar la cadena cien en el texto
M s vale un ya que cien despus se har". La bsqueda com ienza as:
Texto: Ms v a l e un y a q u e c i e n d e s p u s s e h a r
C aden a a b u s c a r : cien
El funcionam iento del algoritm o puede com prenderse m ejor situando la cade
na a buscar paralela al texto. La com paracin es de derecha a izquierda: por lo
tanto, se com para el ltim o carcter en la cadena a buscar (n) con el carcter que
est justam ente encim a en el texto {espacio). C om o n es distinto de espacio, la
cadena que se busca debe desplazarse a la derecha un nm ero de caracteres igual
al valor indicado p o r la entrada en la tabla delta que corresponde al carcter del
texto que no coincide. Para la cadena "cien ,
Texto: Ms v a l e un y a q u e c i e n d e s p u s s e h a r
C a de n a a b u s c a r : cien
// C o n s t r u i r l a t a b l a " d e l t a "
i n t [ ] d e l t a = new i n t [ 2 5 6 ] :
i n t i , longCad = c a d e n a .1e n g t h :
CA PTU LO 14: ALGORITM OS 6 0 5
// i n i c i a r l a t a b l a " d e l t a "
f o r ( i = 0: i < 2 5 6 : i + + )
d e l t a [ i ] = 1o n g C a d :
// A s i g n a r v a l o r e s a l a t a b l a
f o r ( i 0 : i < 1o n g C a d : + + i )
d e l t a [ c a d e n a [ i ] ] = longCad - i - 1;
// A l g o r i t m o B o y e r - M o o r e
i n t j . l o n g T e x = t e x t o . 1e n g t h :
i - l o n g C a d - 1; // i e s e l n d i c e d e n t r o d e l texto
w h ile ( i < longTex)
I
j - l o n g C a d - 1: / / n d i c e d e n t r o de l a c a d e n a a buscar
// M i e n t r a s h a y a c o i n c i d e n c i a de c a r a c t e r e s
w hile (cadena[j] =- t e x t o f i] )
I
if ( j > 0 )
I
// S i g u i e n t e posicin a la izquierda
j--; i--:
I
else
1
// S e l l e g al principio de l a cadena, luego se encontr,
return i ;
// L o s c a r a c t e r e s n o c o i n c i d e n . M o v e r i l o que i n d i q u e el
// v a l o r " d e l t a " d e l c a r c t e r d e l t e x t o q u e no c o i n c i d e
i + - d e l t a [ t e x t o [ i]]:
I
return -1;
f ic h e r o c: 18 3 2 - 10 6 0 - 14 42 44 6 8 - 12 24 3 0 48
Fase de distribucin:
f i c h e r o a: 18 3 2 - 14 4 2 44 68
f i c h e r o b: 10 6 0 - 12 2 4 30 48
Fase de m ezcla:
fichero c: 10 18 32 60 - 12 14 24 30 4 2 44 4 8 68
Fase de distribucin:
fichero a: 10 18 3 2 60
fichero b: 12 14 24 30 4 2 44 4 8 68
Fase de m ezcla:
fichero c: 10 12 14 18 24 3 0 32 4 2 4 4 4 8 6 0 6 8
CA PTU LO 14: A LG O RITM O S 6 0 7
P ara dejar ordenado el fichero del ejem plo hem os necesitado realizar dos pa
sadas. El proceso finaliza, tan pronto com o el nm ero de tram os ordenados del fi
chero c, sea 1. U na form a de reducir el nm ero de pasadas es distribuir los tram os
ordenados sobre m s de dos ficheros.
< m t o d o m e z c l a _ n a t u r a l ()>
n u t r a m o s = 0;
DO
[ C r e a r y a b r i r los f i c h er os te mp o r a l e s a y b]
n _ t r a m o s = d i s t r i b u c i n ( );
n_tramos = mezcla():
WH I L E (n _t r a m o s .'= 1):
E N D < m e z c l a _ n a t u r a l ()>
public c la ss CMezclaNatural
I
p u b l i c s t a t i c v o i d m e z c l a N a t u r a l ( F i 1e f i c h F u e n t e )
throws IOException
I
i n t n r o _ t r a m o s = 0;
// a y b s o n d o s f i c h e r o s temporales
do
I
d i s t r i b u i r ( f i c h F u e n t e . a, b ) :
n r o _ t r a m o s = m e z c l a r a , b. f i c h F u e n t e ) :
)
while (nro_tramos != 1):
import ja v a .i o . * :
//////////////////////////////////////////////////////////////////
// O r d e n a r un f i c h e r o u t i l i z a n d o e l m t od o de m e z c l a n a t u r a l .
// S e t r a t a de un f i c h e r o de t e x t o q u e a l m a c e n a una l i s t a de
// nombres.
II El no mb r e d e l f i c h e r o s e r e c i b e a t r a v s de l a l i n e a de r d e n e s .
// La o r d e n a c i n s e r e a l i z a en o r d e n a l f a b t i c o a s c e n d e n t e .
// La a p l i c a c i n e s t s o p o r t a d a p o r l a c l a s e C M e z c l a N a t u r a l .
// Mtodos:
// mezclaNatural
// d istribuir
// mezclar
II mai n
//
p u b lic c l a s s CMezclaNatural
I
// M e z c l a n a t u r a l / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
p u b lic s t a t i c vo id m e z c la N a tu ra l( F i 1e fic h F u e n te )
th rows IO E xce p tio n
I
// D e f i n i c i n de v a r i a b l e s
F i l e a = new F i 1e ( " f t e m p a . t m p " ) ; // f i c h e r o temporal
F i l e b = new F i 1 e ( " f t e m p b . t m p " ) ; // f i c h e r o temporal
in t nro_tramos;
do
I
n r o _ t r a m o s = d i s t r i b u i r ( f i c h F u e n t e , a. b);
if ( n r o _ t r a m o s < = 1)
I
// P r o c e s o f i n a l i z a d o . B o r r a r los ficheros temporales.
a.deleteO : b.deleteO :
return;
)
nro_tramos = m e z cla rla , b. fichFuente);
I
while (nro_tramos != 1);
I II m e z c l a N a t u r a l
C A P T U L O 14: ALGORITM OS 6 0 9
// F a s e de d i s t r i b u c i n / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
p u b lic s t a t i c in t d i s t r i b u i r ( F i l e fuente. F i l e destinoA.
F i l e d e s t i n o B ) throws IO E xce p tio n
I
// A b r i r un f l u j o d e e n t r a d a d e s d e f u e n t e q u e p e r m i t a
// l e e r l a i n f o r m a c i n l i n e a a l i n e a .
F i l e l n p u t S t r e a m f i s = new F i 1e ! n p u t S t r e a m ( f u e n t e );
I n p u t S t r e a m R e a d e r i s r = new I n p u t S t r e a m R e a d e r t f i s ):
B u f f e r e d R e a d e r f e = new B u f f e r e d R e a d e r ( i s r ) ;
// A b r i r un f l u j o de s a l i d a h a c i a d e s t i n o A
F i l e O u t p u t S t r e a m f o s A = new F i 1 e O u t p u t S t r e a m d e s t i n o A ) ;
O u t p u t S t r e a m W r i t e r o s r A = new O u t p u t S t r e a m W r i t e r ( f o s A ) ;
B u f f e r e d W r i t e r f a = new B u f f e r e d W r i t e r ( o s r A ) ;
// A b r i r un f l u j o de s a l i d a h a c i a d e s t i n o B
F i l e O u t p u t S t r e a m f o s B = new F i 1e O u t p u t S t r e a m t d e s t i n o B ):
O u t p u t S t r e a m W r i t e r o s r B = new O u t p u t S t r e a m W r i t e r ( f o s B ):
B u f f e r e d W r i t e r f b = new B u f f e r e d W r i t e r ( o s r B ):
B u ffe re d W r it e r faux = fa ; // f a u x s e r f a o fb
Strin g linea: II ltima line a leda
S t r i n g I1nea_ant; // lin e a a n t e rio r a la ltima leda
i n t n r o _ t r a m o s = 1; // n me r o t o t a l de t r a m o s o r d e n a d o s
II L e e r l a p r i m e r a l i n e a ( l i n e a anterior)
i f ( ( I 1 n e a _ a n t = f e . r e a d L i n e ( )) != n u i l )
I
// E s c r i b e en f a l a l i n e a l e d a ms el separador de l i n e a
f a . w r i t e ( 1 i n e a _ a n t ) ; f a . n e w L i n e ( );
1
el se
I
faux = n u i l ; fc.closeO : fa .closeO ; fb.closeO :
r e t u r n 0;
// L e e r l a s i g u i e n t e l i n e a ( l i n e a a c t u a l )
w h i le ( ( l i n e a = f c . r e a d L i n e ( )) != n u i l )
I
if ( 1 1 n e a . c o m p a r e T o t 1 i n e a _ a n t ) < 0)
I
// C a m b i a r a l o t r o f i c h e r o
faux = (faux = f a ) ? fb : fa;
++nro_tramos:
I
11nea_ant = 11n e a ;
// E s c r i b e en f a u x l a l i n e a l e d a ms el separador de l i n e a
f a u x . w r i t e ( 1 1nea); f a u x . n e w L i n e ():
I
610 JA V A: C U R SO DE PRO G R A M A CI N
// F a s e d e m e z c l a / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
p u b l i c s t a t i c i n t m e z c l a r t F i l e fuenteA. F i l e fu enteB,
F i l e d e s t in o ) throws IOException
I
// A b r i r un f l u j o d e e n t r a d a d e s d e f u e n t e A que p e r m i t a
// l e e r l a i n f o r m a c i n l i n e a a linea.
F i l e l n p u t S t r e a m f i s A = new F i 1e l n p u t S t r e a m t f u e n t e A ) :
I n p u t S t r e a m R e a d e r i s r A = new I n p u t S t r e a m R e a d e r ! f i s A ) ;
B u f f e r e d R e a d e r f a = new B u f f e r e d R e a d e r ! i s r A ) ;
// A b r i r un f l u j o de e n t r a d a d e s d e f u e n t e B que p e r m i t a
// l e e r l a i n f o r m a c i n l i n e a a linea.
F i l e l n p u t S t r e a m f i s B = new F i l e l n p u t S t r e a m ! f u e n t e B ) :
I n p u t S t r e a m R e a d e r i s r B = new I n p u t S t r e a m R e a d e r t f i s B ) ;
B u f f e r e d R e a d e r f b = new B u f f e r e d R e a d e r ! i s r B ) ;
// A b r i r un f l u j o de s a l i d a h a c i a d e s t i n o
F i l e O u t p u t S t r e a m f o s = new F i 1e O u t p u t S t r e a m ! d e s t i n o );
C u t p u t S t r e a m W r i t e r o s r = new O u t p u t S t r e a m W r i t e r ( f o s );
B u f f e r e d W r i t e r f e = new B u f f e r e d W r i t e r ( o s r );
// Leemos l a s d o s p r i m e r a s lineas, un a de f a y o t r a de f b
U n e a D e F a = f a . r e a d L i n e ! );
1i neaDeFa_ant = U n e a D e F a ;
U n e a D e F b = f b . r e a d L i n e ( );
1i neaDeFb_ant = U n e a D e F b ;
// Vamos l e y e n d o y c o m p a r a n d o h a s t a q u e s e a c a b e a l g u n o de l o s
// f i c h e r o s . La f u s i n s e r e a l i z a e n t r e p a r e s d e t r a m o s
// o r d e n a d o s . Un t r a m o de f a y o t r o de f b d a r n l u g a r a un
// t r a m o o r d e n a d o s o b r e f e .
w h i l e ( U n e a D e F a ! = n u i l && U n e a D e F b ! = n u i l )
I
if ( U n e a D e F a . c o m p a r e T o d IneaDeFb) < 0) // i f 1
I
i f ( 1 1 n e a D e F a .c o m p a r e T o ( 11n e a D e F a _ a n t ) < 0) // i f 2
// E n c o n t r a d o e l f i n a l d e l t r a m o de f a
I
11 n e a D e F a _ a n t = U n e a D e F a ;
// C o p i a m o s e l t r a m o o r d e n a d o de f b
do
I
f c . w r i t e ( 1 I n e a D e F b ) : f e . n e w L i n e ( );
CA PTU LO 14: ALGORITM OS 6 1 1
11neaDeFb_ant - lneaDeFb;
I
while ( ( U n e a D e F b - f b . r e a d L i n e t ) ) ! = n u i l &&
1 IneaDeFb.compareTod1neaDeFb_ant) > 0):
++nro_tramos;
l
else // de i f 2
[
// C o p i a m o s l a c a d e n a l e d a de f a
11neaDeFa_ant = U n e a D e F a :
f e . w r i t e t 1 i n e a D e F a ) : f e . n e w L i n e t ):
U n e a D e F a = f a . r e a d L i n e ( ):
1
1
else // de i f 1
I
i f (1 I n e a D e F b . c o m p a r e T o d 1 n e a D e F b _ a n t ) < 0 ) // i f 3
// E n c o n t r a d o el f i n a l d e l t r a m o de fb
I
11neaDeFb_ant - U n e a D e F b :
// C o p i a m o s e l t r a m o o r d e n a d o d e fa
do
I
f c . w r i t e t l i n e a D e F a ) : f e . n e w L i n e ( );
1 1neaDeFa_ant - U n e a D e F a :
1
while ( ( U n e a D e F a - f a . r e a d L i n e t ) ) ! = n u i l &&
UneaDeFa.com pareTo(HneaDeFa_ant) > 0):
++nro_tramos;
1
else // d e i f 3
I
II C o p i a m o s l a c a d e n a l e d a d e f b
11n e a D eF b_ a n t = l n e a D e F b :
f c . w r i t e d I n e a D e F b ) ; f e . n e w L i n e t ):
U n e a D e F b = f b . r e a d L i n e t ):
1 // de w h i l e
// En e l c a s o d e a c a b a r s e primero los d a t o s de fb
i f ( 1 1 n e a D e F b = = n u l 1)
I
f e . w r i t e t l 1n e a D e F a ): f e . n e w L i n e t ):
w h i l e ( d i n e a D e F a = fa . re a d L i n e t )) != n u i l )
I
f e . w r i t e ( 1 1 n e a D e F a ); f e . n e w L i n e t );
// En e l c a s o de a c a b a r s e primero lo s d a t o s d e fa
612 JA V A : C U R SO DE PROGRAM A CIN
// L e e r el f i c h e r o y m o s t r a r l o
S t r in g lnea;
w h ile ( ( l n e a = f e . r e a d L i n e ( )) != n u i l )
S y s t e m . o u t . p r i n t l n ( 1 n e a ):
f e . e l o s e ( ):
C A PTU LO 14: ALGORITM OS 6 1 3
catchlOException e)
I
System .out.p rintln"Error: " + e .g e tM e s sa g e )):
I
1
I
i
//////////////////////////////////////////////////////////////////
De la clase B u ffe re d W rite r. cabe destacar los m todos: w rite que perm ite
escribir una lnea de texto pero sin escribir el carcter delim itador de la misma
(norm alm ente \n, \r, o \r\n) y n e w L in e que perm ite escribir el carcter delim itador
de lnea: este carcter es definido por el sistem a y no tiene que ser necesariam ente
el carcter \n.
614 JA V A : C U R SO D E PROGRAM A CIN
/////////////////////////////////////////////////////////////////
// D e f i n i c i n de l a clase CListaTfnos.
//
import j a v a . i o . * ;
public c la ss CListaTfnos
I
private R a n d o m A c c e s s F i 1e f e s : // f l u j o
private int nregs: // n me r o de r e g i s t r o s
private i n t tamaoReg = 140: // t a ma o d e l r e g i s t r o en b y t e s
// B u s c a r un d e t e r m i n a d o registro a p artir de po s
// M t o d o q u i c k s o r t p a r a o r d e n a r e l f i c h e r o ////////////////////
pu blic void q u i c k s o r t O throws IOException
I
qs(0, nregs - 1):
// O b t e n e r d e l r e g i s t r o m i t a d , el campo p o r e l que
// s e va a o r d e n a r e l f i c h e r o .
mitad - c a m p o ((iz q + d e r ) / 2 ) :
do
I
while (cam poizq).com pareom itad) < 0 && i z q < s u p ) izq++:
w h ile (m it a d .compareTo(campo(der)) < 0 && d e r > i n f ) der--;
i f ( iz q < - der)
I
p e r m u ta rR e g istro s(iz q . der):
izq++: d e r --;
w h i l e ( i z q <= d e r ) :
if (in f < der) q s ( i n f , d e r );
i f (iz q < sup) q s t iz q , sup):
// P e r m u t a r l o s r e g i s t r o s de l a s p o s i c i o n e s i y j
p r i v a t e v o i d p e r m u t a r R e g i s t r o s ( i n t i . i n t j ) th rows IOException
I
C P e r s o n a x. y;
// L e e r l o s r e g i s t r o s de l a s posiciones i y j
x =* v a l o r E n ( i );
616 JA V A: C U R S O D E PROGRAM A CIN
y = v a l o r E n j ) ;
// E s c r i b i r l o s en l a s posiciones j e i
ponerValorEn(j. x):
p o n e r V a l o r E n ( i , y );
I
// O b t e n e r e l campo u t i l i z a d o p a r a o r d e n a r , d e l r e g i s t r o nreg
p r i v a t e S t r i n g campotint n reg) throws IOException
I
f e s . s e e k ( n r e g * tamaoReg); // s i t u a r e l p u n t e r o de L/E
r e t u r n f e s . re a d U T F t ): // d e v u e l v e e l nombre
El m todo perm utarR egistros es llam ado p o r qs (q uicksort) cuando hay que
perm utar d o s registros del fichero para que queden correctam ente ordenados.
F i l e f i c h e r o - new F i l e C l i s t a t f n o s . d a t " ) :
l i s t a t f n o s - new C L i s t a T f n o s ( f i c h e r o ) :
// ...
c a s e 6: // o r d e n a r
l i s t a t f n o s . q u i c k s o r t f ):
break:
ALGORITMOS HASH
Los algoritm os hash son m todos de bsqueda, que proporcionan una longitud de
bsqueda pequea y una flexibilidad superior a la de otros m todos, com o puede
ser, el m todo de bsqueda binaria que requiere que los elem entos de la matriz
estn ordenados.
Matrices hash
Clave Contenido
50 4 0
3721
6375
La m atriz se organiza con elem entos form ados p o r dos m iem bros: clave y
contenido. La clave constituye el m edio de acceso a la m atriz. A plicando a la cla
ve una funcin de acceso f a , previam ente definida, obtenem os un nm ero entero
positivo i correspondiente a la posicin del elem ento en la m atriz.
i = fa (c la v e)
Com o ejem plo, suponer que la clave de acceso se corresponde con el nm ero
del docum ento nacional de identidad (dni) y que el contenido son los datos co
rrespondientes a la persona que tiene ese dni. U na funcin de acceso, i= fa(dni),
que haga corresponder la posicin del elem ento en la m atriz con el d n i, es inm e
diata: / = dni. E sta funcin as definida presenta un inconveniente y es que el n
m ero de valores posibles de i es dem asiado grande para utilizar una m atriz. Para
solucionar este problem a, siem pre es posible, dada una m atriz de longitud L, crear
una funcin de acceso, fa , que genere un valor com prendido entre 0 y L, m s co
618 JA VA: C U R SO D E PROGRAM A CIN
m nm ente entre 1 y L. E n este caso puede suceder que dos o m s claves den lugar
a un m ism o valor de i:
Clve Contenido
5040
3721
688 : 4007
3900
c
6375
i = fa (6 3 8 3 ) = 3
accesos = (2-k)/(2-2k)
L = 2 5 6 lo q u e implica n = 8
C = 6 25
C2 = 3 9 0 6 2 5 ( 0 < = C2 < = 2 32- l )
3 9 0 6 2 5 10 = 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 0 1 0 1 1 1 1 0 0 0 0 1 ;
n b i t s del m e d i o : 0 1 0 1 1 1 1 1 ; = 9 5 10
i = m dulo(clave/L)
5040 JT 2039 0
C ada elem ento de esta estructura incorpora un nuevo m iem bro R, el cual es
una referencia a la lista encadenada de desbordam iento.
Eliminacin de elementos
En el m todo hash la elim inacin de un elem ento no es tan sim ple com o dejar va
co dicho elem ento, ya que esto dara lugar a que los elem entos insertados por c o
lisin no puedan ser accedidos. Por ello, se suele utilizar un m iem bro
com plem entario que sirva para poner una m arca de que dicho elem ento est eli
m inado. E sto perm ite acceder a otros elem entos que dependen de l p o r colisio
nes, ya que la clave se conserva y tam bin perm ite insertar un nuevo elem ento en
esa posicin cuando se d una nueva colisin.
Clase CHashAbierto
C om o ejercicio escribim os a continuacin una clase denom inada C H ashAbierto
que proporciona los m todos necesarios para trabajar con m atrices hash utilizando
el m todo hash abierto, cuyo seudocdigo se expone a continuacin:
C A PTU LO 14: ALGORITM OS 6 2 1
< m t o d o h a s h ( m a t r i z . e l e m e n t o x)>
[La m a t r i z est i niciada a cero ]
i - matricula mdulo nmero_elementos
DO U H I L E (no i ns er t a d o y h aya e l e m e n t o s libres)
IF ( e l e m e n t o "i" e s t libre) THEN
c o p i a r e l e m e n t o x e n la p o s i c i n i
ELSE
I F ( cl av e d u p l i c a d a ) THEN
er ro r: c l a v e d u p l i c a d a
ELSE
[se ha p r o d u c i d o una c o l i s i n ]
[ a v a n z a r al s i g u i e n t e e l e m e n t o ]
i - i+1
IF (i - n m e r o _ e l e m e n t o s ) THEN
i - 0
EN DI F
ENDIF
ENDIF
ENDDO
E N D <h as h>
L a clase C H ashA bierto que vam os a im plem entar incluir un atributo privado
m atrizhash para referenciar la m atriz hash. Un objeto C H ashAbierto encapsula
una m atriz hash de 101 elem entos por om isin, que son referencias a objetos de
tipo O b je c t. lo que perm itir alm acenar elem entos de cualquier clase. A sim ism o,
incluye los m todos indicados en la tabla siguiente:
//////////////////////////////////////////////////////////////////
// C l a s e a b s t r a c t a C H a s h A b i e r t o : m t od o h a s h a b i e r t o .
// Para u t i l i z a r l o s mtodos p r o p o r c io n a d o s por e s t a c l a s e .
// t e n d r e m o s q u e c r e a r una s u b c l a s e de e l l a y r e d e f i n i r l o s
// m t o d o s : f a ( f u n c i n de a c c e s o ) y c o m p a r a r .
//
public abstract class CHashAbierto
I
il A t r i b u t o s
p r iv a t e ObjectC] m atrizhash;
// M t o d o s
public CHashAbierto()
I
m a t r i z h a s h = new O b j e c t C 1 0 1 3 :
// B u s c a r un nmero p r i m o a p a r t i r d e un n me r o d a d o / / / / / / / / / / /
p u b l i c i n t n m e r o P r i m o ( i n t n)
I
boolean primo = f a l s e ;
int i, r = (in t)M ath.sqrt((dou ble)n):
i f (n % 2 0) n++;
w hile (prim o)
I
primo = tru e :
f o r ( i = 3: i < = r ; i + = 2 )
i f (n % i = = 0) primo = f a l s e :
C A P T U L O 14: A LG O RITM O S 6 2 3
if (prim o) n + = 2: // s i g u i e n t e i mp a r
I
return n;
// F u n c i n d e a c c e s o / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
II E s t e m t od o d e b e s e r r e d e f i n i d o en una s u b c l a s e p a r a p o d e r
II d e f i n i r l a f u n c i n de a c c e s o q u e e l u s u a r i o d e s e e a p l i c a r ,
public abstract in t fa(0bject obj):
// M t o d o c o m p a r a r / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
II E s t e m t od o d e b e s e r r e d e f i n i d o en una s u b c l a s e p a r a que
// p e r m i t a c o m p a r a r d o s e l e m e n t o s de l a m a t r i z h a s h p o r el
// a t r i b u t o que n e c e s i t e m o s en ca d a momento,
p u b l i c a b s t r a c t i n t c o m p a r a r ( O b j e c t o b j l . O b j e c t o b j 2>:
// M t o d o h a s h a b i e r t o / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
p u b l i c v o i d h a s h l n ( 0 b j e c t x)
l
int i: // I n d i c e p a r a a c c e d e r a un e l e m e n t o
i n t c o n t a = 0: // c o n t a d o r
boolean in s e r t a d o = f a l s e :
i = f a ( x ); // f u n c i n d e a c c e s o
w h i l e ( i n s e r t a d o && c o n t a < m a t r i z h a s h . l e n g t h )
I
if (m a triz h a s h [ i] == n u il) // e l e m e n t o l i b r e
I
m a t r i z h a s h [ i ] = x;
insertado = true;
I
e l s e // el a v e d u p l i ca d a
i f (comparar(x. m a t r iz h a s h [ i]) = = 0)
I
S y s t e m . o u t .p r in t ln ( "e r r o r : clave du p lica d a "):
insertado = true:
1
else // c o l i s i n
I
// S i g u i e n t e e l e m e n t o l i b r e
i++; conta++:
i f (i == m a trizha sh .length ) i = 0:
if (co n ta == m a t r i z h a s h . l e n g t h )
System .out.p r i n t l n ( " e r r o r : m atriz llena\n"):
// x p r o p o r c i o n a r e l a t r i b u t o u t i l i z a d o p a r a b u s c a r . El r e s t o
// de l o s a t r i b u t o s no i n t e r e s a n ( s o n l o s que s e d e s e a c o n o c e r )
in t i; // i n d i c e p a r a acceder a un e l e m e n t o
i n t c o n t a = 0 ; // c o n t a d o r
boolean encontrado = f a l s e :
i * f a ( x ): II f u n c i n de a c c e s o
i f ( m a t r i z h a s h t i ] == n u i l ) r e t u r n n u i l :
w h i l e ( e n c o n t r a d o && c o n t a < m a t r i z h a s h . l e n g t h )
I
if (comparar(x, m a t r i z h a s h [ i ] ) = = 0)
I
x = m atrizha sh [i];
encontrado = true:
1
else // c o l i s i n
I
// S i g u i e n t e e l e m e n t o l i b r e
i++; conta++;
i f (i == m atrizh a sh .le n g th ) i = 0;
if (conta m a t r i z h a s h . 1 e n g t h ) // no e x i s t e
r e t u r n nul'l :
el se
r e t u r n x;
/////////////////////////////////////////////////////////////////
// D e f i n i c i n de l a c l a s e CAl u mno
II
public class CAl u mno
I
// A t r i b u t o s
p riv a te int m atrcula:
p r i v a t e S t r i n g nombre:
// Mtodos
CA PTU LO 14: ALGORITM OS 6 2 5
public C A I u m n o ( ) {1
no mb r e = nom;
m a t r i c u l a = mat;
no mb r e - nom;
r e t u r n n o mbr e ;
public void a s i g n a r M a t r i c u l a ( i n t ma t )
matri cu la = m at;
public long o b t e n e r M a t r ic u la ()
I
return m atrcula;
Los objetos C Alum no sern alm acenados en la m atriz utilizando com o clave
el nm ero de m atrcula. Segn esto, derivam os la clase H ashA bierto de la clase
abstracta C H ashAbierto y redefinim os los m todos f a y com parar as:
//////////////////////////////////////////////////////////////////
// C l a s e d e r i v a d a de l a c l a s e a b s t r a c t a C H a s h A b i e r t o . Redefine
// l o s m t o d o s : f a ( f u n c i n d e a c c e s o ) y c o m p a r a r .
//
public class HashAbierto extends CHashAbierto
I
public HashAbierto(int nElementos)
I
s u p e r ( n F l e m e n t o s );
//////////////////////////////////////////////////////////////////
Finalm ente, escribirem os una aplicacin Test que perm ita crear un objeto
H ashA bierto, envoltorio de la m atriz hash. Para probar su correcto funciona
m iento escribirem os cdigo que perm ita tanto aadir com o buscar objetos en di
cha matriz.
import j a v a . i o . * :
//////////////////////////////////////////////////////////////////
// A p l i c a c i n para t r a b a j a r c o n una m a t r i z hash
//
public e la ss Test
I
public static void m a in (S trin g [] args)
I
// D e f i n i c i n de v a r i a b l e s
PrintStream f lu jo S = System.out;
i n t n _ e l e m e n t o s : // n m e r o de e l e m e n t o s de l a m a t r i z hash
i nt i :
S t r i n g nombre:
i nt m a t r ic u l a :
C AI um n o x ;
// C r e a r un o b j e t o H a s h A b i e r t o ( e n c a p s u l a l a m a t r i z h a s h )
S y s t e m . o u t . p r i n t l n ( " n m e r o de e l e m e n t o s : ");
n _ e l e m e n t o s = L e e r . d a t o l n t t );
H a s h A b i e r t o m = new H a s h A b i e r t o ( n _ e l e m e n t o s ) :
f l u j o S . p r i n t l n ( " S e c o n s t r u y e una m a t r i z de +
m .nmeroDeElementos( ) + " e l e m e n t o s " ) :
// In t r o d u c ir datos
CA PTU LO 14: A LG O RITM O S 6 2 7
f l u j o S . p r i n t n ( " In t r o d u c ir datos. +
"Para f i n a l i z a r , m atrcula = 0 \ n ") ;
flujoS. p rin tC m a tricu la : ) : m a t r c u l a = L e e r , d a t o l n t ( ):
w h i l e ( m a t r i c u l a ! - 0)
1
f l ujoS. p r in t ( "nombre: " ) : no mb r e = L e e r . d a t o O :
m .hashln(new CAIumno(nombre. m a t r c u l a ) ) :
flujoS.printC m atricula: ) : m a t r c u l a - L e e r . d a t o l n t ):
// B u s c a r d a t o s
f lu j o S . p r in t ln t " B u s c a r datos. +
"Para f i n a l i z a r , m atricu la = 0 \ n ")
flujoS.printC m atricula: " ) : m a t r i c u l a = L e e r . d a t o I n t ( ):
w h i l e ( m a t r i c u l a ! - 0)
1
x - (CAlumno)m.hashOut(new C A lu m n o ( "" . m a t r i c u l a ) ) :
i f ( x ! = n u l 1)
flu jo S . p r in t n ( "n o m b r e : " + x .obtenerNombret));
el se
f l u j o S . p r i n t l n ( " N o e x i s t e ):
flujoS.printC m atricula: ) ; m a t r c u l a - L e e r . d a t o I n t ( ):
I
1
I
EJERCICIOS RESUELTOS
1. C om parar las dos siguientes versiones del m todo bsqueda binaria e indicar cul
de ellas es m s eficaz.
i f (m.length = 0 ) r e t u r n - 1;
i n t m i t a d , i n f = 0. s u p - m . l e n g t h - 1;
do
I
mitad = ( i n f + sup) / 2:
628 JA V A : C U R S O D E P R O G R A M A C I N
if (v > m [m itad])
i n f = mi t a d + 1;
el se
s u p = mi t a d - 1 :
I
while( m[mitad] ! = v && i n f <= s u p ) ;
if (m[mi t a d ] = v)
r e t u r n mitad;
else
r e t u r n -1;
i f (m.length = 0 ) r e t u r n - 1;
i n t m i t a d , i n f = 0. s u p = m . l e n g t h - 1;
do
I
mi t a d = ( i n f + sup) / 2.:
i f (v > m[mitad])
i nf = mi t a d + 1;
el se
sup = m itad;
if ( m [ i n f ] = = v)
return in f;
else
r e t u r n -1;
Ii
L a aplicacin siguiente perm ite ver de una form a prctica que la versin se
gunda em plea m enos tiem po de ejecucin que la prim era. E sta aplicacin crea una
m atriz y, utilizando prim ero una versin y despus la otra, realiza una bsqueda
por cada uno de sus elem entos y dos bsquedas m s para dos valores no pertene
cientes a la m atriz, uno m enor que el m enor y otro m ayor que el m ayor. El tiem po
de ejecucin m edido en m ilisegundos se obtiene por diferencia de los tiem pos de
vueltos por el m todo c u rre n T im e M illis de la clase S ystem al iniciar cada pro
ceso de bsqueda y al finalizarlo.
class prueba
1
public static int bsquedaBinl(double[] m. d o u b l e v)
I
// V e r s i n 1
// V e r s i n 1
t i - S y s t e m . c u r r e n t U m e M i 11 i s ( ) ;
i = bsquedaBinl(a.O ):
f o r ( i - 0: i < n; i + + )
i b s q u e d a B i n l ( a . i + 1 ):
i = b s q u e d a B i n l ( a . n + 1 ):
S y s te m . o u t .p r in t ln ( S y s t e m . c u r r e n t T im e M illis () - t i) + " m ilisegundos"):
// V e r s i n 2
t i - S y s t e m . c u r r e n t T i m e M i 11 i s ( ) :
i - bsquedaBin2(a,0):
f o r ( i = 0 : i < n; i + + )
i - b s q u e d a B i n 2 ( a . i + L ):
i - b s q u e d a B i n 2 ( a . n + 1 ):
S y s t e m . o u t . p r i n t n ( ( S y s t e m . c u r r e n t T i m e M i 11 i s ( ) - t i ) + m i l i s e g u n d o s " ) :
630 JA V A : C U R SO D E PROGRAM A CIN
2. Un centro num rico es un nm ero que separa una lista de nm eros enteros
(com enzando en 1) en dos grupos de nm eros cuyas sum as son iguales. El prim er
centro num rico es el 6, el cual separa la lista (1 a 8) en los grupos: (1, 2, 3, 4, 5)
y (7, 8) cuyas sum as son am bas iguales a 15. El segundo centro num rico es el 35,
el cual separa la lista ( l a 49) en los grupos: (1 a 34) y (36 a 49) cuyas sum as son
am bas iguales a 595. E scribir un program a que calcule los centros num ricos en
tre 1 y n.
El ejem plo (1 a 5 ) 6 (7 a 8), donde se observa que 6 es un centro num rico, sugie
re ir probando si los valores 3, 4, 5, 6, .... en, n-1 son centros num ricos. En
general en es un centro num rico si la sum a de todos los valores enteros desde 1 a
cn-1 coincide con la sum a desde cn+ 1 a lim _sup_grupo2 (lm ite superior del gru
po segundo de nm eros). Para que el program a sea eficiente, buscarem os el valor
lim _sup_grupo2 entre los valores cn+ 1 y n-1 utilizando el m todo de bsqueda
binaria. R ecuerde que la sum a de los valores enteros entre 1 y x viene dada p o r la
expresin ( x * (x + l))/2 .
II B s q u e d a binaria
C A PTU LO 14: ALGORITM OS 6 3 1
do
I
m i t a d = ( i n f + s u p ) / 2;
suma_grupo2 = (m itad * (m itad + 1 ) ) / 2 suma_grupol - en;
i f (sum a_gru po l > suma_grupo2)
inf = m i t a d + 1:
el se
s u p = m i t a d - 1;
I
while ( suma_grupol ! - s u m a _ g r u p o 2 && i n f < = s u p ) ;
EJERCICIOS PROPUESTOS
1. Escribir un program a que calcule los centros num ricos entre i y n utilizando el
algoritm o de bsqueda secuencial en lugar del de bsqueda binaria. U tilice el
m todo c u rre n tT im e M illis de la clase S y ste m para com parar cunto m s lento es
el m todo de bsqueda secuencial que el de bsqueda binaria.
4. E scribir una clase que incluya un m todo orilenarM atriz2D que perm ita ordenar
ascendentem ente una m atriz de dos dim ensiones en la que cada elem ento sea un
o bjeto de la clase C Alum no expuesta anteriorm ente en este m ism o captulo.
Para realizar el proceso de ordenacin em plee el m todo que quiera, pero hgalo
directam ente sobre la m atriz por el cam po nom bre.
Finalm ente, escriba una aplicacin que pueda recibir el nom bre de un fichero
com o argum ento en la lnea de rdenes, cuyos registros sean de la clase C A lum no,
alm acene los registros en una m atriz de dos dim ensiones y utilizando el m todo
o rdenar que acaba de escribir, ordene la m atriz y la visualice una vez ordenada.
5. R ealizar un program a que cree una lista dinm ica a partir d e una serie de nm eros
cualesquiera introducidos por el teclado. A continuacin, ordenar la lista ascen
dentem ente utilizando el m todo quicksort.
// M t o d o s
// . . .
I
HILOS
U no de los pasos im portantes que la inform tica dio en favor de los desarrollado-
res de softw are fue colocar un nivel de softw are por encim a del hardw are de un
ordenador. Este nivel de softw are, conocido com o sistem a operativo, es en esen
cia una interfaz fcil de u tilizar que nos perm ite controlar todas las partes del
hardw are, en la m ayora de los casos, sin un profundo conocim iento del m ism o.
A su vez, los sistem as operativos tam bin han experim entado un gran avance,
pasando de los sistem as de un nico procesador a los actuales sistem as operativos
distribuidos o de red, o a los sistem as operativos con m ultiprocesadores. Esta
evolucin ha desem bocado en un m ejor aprovecham iento de todos los recursos
disponibles, perm itindonos ejecutar cada vez m s tareas en m enos tiem po.
CONCEPTO DE PROCESO
Un proceso es un ejem plar en ejecucin de un program a. C ada proceso consta de
bloques de cdigo y de datos cargados desde un fichero ejecutable o desde una
biblioteca dinm ica. Tam bin es propietario de otros recursos que se crean du
rante la vida de dicho proceso y se destruyen cuando finaliza. Por ejem plo, un
proceso posee:
634 JA V A : C U R S O D E P R O G R A M A C I N
P re p a ra d o
^ lo q u e a d ^ J
^ E n eje cu c i n
HILOS
U n hilo (thread - llam ado tam bin proceso ligero o subproceso) es la unidad de
ejecucin de un proceso y est asociado con una secuencia de instrucciones, un
conjunto de registros y una pila. C uando se crea un proceso, el sistem a operativo
crea su prim er hilo (hilo prim ario) el cual puede a su vez, crear hilos adicionales.
E sto pone de m anifiesto que un proceso no se ejecuta, sino que es slo el espacio
de direcciones donde reside el cdigo que es ejecutado m ediante uno o m s hilos.
s a l d o - C u e n t a . O b t n e r S a l d o ( );
saldo +- ingreso:
Cuenta.EstablecerSald o( saldo ):
Los hilos com parten la U C P de la m ism a form a que lo hacen los procesos,
pueden crear hilos hijo y se pueden bloquear. N o obstante, m ientras un hilo est
bloqueado se puede ejecutar otro hilo del m ism o proceso, en el caso de hilos so
portados por el kernel (ncleo del sistem a operativo: program as en ejecucin que
hacen que el sistem a funcione), no sucediendo lo m ism o con los hilos soportados
p o r una aplicacin (por ejem plo, en W indow s N T todos los hilos son soportados
por el kernel). Un ejem plo, im aginem os que alguien llega a un cajero para depo
sitar dinero en una cuenta y casi al m ism o tiem po, un segundo cliente inicia la
m ism a o peracin sobre la m ism a cuenta en otro cajero. P ara que los resultados
sean correctos, el segundo cajero quedar bloqueado hasta que el registro que est
siendo actualizado por el prim er cajero, quede liberado.
Estados de un hilo
Igual que los procesos con un solo hilo de control, los hilos pueden encontrarse en
uno de los siguientes estados:
P re p a ra d o
J
B lo q u ea d o
J
E n eje cu c i n
)
Nuevo. El hilo ha sido creado pero an no ha sido activado. C uando se active
pasar al estado preparado.
Preparado. El hilo est activo y est a la espera de que le sea asignada la
UCP.
CA PTU LO 15: HILOS 6 3 7
E s evidente que los hilos son extraordinariam ente tiles, pero tam bin es evi
dente que si no se utilizan adecuadam ente pueden introducir nuevos problem as
m ientras tratam os de resolver otros m s antiguos. P or lo tanto, es un error pensar
638 JA V A: C U R SO DE PROGRAM A CIN
que la m ejor form a de desarrollar una aplicacin es dividirla en partes que se eje
cuten cada u na com o un hilo.
La m ayora del soporte que Java proporciona para trabajar con hilos reside en la
clase T h re a d del paquete ja v a .la n g, aunque tam bin la clase O b ject, la interfaz
R u n n a b le y la clases T h r e a d G r o u p y T h re a d D e a th del m ism o paquete, as c o
m o la m quina virtual, proporcionan algn tipo de soporte.
Los hilos en Java se pueden crear de dos form as: escribiendo una nueva clase
derivada de T h re a d , o bien haciendo que una clase existente im plem ente la in
terfaz R u n n a b le .
// C o n s t r u c t o r e s
T h r e a d ( [ argumentos])
// M t o d o s
s t a t i c Thread c u r r e n t T h r e a d ( )
II D e v u e l v e una r e f e r e n c i a a l h i l o que a c t u a l m e n t e e s t
// en e j e c u c i n ,
void d e s t r o y ( )
// D e s t r u y e e s t e h i l o , s i n r e a l i z a r n i n g u n a o p e r a c i n de
// l i m p i e z a .
S t r i n g getNameO
// D e v u e l v e e l no mb r e d e l h i l o ,
int g e t P r io r it y ( )
II D e v u e l v e l a p r i o r i d a d d e l h i l o ,
void i n t e r r u p t f )
II E n v a e s t e h i l o al e s t a d o d e p r e p a r a d o ,
boolean i s A l i v e O
II V e r i f i c a s i e s t e h i l o e s t v i v o ( n o ha t e r m i n a d o ) .
C A P T U L O 15: H IL O S 639
// I n i c i a l a e j e c u c i n de e s t e h i l o : l a m q u i n a v i r t u a l de J a v a
// i n v o c a al m t od o ru n de e s t e h i l o ,
s t a t ic void y i e l d )
// D e t i e n e t e m p o r a l m e n t e l a e j e c u c i n de e s t e h i l o p a r a
II p e r m i t i r l a e j e c u c i n de o t r o s .
// M t o d o s h e r e d a d o s d e l a c l a s e O b j e c t : n o t i f y . n o t i f y A l l y w a i t
void n o t i f y ( )
// D e s p i e r t a un h i l o de l o s que e s t n e s p e r a n d o p o r el
// m o n i t o r d e e s t e o b j e t o ,
v o i d n o t i f y A l 1( )
II D e s p i e r t a t o d o s l o s h i l o s q u e e s t n e s p e r a n d o por el
// m o n i t o r de este objeto,
vo id w a i t (tmilisegundosl. nanosegundos]])
II E n v a e s t e h i l o a l e s t a d o d e e s p e r a h a s t a que o t r o h i l o
// i n v o q u e a l m t od o n o t i f y o n o t i f y A l l . o h a s t a q u e t r a n s c u r r a
// e l t i e m p o e s p e c i f i c a d o .
I
Segn hem os dicho anteriorm ente, un hilo puede ser un objeto d e una subclase de
la clase T h re a d . Entonces, para que una aplicacin pueda lanzar un determ inado
hilo de ejecucin, el prim er paso es escribir la clase del hilo derivada de T h re a d y
sobreescribir el m todo r u n heredado por sta, con el fin de especificar la tarea
que tiene que realizar dicho hilo.
Por ejem plo, supongam os que querem os escribir una aplicacin elem ental que
en un instante determ inado de su ejecucin lance un hilo que realice un sim ple
conteo. La clase del hilo puede ser la siguiente:
Para p o d er lanzar un hilo de la clase C ontador A delante, prim ero tenem os que
construir un objeto de esa clase y despus enviar a dicho objeto el m ensaje s ta rt;
De esto ltim o se encarga el constructor de la clase. La siguiente aplicacin
m uestra un ejem plo:
El operador new crea un hilo cuentaAdelante (el hilo est en el estado nuevo).
El m todo start cam bia el estado del hilo a preparado. De ahora en adelante y
hasta que finalice la ejecucin del hilo cuentaAdelante, ser el planificador de
hilos el que determ ine cundo ste pasa al estado de ejecucin y cundo lo aban
dona para p erm itir que se ejecuten sim ultneam ente otros hilos.
Segn lo expuesto, el m todo start no hace que se ejecute inm ediatam ente el
m todo ru n del hilo, sino que lo sita en el estado preparado para que com pita
por la U C P ju n to con el resto de los hilos que haya en este estado. Slo el planifi
cador puede asignar tiem po de U C P a un hilo y lo har con cuentaAdelante en
cualquier instante despus de que haya recibido el m ensaje start. Por lo tanto, un
hilo durante su tiem po de vida, gasta parte de l en ejecutarse y el resto en perm a
necer en alguno de los estados distintos al de ejecucin. M s adelante aprender
cm o un hilo transita entre los diferentes estados.
1. El objeto debe ser de una clase que im plem ente la interfaz R u n n a b le , ya que
es esta la que aporta el m todo run.
2. Sobreescribir el m todo r u n con las sentencias que tiene que ejecutar el hilo.
3. C rear un objeto de esa clase.
4. C rear un objeto de la clase T h re a d pasando com o argum ento al constructor,
el objeto cuya clase incluye el m todo run.
5. Invocar al m todo start del objeto T h re ad .
ThreadtRunnable objeto)
Para poder lanzar un hilo asociado con la clase ContadorAtras, prim ero tene
m os que co n struir un objeto de la m ism a, despus un objeto de la clase T h re a d
pasando com o argum ento el objeto de la clase ContadorAtras y finalm ente, enviar
al objeto T h re a d el m ensaje start; de estas dos ltim as operaciones se encarga el
co nstructor ContadorAtras. La siguiente aplicacin m uestra un ejem plo:
E sta form a de lanzar un hilo quizs sea un poco m s com plicada. Sin em bar
go, hay razones suficientes para hacer este pequeo esfuerzo. Si el m todo r u n es
parte de la interfaz de una clase cualquiera, tiene acceso a todos los m iem bros de
esa clase, cosa que no ocurre si pertenece a una subclase de T h re a d . O tra razn
es que Java no perm ite la herencia m ltiple; entonces, si escribim os una clase de
rivada de T h re a d , esa clase no puede ser a la vez una subclase de cualquier otra.
P o r ejem plo, para poder asociar un hilo con la clase CCuentaAhorro derivada de
CCuenta (captulo 10), la nica form a de hacerlo es que CCuentaAhorro imple-
m ente la interfaz R u n n a b le .
Finalm ente, a pesar d e que en ocasiones hablem os en trm inos sim ilares a: la
clase ContadorAtras es un hilo , desde el punto de vista de la program acin
orientada a objetos no es correcto expresarse as, a pesar de entendem os. Lo nico
CA PTU LO 15: HILOS 6 4 3
que es correcto es: la clase ContadorAtras est asociada con un hilo . Observe
en el ejem plo anterior que el hilo es el objeto de la clase T h re a d , no el objeto de
la clase ContadorAtras. Entonces, siem pre que necesitem os que una clase tenga el
com portam iento de un hilo, deberem os im plem entar en la m ism a la interfaz R u n -
nable y sobreescribir el m todo run.
Demonios
Un demonio, a diferencia de los hilos tradicionales, no form a parte de la esencia
del program a, sino de la m quina Java. Los demonios son usados generalm ente
para prestar servicios en segundo plano a todos los program as que puedan nece
sitar el tipo de servicio proporcionado. Por ejem plo, el recolector de basura de Ja
va es un ejem plo de este tipo de hilos.
Para crear un hilo demonio sim plem ente hay que crear un hilo norm al y en
viarle el m ensaje setD aenion:
hilo.setDaem on(true):
Para sab er si un hilo es un demonio sim plem ente hay que enviarle el m ensaje
isD a e m o n . El m todo que se ejecuta devolver tru e si el hilo es un demonio y
false en caso contrario;
boolean b - h i 1 o . i s D a e m o n ( );
644 JA V A : C U R S O D E P R O G R A M A C I N
El intrprete Java norm alm ente perm anece en ejecucin hasta que todos los
hilos en el sistem a finalizan su ejecucin. Sin em bargo, los dem onios son una ex
cepcin, ya que su labor es proporcionar servicios a otros program as. Por lo tanto,
no tiene sentido continuar ejecutndolos cuando ya no haya program as en ejecu
cin. Por esta razn, el intrprete Java finalizar cuando todos los hilos que que
den en ejecucin sean dem onios. El siguiente ejem plo m uestra cm o im plem entar
un hilo dem onio:
//////////////////////////////////////////////////////////////////
// H i l o demonio. Suena "bip" a p r o x i m a d a m e n t e ca d a segundo
//
public class C D e m o ni o e x t e n d s T h r e a d
I
p u b l i c CDemoni o ( )
I
setDaemon(true);
s t a r t t ):
1
//////////////////////////////////////////////////////////////////
Para iniciar un dem onio, dbip, de la clase C D em onio basta con escribir una
sentencia com o la siguiente:
C De m o n i o d b i p = new C D e m o n i o O ;
Finalizar un hilo
Un hilo term ina de form a natural cuando su m todo r u n devuelve el control.
C uando esto sucede el hilo pasa al estado m uerto (ha term inado) y no hay forma
de salir de este estado. Esto es, una vez que el hilo est m uerto, no puede ser
arrancado otra vez; si deseam os ejecutar otra vez la tarea desem peada p o r el hilo
C A PTU LO 15: H ILOS 6 4 5
hay que construir un nuevo objeto hilo y enviarle el m ensaje start, pero s se pue
de invocar a sus m todos.
Por ejem plo, supongam os una clase ContadorAdelante que m uestra un conta
d o r ascendente que ser detenido cuando el atributo continuar sea false. La clase,
adem s de este atributo y del m todo r u n que m uestra la cuenta, tiene un m todo
term inar que pone el atributo continuar a false. y dos constructores: el prim ero
inicia el hilo con el nom bre asignado por om isin y el segundo, tam bin lo inicia
pero con el nom bre pasado com o argum ento.
//////////////////////////////////////////////////////////////////
// C l a s e que d e f i n e un h i l o q u e c u e n t a a s c e n d e n t e m e n t e m i e n t r a s
// q u e e l a t r i b u t o c o n t i n u a r s ea t r u e .
//
public class C o n ta d o r A d e la n t e e x t e n d s Thread
I
private boolean c o n t in u a r - true:
public ContadorAdelantet>
I
s t a r t ():
1
public void r u n ( )
I
i n t i - 1:
while (continuar)
(
System .out.print(getNam e() + " " + i++ + " \ r " )
I
S y s t e m . o u t . p r i n t l n ( ):
1
public void t e r m i n a r O
I
continuar = fa lse;
I
I
//////////////////////////////////////////////////////////////////
un contador ascendente en la pantalla, el dem onio hace sonar un bip cada segun
do. El contador se detendr cuando el usuario pulse la tecla Entrar.
import j a v a . i o . * :
//////////////////////////////////////////////////////////////////
// T e r m i n a r un h i l o .
II
p u b lic c l a s s Test
I
public s t a t ic void m a in (S trin g [] args)
I
// L a n z a r e l d e m o n i o d b i p
C D e m o n i o d b i p = new C D e m o n i o O ;
// L a n z a r el h i l o c u e n t a A d e l a n t e
C o n t a d o r A d e l a n t e c u e n t a A d e l a n t e = new C o n t a d o r A d e l a n t e ( " C o n t a d o r + " );
S y s t e m . o u t . p r i n t l n ( " P u l s e [ E n t r a r ] p a r a f i n a l i z a r );
I n p u t S t r e a m R e a d e r i s = new I n p u t S t r e a m R e a d e r ( S y s t e m . i n ) ;
B u f f e r e d R e a d e r b r = new B u f f e r e d R e a d e r ! i s ) :
try
I
b r .r e a d L i n e ( ); II e j e c u c i n d e t e n i d a hasta pulsar [Entrar]
I
c a t c h ( l O E x c e p t i o n e) I I
// P e r m i t i r a l h i l o c u e n t a A d e l a n t e finalizar
c u e n t a A d e l a n t e . t e r m i n a r ( );
//////////////////////////////////////////////////////////////////
Controlar un hilo
A hora que ya hem os visto cm o realizar una determ inada tarea utilizando un hilo,
podem os deducir fcilm ente que su ciclo de vida evoluciona segn m uestra la fi
gura siguiente:
Finaliz
N uevo j i start C H ilo 1 .1 H ilo e n 1 run H ilo |
------ 1
, hi' J a e te m a o e je c u c i n s m u e rto 1
U n hilo, durante su ciclo de vida est transitando por los estados: nu evo, p r e
parado, en ejecucin, bloqueado y m uerto, estudiados anteriorm ente. El estado en
ejecucin se corresponde en la figura con el bloque hilo en ejecucin , el cual se
alcanza desde el estado preparado al que pasa el hilo despus de que haya sido
C A P T U L O 15: HILOS 647
creado y haber recibido el m ensaje start, y cuando el hilo est vivo y no est en
ejecucin es que est detenido, bloque hilo detenido .
Precisam ente, el m todo isA liv e de T h re a d devuelve true si el hilo que reci
be este m ensaje ha sido arrancado (sta rt) y todava no ha m uerto.
N orm alm ente es el planificador el que controla cundo un hilo debe estar en
ejecucin y cundo pasa a estar detenido, pero en ocasiones tendrem os que ser
nosotros los q ue program em os las circunstancias bajo las cuales un hilo pueda pa
sar a ejecucin, o bien deba pasar de ejecucin a algunos de los estados p rep a ra
d o o bloqueado (bloqueado porque est dorm ido, est esperando a que otro hilo lo
desbloquee, o esperando a que term ine una operacin de E/S, o bien esperando a
apropiarse de un m todo sincronizado).
Preparado
P re p a ra d o
J
"T i yield
E n eje cu c i n
J
El m todo y ie ld es static, por lo tanto, opera sobre el hilo que actualm ente se
est ejecutando. C uando necesite invocarlo basta con que escriba: Thread.yield().
Bloqueado
M uchos m todos que ejecutan operaciones de entrada tienen que esperar por al
guna circunstancia en el m undo exterior antes de que ellos puedan proseguir; este
com portam iento se conoce com o bloqueo. P or ejem plo, la sentencia siguiente lee
un byte de la entrada estndar lanzando un hilo que ejecuta read:
n = S y s t e m . i n . r e a d ( );
Java im plem enta m uchos de los bloqueos que ocurren durante una operacin
de E/S llam ando a los m todos sleep y w ait que vem os a continuacin.
D orm ido
U n hilo dorm ido pasa tiem po sin hacer nada, p o r lo tanto, no utiliza la UCP.
el tiempo acab
o interrupt
U na llam ada al m todo sleep solicita que el hilo actualm ente en ejecucin ce
se durante un tiem po especificado. H ay dos form as de llam ar a este mtodo:
T h r e a d . s i e e p ( mi 1 is e g u n d o s ) ;
T h r e a d . s l e e p (mi 1 isegund os , n a n o s e g u n d o s ) :
Se puede observar que el m todo sleep, igual que yield, es static. Ambos
m todos operan sobre el hilo que actualm ente se est ejecutando.
L a figura anterior indica que cuando un hilo despierta (el tiem po que tena
que dorm ir ha transcurrido) no contina la ejecucin, sino que se m ueve al estado
C A PTU LO 15: H ILOS 6 4 9
Esperando
n o tify /n o tify A II
Planificacin de hilos
M uchos ordenadores tienen slo una UCP, as que los hilos que requieran ejecu
tarse deben com partirla. La ejecucin de m ltiples hilos sobre una nica UCP, en
cierto orden, es llam ada planificacin. La m quina Java (Java R untim e Environ-
m ent - JRE: m quina virtual de Java, incluido el planificador, clases del ncleo
central de Jav a y los ficheros de soporte) soporta un algoritm o de planificacin
determ inista (en cualquier m om ento se puede saber qu hilo se est ejecutando o
cunto tiem po continuar ejecutndose) m uy sim ple, conocido com o fix e d p r io r ity
scheduling (planificacin por prioridad: el hilo que se elige para su ejecucin es el
de prioridad m s alta). Esto es, la planificacin de la U C P es totalm ente por d ere
cho de prioridad (preem ptive).
Lo anteriorm ente expuesto significa que cada hilo Java tiene asignado una
prioridad definida por un valor num rico entre M /N _ P R IO R IT Y y M AX_PR IO -
R IT Y (constantes definidas en la clase T h re a d ), de form a que cuando varios hilos
estn preparados, ser elegido para su ejecucin el de m ayor prioridad. Sola
m ente cuando la ejecucin de ese hilo se detenga por cualquier causa, podr eje
cutarse un hilo de m enor prioridad; y cuando un hilo con prioridad m s alta que el
650 J A V A : C U R S O D E P R O G R A M A C I N
que actualm ente se est ejecutando se m ueva al estado preparado, pasar auto
m ticam ente a ejecutarse.
C uando todos los hilos que com piten p o r la U CP tienen la m ism a prioridad, el
planificador elige para su ejecucin al siguiente segn el orden resultante de apli
car el algoritm o round-robin (no preem ptive). En este caso, la cola de hilos listos
para ejecutarse se trata com o una cola circular FIFO . La U C P ser cedida a otro
hilo bien porque:
R esum iendo, cuando se ejecuta un proceso que tiene varios hilos preparados,
la m quina Java asigna la U C P en funcin de la prioridad que tenga asignada el
hilo activo: de m ayor prioridad a m enor prioridad. En Java, los hilos tienen asig
nadas prioridades de 1 a 10 (10 es la prioridad m s alta: M A X _P R IO R IT Y ). Por
otra parte, cuando el sistem a asigna la U C P a un hilo, trata de igual form a a todos
los hilos de la m ism a prioridad. Esto es, asigna un cuanto al prim er hilo prep a ra
d o de prioridad 10, cuando ste finaliza su intervalo de tiem po, asigna otro cuanto
al siguiente hilo preparado de prioridad 10 y as sucesivam ente. C uando todos los
hilos de prioridad 10 han tenido su intervalo de tiem po, se em pieza otra vez por el
prim ero.
h i l o . s e t P r i o r i t y (nuevaPrioridad) ;
C onstante Valor
M IN _PR10R1TY
N O R M _PR IO R ITY 5 (valor por om isin)
M A X _PR IO R ITY 10
i nt p = g e t P r i o r i t y ( ) :
652 JA V A: C U R SO D E PROGRAM A CIN
El valor que devuelve este m todo est com prendido entre M N _P R I()R IT Y y
M AX _PR IO R ITY.
El siguiente ejem plo im plem enta una aplicacin que visualiza n contadores.
Por ejem plo, para 2 contadores la pantalla m ostrara una lnea con el siguiente
formato: nom bre del hilo, prioridad y cuenta.
C ada contador es un hilo. Las prioridades asignadas a cada hilo son diferentes
(2, 3, etc.). La clase que da lugar a cada objeto hilo contador es la siguiente:
// O t r o s m t od o s
I
El m todo r u n de la clase sim plem ente genera, cuenta y acum ula 500000
nm eros aleatorios. El m iem bro cuenta es pblico porque otro hilo C uentas utili
zar ese valor para m ostrar el progreso de cada uno de los contadores.
La clase C uentas se im plem enta tam bin com o un hilo encargado de lanzar
las cuentas. Su m todo ru n contiene un bucle que se ejecutar m ientras los hilos
contadores estn vivos; en cada iteracin m ostrar p o r cada hilo contador su nom
bre, prioridad y estado de la cuenta, y esperar durante nM ilisegundos. La priori
dad del hilo C uentas ser (nC uentas+ 2)% Thread.M A X _P R IO R ITY , donde /Cuen
tas es el nm ero de hilos contador. Por ejem plo, para 2 hilos contador la prioridad
del prim er hilo, ContadorfO], ser 2, la del segundo. C o n ta d o r!I], ser 3 y la del
hilo de la clase Cuentas, 4. De esta form a, m ientras el hilo C uentas duerm e los
hilos contador com piten por la U C P (lgicam ente finalizar antes la cuenta el de
m ayor prioridad) y cuando despierte, por ser el hilo de m ayor prioridad obtendr
inm ediatam ente la U CP y m ostrar los resultados actuales de las cuentas. A con
tinuacin se m uestra el cdigo correspondiente a esta clase:
CA PTU LO 15: HILOS 6 5 3
public C uentasint n)
I
n C u e n t a s = n: // n me r o de h i l o s c o n t a d o r e s
// E s t a b l e c e r l a p r i o r i d a d de e s t e hilo
s e t P r i o r i t y n C u e n t a s + 2 I X T h r e a d . H A X _ P R 1 0 R I T Y );
// C r e a r y e s t a b l e c e r l a s p r i o r i d a d e s de l o s hilos contador
c u e n t a = new C o n t a d o r [ n C u e n t a s ] :
f o r ( i n t i = 0; i < n C u e n t a s : i + + )
I
c u e n t a [ i ] = new C o n t a d o r O ;
cuenta [ i ] . s e t P r i o r i t y ( ( i + 3 U T h r e a d .MAX_PRI0RITY -1 );
// M o s t r a r e l nombre y l a p r i o r i d a d d e e s t e h i l o
S y s t e m . o u t . p r in t ln ( t h i s .getName) + P-" +
t h i s . g e t P r i o r i t y ( ));
// L a n z a r l o s h i l o s c o n t a d o r e s p a r a s u e j e c u c i n
f o r ( i = 0; i < n C u enta s; i+ + )
c u e n t a [ i ] . s t a r t ( );
do
[
// M o s t r a r nombre d e l h i l o , p r i o r i d a d y e s t a d o de l a c u e n t a
f o r ( i = 0: i < n C u e n t a s : i + + )
S y s t e m . o u t . p r in t c u e n t a [ i] .getName) +
P " + c u e n t a [ i ] . g e t P r i o r i t y ( ) + " " +
c u e n t a [ i] .cuenta + " ) :
S y s t e m . o u t . p r i n t \ r " ) :
// H a y h i l o s v i v o s ?
h a y a H i l o s V i v o s = c u e n t a [ 0 ] . i s A l i v e );
f o r ( i = 1; i < n C u e n t a s : i + + )
h a y a H i l o s V i v o s = h a y a H i 1o s V i v o s || c u e n t a [ i ] . i s A l i v e );
// A h o r a e l h i l o d o r m i r n M i 1 i s e g u n d o s . m i e n t r a s l o s h i l o s
// c o n t a d o r e s s i g u e n s u c u r s o ,
try
int nMi 1 i s e g u n d o s = ( i n t ) l ) * M a t h . pow 2 . n C u e n t a s ) ) :
654 JA V A : C U R S O D E P R O G R A M A C I N
s i e e p ( n M i 1i s e g u n d o s ) ;
1
catch ( I n t e r r u p t e d E x c e p t i o n e) 1 I
I
while ( h a y a H i 1o s V i v o s ):
SINCRONIZACIN DE HILOS
En los ejem plos que hem os visto hasta ahora cada hilo contena todo lo que nece
sitaba para su ejecucin: datos y m todos. A dem s, cada uno de ellos se poda
ejecutar sin que interfiriera en la ejecucin de cualquier otro hilo que se ejecutara
concurrentem ente con l. E stam os en el caso de h ilos independientes.
Sin em bargo, hay m uchas situaciones en las que dos o m s hilos ejecutndose
concurrentem ente deben acceder a los m ism os recursos y/o datos. C om o ejem plo,
im agine la situacin donde dos hilos acceden al m ism o fichero de datos; un hilo
CA PTU LO 15: HILOS 6 5 5
puede escribir en el fichero m ientras el otro sim ultneam ente lee del m ism o. Es
tam os en el caso de h ilos cooperantes. Este tipo de situacin puede crear resulta
dos im predecibles, adem s de indeseables. En estos casos, sim plem ente se debe
tom ar el control de la situacin y asegurar que cada hilo acceda a los recursos de
una m anera previsible, sincronizando las actividades que desarrollan cada uno de
ellos. P ara realizar operaciones de sincronizacin Java proporciona los siguientes
elem entos de sincronizacin: secciones crticas, w a it y notify.
En general un hilo se sincroniza con otro hilo ponindose l m ism o a dorm ir.
N o obstante, antes de ponerse a dorm ir, debe poner en conocim iento del sistem a
qu evento debe ocurrir para reanudar su ejecucin. D e esta form a, cuando se
produzca ese evento, el sistem a despertar al hilo perm itindole continuar la eje
cucin. Por ejem plo, si un hilo padre necesita esp erar hasta que uno o m s hilos
hijo finalicen, se pone l m ism o a dorm ir hasta que el hilo o hilos hijo pasen al
estado m uerto.
Secciones crticas
S upongam os una aplicacin en la que dos hilos de un proceso acceden a una nica
m atriz de datos con la intencin de registrar los resultados obtenidos durante un
experim ento. El program a podra sim ularse as:
C ream os un objeto datos que envuelva una m atriz unidim ensional con el pro
psito de alm acenar los datos adquiridos a travs de una tarjeta que acta co
m o interfaz entre nuestra aplicacin y el m edio utilizado para realizar el
experim ento. En nuestro ejem plo, sim ularem os cada uno de los datos adquiri
dos con un valor obtenido a partir de unos sencillos clculos.
C ream os uno o m s hilos para que tom en los datos y los vayan alm acenando
en la m atriz hasta llenarla, instante en el que su ejecucin finalizar.
Im plem entem os una clase C D atos para m anipular una m atriz unidim ensional
de tipo d o u b le con n elem entos. D icha clase incluir los atributos:
y los m todos:
656 J A V A : C U R S O D E P R O G R A M A C I N
public c la ss COatos
I
// A t r i b u t o s
p r iv a t e d o u b le [] dato:
p r i v a t e i n t i n d = 0:
p u b l i c i n t ta mao:
// M t o d o s
p u b l i c C D a t o s d n t n)
I
i f ( n < 1 ) n - 10:
t a ma o = n;
d a t o - new d o u b l e [ n ] ;
Uno o m s hilos sern los encargados d e adquirir los datos. Q uiere esto decir
que cuando se lancen estos hilos, el constructor de cada uno de ellos debe de reci
b ir com o argum ento el objeto C D atos donde sern alm acenados los datos que se
CA PTU LO 15: HILOS 6 5 7
adquirirn, ejecutando el m todo clculos del objeto C D atos. La clase de los hilos
aludidos puede ser as:
do
I
i - m .clculos(getNam e()): // a d q u i r i r d a t o s
I
w h i 1e ( i < m.tamao);
Para lanzar los hilos que adquirirn los datos, im plem entarem os una aplica
cin com o la siguiente:
public c la ss Test
1
public static void m a in (S trin g [] args)
I
C D a t o s d a t o s = new C D a t o s ( l O ) ;
C A d q u i r i r D a t o s a d q u i r i r D a t o s _ 0 = new C A d q u i r i r D a t o s ( d a t o s ) ;
a d q u i r i r D a t o s _ 0 . s t a r t ( ):
I
1
Thread-0 tom l a m u e s t r a 8
Thread-0 tom l a m u e s t r a 9
O bservando los resultados vem os que todo se ha desarrollado norm alm ente.
M odifiquem os la aplicacin Test para que ahora utilice dos hilos en lugar de uno,
para adquirir los datos:
C AdquirirDatos a d q u i r i r D a t o s _ 0 = new C A d q u i r i r D a t o s ( d a t o s );
C AdquirirDatos a d q u i r i r D a t o s _ l = new C A d q u i r i r D a t o s ( d a t o s );
a d q u i r i r D a t o s _ 0 . s t a r t ( ):
adqui r i r D a t o s _ l . s t a r t ( ) :
T h r e a d - 0 tom l a m u e s t r a 0
T h r e a d - 0 tom l a m u e s t r a 1
T h r e a d - 0 tom l a m u e s t r a 2
T h r e a d - 1 tom l a m u e s t r a 0
T h r e a d - 1 tom l a m u e s t r a 4
T h r e a d - 0 tom l a m u e s t r a 4
T h r e a d - 1 tom l a m u e s t r a 5
T h r e a d - 0 tom l a m u e s t r a 6
T h r e a d - 1 tom l a m u e s t r a 7
T h r e a d - 0 tom l a m u e s t r a 9
T h r e a d - 1 tom l a m u e s t r a 9
j a v a . l a n g . A r r a y l n d e x O u t O f B o u n d s E x c e p t i o n : 10
at. C D a t o s . a s i g n a r ( C D a t o s . j a v a : 2 1 )
at C D a t o s . c l c u l o s ( C D a t o s . j a v a :29)
a t C A d q u i r i r D a t o s . r u n t C A d q u i r i r D a t o s . j a v a , Com p il e d Code)
ndice del elem ento de la m atriz donde est alm acenada). En cam bio, al ejecutarse
los dos hilos concurrentem ente, s se han dado esos problem as.
1. p u b l i c i n t c l c u l o s S t r i n g h i l o )
2. 1
3. i f ( i nd > - t a ma o ) r e t u r n ta mao;
4. d o u b l e x = M a t h . r a n d o m ( );
5. S y s t e m . o u t . .p r i n t l n ( h i 1 o + " m u e s t r a
6. asignartx. i n d ) ;
7. i nd++:
8. r e t u r n ind;
9. 1
L gicam ente los problem as expuestos aparecen porque dos hilos estn acce
diendo a un m ism o objeto de datos sin ningn sincronism o. Por lo tanto, la forma
de ev itar los problem as planteados es que cuando un hilo est accediendo a ese
objeto de datos, no pueda hacerlo el otro y viceversa. E sta seccin de cdigo que
en un instante determ inado tiene que acceder exclusivam ente a un objeto de datos
com partido, recibe el nom bre de seccin crtica.
En Java, cada objeto tiene un m onitor (tam bin llam ado cerrojo lock). En un
instante determ inado, ese m onitor es controlado, com o m ucho, por un solo hilo.
El m onitor controla el acceso al cdigo sincronizado del objeto; en o tras palabras,
a la seccin crtica.
Si ahora ejecuta de nuevo la aplicacin Test com probar que todo funciona
com o esperbam os.
Un hilo que quiera ejecutar el cdigo sincronizado de un objeto debe prim ero
intentar adquirir el control del m onitor d e ese objeto. Si el m onitor est disponi
ble, esto es, si no est controlado p o r o tro hilo, entonces lo adquirir y ejecutar el
cdigo sincronizado y cuando finalice liberar el m onitor. E n cam bio, si el m oni
tor est controlado p o r otro hilo, entonces el hilo que lo intent se bloquear y
slo reto m ar al estado preparado cuando el m onitor est disponible.
e n tra r e n el cdigo
s incron izad o
E n eje cu c i n
m o n ito r n o o b te n id o
U na seccin crtica puede ser tam bin un bloque de cdigo que se ejecuta so
bre un determ inado objeto. En este caso, la seccin crtica se delim ita as:
synchronized ( objeto)
I
II C d i g o que s e e j e c u t a sobre objeto
I
CA PTU LO 15: HILOS 6 6 1
Si aplicam os esta segunda tcnica sobre el ejem plo anterior, podem os elim i
nar el m todo clculos de la clase C D atos y reescribir el m todo r u n de la clase
C AdquirirD atos as:
p u b l i c C A d q u i r i r D a t o s ( CDatos mdatos) // c o n s t r u c t o r
I
m = mdatos:
synchronized (m)
1
i f ( m . i n d > - m.tamao) r e t u r n :
x - M a t h . r a n d o m t );
S y s t e m . o u t . p r i n t l n ( g e t N a m e ( ) + " tom l a m u e s t r a " + m.ind):
m .a sig n a rx , m.ind):
m.ind++:
O bserve que el cdigo anterior exige que el atributo in d de C D atos sea pbli
co. En la versin anterior era privado.
synchronized (m)
1
do
(
i f ( m .i n d >= m.tamao) r e t u r n :
x - M a t h . r a n d o m t );
S y s t e m . o u t . p r i n t l n ( g e t N a m e ) + " tom l a m u e s t r a " + m.ind):
m .a sign a r(x , m.ind):
662 JA V A : C U R S O D E P R O G R A M A C I N
m. i n d + + ;
I
while (m .ind < m.tamao):
I
M onitor reentrante
public c la ss CDatos
I
II ...
La m quina Java perm ite a un hilo volver a tom ar el control de un m onitor del
que ya lo tiene, porque los m onitores Java son reentrantes. Esto slo funcionar
en sistem as que soporten m onitores reentrantes.
H em os visto que las secciones crticas son m uy fciles de utilizar, pero slo se
pueden em plear para sincronizar hilos involucrados en una nica tarea; en el
ejem plo anterior la tarea era nica: alm acenar datos en una m atriz. L os m todos
w a it y n o tify proporcionan una alternativa m s para com partir un objeto, pero
con la diferencia de que perm iten sincronizar hilos involucrados en tareas distin
tas, una dependiente de la otra. Piense, por ejem plo, en un sistem a que cada vez
que genera un m ensaje lo encapsula en un objeto C M ensaje con el fin de m ani
pularlo. En este caso, las tareas involucradas sobre el objeto C M ensaje son: una,
alm acenar el m ensaje generado y otra, obtener el m ensaje alm acenado para m os
trarlo. C laram ente se ve que una tarea depende de la otra; evidentem ente, un m en
saje no puede ser m ostrado si antes no se ha producido.
public ProductorCMensaje c) // c o n s t r u c t o r
I
m e n s a j e = c:
nmeroMsj = ( i n t ) ( M a t h . r a n d o m ) * 100);
m e n s a j e . a l m a c e n a r n m e r o M s j ) : // a l m a c e n a e l m e n s a j e
System .out.println"Productor " + getName) +
" almacena el mensaje # + nmeroMsj);
try
I
i n t msegs = ( i n t ) ( M a t h . r a n d o m ) * 100):
// P o n e r a d o r m i r e l h i l o h a s t a que s e p r o d u z c a el
// s i g u i e n t e m e n s a j e ,
sleep m segs);
I
catch ( In t e rru p t e d E x c e p t io n e) I )
p u b lic ConsumidorCMensaje c) // c o n s t r u c t o r
I
m en sa j e = c:
w hile (true)
I
msj = m e n s a j e . o b t e n e r ) : // o b t i e n e e l l t i m o m e n s a j e
S y s t e m . o u t .p r in t ln ( "C o n s u m id o r + getName) +
obtuvo: " + m s j ):
U na aplicacin que lance los hilos productor y consum idor y m uestre los re
sultados que producen puede ser la siguiente:
public c la ss Test
666 J A V A : C U R S O D E P R O G R A M A C I N
public static v o i d ma i n ( S t r i n g [ D a r g s )
I
C M e n s a j e m e n s a j e = new C M e n s a j e O :
P r o d u c t o r p r o d u c t o r l = new P r o d u c t o r ( m e n s a j e ) :
C o n s u m i d o r c o n s u m i d o r l = new C o n s u m i d o r ( m e n s a j e ) ;
p r o d u c t o r l . s t a r t ( );
c o n s u m i d o r l . s t a r t ( ):
C uando ejecute la aplicacin anterior, tenga presente que los hilos productor y
consum idor trabajarn indefinidam ente. P or lo tanto, para detener la ejecucin
tendr que pu lsar las teclas C trl+C . E n lugar de esto, podram os haber utilizado la
tcnica m ostrada en el apartado F inalizar un hilo . N o lo hem os hecho para no
com plicar el cdigo y centrarnos en el tem a de sincronizacin. U na v ez que haya
ejecutado la aplicacin, observar resultados anlogos a los siguientes:
entrar en el cdigo - E s p e ra n d o 1. J R ln n u o a d n 1
sincronizado 1
E n e je c u c i n j
| mitoTr^^ notify/notifyAII
tiempo excedido
interrupt
CA PITU LO 15: HILOS 6 6 7
v o i d w a i t ( O ? / isegu nd os . n a n o s e g u n d o s ] ] )
Precisam ente, una de las diferencias entre sleep y w ait es que el prim ero,
cuando es llam ado, no cede el control del m onitor, m ientras que el segundo s.
El m todo n o tify A Il, a diferencia de notify, despierta todos los hilos que es
tn esperando por el m onitor que controla el acceso al cdigo sincronizado de un
objeto. Igualm ente, los hilos despertados com petirn de la m anera habitual por
adquirir la UCP con el resto de los hilos que estn en el estado preparado.
Evidentem ente, el m todo notify es m s rpido que n o tify A Il, pero su form a
de proceder nos puede conducir a situaciones no deseadas cuando hay varios hilos
esperando en el m ism o objeto. En este caso, rara vez se utiliza, y p o r seguridad se
sugiere utilizar n o tify A Il.
II ...
I
A hora, cuando el hilo productor adquiera el control del m onitor del objeto
C M ensaje y ejecute el m todo sincronizado a lm acenar, lo prim ero que har ser
interrogar el atributo disponible. Si su valor es tru e , el hilo se pondr a dorm ir
hasta que se m uestre el ltim o m ensaje producido y cede el control del m onitor, y
si vale false, alm acena el nuevo m ensaje, cam bia el atributo disponible a tru e , e
invoca a notifyA U para despertar a todos los hilos que estn esperando p o r este
monitor.
A sim ism o, cuando el hilo consum idor adquiera el control del m onitor del ob
je to C M ensaje y ejecute el m todo sincronizado obtener, lo prim ero que har ser
interrogar el atributo disponible. Si su valor es false, el hilo esperar hasta que
haya un m ensaje cediendo el control del m onitor, y si su valor es tru e , cam bia el
atributo disponible a false, invoca a notifyA U para despertar a todos los hilos que
estn esperando por este m onitor y retom a el m ensaje.
CA PTU LO 15: H ILOS 6 6 9
public c la ss Test
I
public static void m a in (S trin g [] args)
(
C M e n s a j e m e n s a j e = new C M e n s a j e O :
P r o d u c t o r p r o d u c t o r l = new P r o d u c t o r ( m e n s a j e );
C o n s u m i d o r c o n s u m i d o r ] = new C o n s u m i d o r ( m e n s a j e ) :
C o n s u m i d o r c o n s u m i d o r 2 = new C o n s u m i d o r ( m e n s a j e ) :
670 JA V A : C U R S O D E P R O G R A M A C I N
p r o d u c t o r l , s t a r t ( );
c o n s u m i d o r l . s t a r t ( ):
c o n s u m i d o r 2 . s t a r t ( );
A continuacin edite los m todos alm acenar y obtener, y cam bie las senten
cias w hile p o r if:
Productor T h r e a d - 0 a l m a c e n a : m e n s a j e #14
Consumidor Thread-1 obtuvo: m e n s a j e #14
Consumidor Thread-2 obtuvo: m e n s a j e #14
Interbloqueo
A nteriorm ente dijim os que la inanicin (starvation) ocurre cuando un hilo se que
da com plem ente bloqueado y no puede progresar porque no puede acceder a los
CA PTU LO 15: H ILOS 6 7 1
recursos q ue necesita; si esto ocurre entre dos o m s hilos porque esperan por una
condicin recproca que nunca puede ser satisfecha, estam os en un caso de inter-
bloqueo (deadlock: algunos autores prefieren denom inarlo abrazo m ortal). Por
ejem plo dos hilos necesitan im prim ir un docum ento alm acenado en el disco, para
lo que necesitan los recursos disco e im presora. Puesto que los hilos se estn eje
cutando paralelam ente, suponga que uno ya ha adquirido el disco y el otro la im
presora. E sto significa que am bos hilos quedarn bloqueados, cada uno de ellos
esperando por el recurso que tiene el otro.
GRUPO DE HILOS
C ada hilo Jav a es un m iem bro de un grupo de hilos. E ste grupo puede ser el pre
definido por Java o uno especificado explcitam ente. Los grupos de hilos propor
cionan un m ecanism o p ara agrupar varios hilos en un nico objeto con el fin de
poder m anipularlos todos de una vez; p o r ejem plo, poder interrum pir un grupo de
hilos invocando una sola vez al m todo in te r r u p t. A su vez, un grupo de hilos
tam bin puede pertenecer a otro grupo, form ando una estructura en rbol. Desde
el punto de vista de esta estructura, un hilo slo tiene acceso a la inform acin
acerca de su grupo, no a la de su grupo padre o de cualquier otro grupo.
Java proporciona soporte para trabajar con grupos de hilos a travs de la clase
T h re a d G ro u p del paquete lang.
Grupo predefinido
C uando cream os un hilo sin especificar su grupo en el constructor. Java lo coloca
en el m ism o grupo (grupo actual) del hilo bajo el cual se crea (hilo actual).
Despus, cada hilo consum idor que es creado es aadido al grupo actual que
hem os denom inado consum idores.
672 JA V A : C U R S O D E P R O G R A M A C I N
Finalm ente, m s adelante, se enva al grupo actual el m ensaje list con el obje
tivo de escrib ir inform acin acerca del grupo de hilos. O tros m todos puede ver
los en la docum entacin proporcionada con el JDK.
public c la ss Test
I
public static void m a in (S trin g [] args)
I
ThreadGroup c o n su m id o re s =
T h r e a d . c u r r e n t T h r e a d ( ) . g e t T h r e a d G r o u p ( );
C M e n s a j e m e n s a j e = new C M e n s a j e ! ):
P r o d u c t o r p r o d u c t o r l = new P r o d u c t o r ( m e n s a j e ) ;
C o n s u m i d o r c o n s u m i d o r l = new C o n s u m i d o r t m e n s a j e , c o n s u m i d o r e s ,
"consumi d o r l " ) ;
C o n s u m i d o r c o n s u m i d o r 2 = new C o n s u m i d o r ( m e n s a j e , c o n s u m i d o r e s ,
" c o n s u m i d o r 2 " );
consumidores . l i s t O ;
II...
1
S iguiendo con el ejem plo anterior, vem os que cuando se invoc al constructor
C onsum idor se pasaron tres argum entos: un objeto C M ensaje, el grupo de hilos y
el nom bre del hilo que se desea aadir al grupo. S egn esto, el constructor de esta
clase ser com o se indica a continuacin:
Grupo explcito
Para aadir un hilo a un determ inado grupo prim ero crearem os el grupo y despus
procederem os de la m ism a form a explicada en el apartado anterior. Por ejem plo,
si en el ejem plo anterior en lugar de utilizar el grupo predefinido p o r Java quisi
ram os definir explcitam ente un grupo referenciado por la variable consum idores
y denom inado tam bin consum idores, la prim era lnea del m todo m a in la susti
tuiram os por la som breada en el cdigo m ostrado a continuacin:
public c la ss Test
I
public static void m a in (S trin g [] args)
(
ThreadGroup c o n su m id o re s - new T h r e a d G r o u p ( " c o n s u m i d o r e s " ):
II...
TUBERIAS
B sicam ente una tubera es utilizada para canalizar la salida de un hilo (puede ser
el hilo principal de un program a en ejecucin) hacia la entrada de otro. De esta
form a los hilos pueden com partir datos sin tener que recurrir a otros elem entos
com o, por ejem plo, ficheros tem porales o m atrices.
1
lpi
P ip e d R e a d e r P ip e d W rite r
si se cerrara un extrem o se interrum pira el flujo. Esto m ism o ocurre con los flujos
que denom inam os tuberas.
P i p e d W r i t e r e m i s o r - new P i p e d W r i t e r ( ) ;
P i p e d R e a d e r r e c e p t o r = new P i p e d R e a d e r ( e m i s o r ) ;
o bien:
P i p e d R e a d e r r e c e p t o r = new P i p e d R e a d e r t ):
P i p e d W r i t e r e m i s o r = new P i p e d W r i t e r ( r e c e p t o r ):
Por ejem plo, pensem os en una lista de objetos, relacionados con alum nos que
cursan una determ inada asignatura, que deseam os ordenar para despus obtener
una lista de los aprobados. Sin tuberas, el program a tendra que alm acenar los re
sultados entre cada paso en algn lugar, p o r ejem plo, en m atrices:
Lista
de
m e n s a je s
C A P T U L O 15: HILOS 6 7 5
En prim er lugar vam os a m ostrar la aplicacin que lanzar los hilos productor
y consum idor:
import j a v a . i o . * ;
p u b lic c l a s s Test
I
public s t a t ic void m a in (S trin g [] args)
I
try
I
P i p e d W r i t e r e m i s o r = new P i p e d W r i t e r ( );
P i p e d R e a d e r r e c e p t o r = new P i p e d R e a d e r ( e m i s o r ) ;
P r o d u c t o r p r o d u c t o r l = new P r o d u c t o r ( e m i s o r ):
C o n s u m i d o r c o n s u m i d o r l = new C o n s u m i d o r ! r e c e p t o r ):
p r o d u c t o r l . s t a r t ( );
c o n s u m i d o r l . s t a r t ):
I
catch (IOException ignorada) II
import j a v a . i o . * :
pu blic c la s s Productor extends Thread
I
private PipedW riter emisor = n u il ;
676 JA V A : C U R S O D E P R O G R A M A C I N
p u b l i c P r o d u c t o r ( P i p e d W r i t e r em) // c o n s t r u c t o r
I
e m i s o r = em:
f l u j o S = new P r i n t W r i t e r ( e m i s o r );
I
publi c void r u n ( )
I
w hile (true)
(
a l m a c e n a r M e n s a j e t ):
try
I
i n t msegs = ( i n t ) ( M a t h . ra n d o m t ) * 1 0 0 ):
// P o n e r a d o r m i r el h i l o h a s t a q u e s e p r o d u z c a el
// s i g u i e n t e m e n s a j e ,
s l e e p m s e g s );
I
catch ( InterruptedException e) I I
nmeroMsj = ( i n t ) ( M a t h . r a n d o m ) * 1 0 0 ) :
// S u p o n e r o p e r a c i o n e s p a r a b u s c a r e l m e n s a j e en una t a b l a
// d e m e n s a j e s : r e s u l t a d o :
t e x to M e n s a je = "mensaje # " + nmeroMsj:
f l u j o S . p r i n t l n ( t e x t o M e n s a j e ) : // e n v i a r m e n s a j e p o r l a t u b e r a
System .out.println"Productor " + getNamet) +
" almacena: " + t e x t o M e n s a j e ) :
p r o t e c t e d v o i d f i n a l i z e O th rows IO E x c e p t io n
i
i f ( f l u j o S != n u i l ) I f l u j o S . c l o s e ( ): f l u j o S = n u i l ; I
i f ( e m i s o r != n u i l ) I e m i s o r .e l o s e ( ): e m i s o r = n u i l : )
Finalm ente, m ostram os la clase correspondiente al hilo consum idor. E sta cla
se tiene un atributo receptor, que referenciar el extrem o de la tubera desde el
cual el hilo consum idor obtendr los m ensajes. Este atributo ser establecido por
el constructor de la clase.
C A PTU LO 15: HILOS 6 7 7
P ara obtener los m ensajes, el m todo ru n del hilo consum idor crea un flujo
(flu jo E ) de la clase B u ffe re d R e a d e r desde el extrem o receptor. Este flujo perm i
tir utilizar el m todo re a d L in e , que P ip e d R e a d e r no tiene, para obtener los
m ensajes enviados por el productor. C uando no haya ningn m ensaje, sim ple
m ente el hilo que ejecuta el m todo re a d L in e queda bloqueado.
import j a v a . i o . * ;
p u b li c c l a s s Consumidor extends Thread
receptor - nuil
p riv a t e BufferedReader flu jo E = n u il :
S t r i n g msj = n u l 1 :
try
e ( ) ; // o b t e n e r m e n s a j e d e l a tubera
S y s t e m .o u t .p r in t ln ("C o n s u m id o r " + getNameO +
" obtuvo: " + m s j ):
EJERCICIOS RESUELTOS
1. R ealizar una aplicacin que utilice dos hilos, un productor y un consum idor, tra
bajando sobre una nica m atriz de enteros positivos. E sto es, un hilo productor
generar enteros que alm acenar en una m atriz circular y un hilo consum idor ob
tendr de esa m atriz los enteros generados por el productor. M uchas aplicaciones
de la vida ordinaria reproducen este problem a. U n ejem plo es el adm inistrador de
im presin en un servidor de red; los productores son los usuarios de la red y el
consum idor la im presora o im presoras.
quear la m atriz slo m ientras se est insertando un d ato y el consum idor lo har
slo m ientras se est extrayendo. C uando la m atriz est vaca, el hilo consum idor
se pondr a esperar hasta que haya datos. A sim ism o, cuando la m atriz est llena,
el hilo productor se pondr a esperar hasta que haya elem entos libres.
La m atriz que alm acenar los datos ser un objeto de la clase C M atriz. Esta
clase estar form ada p o r los atributos:
m M atriz de n enteros positivos.
indP rod ndice del elem ento donde el productor debe insertar el si
guiente elem ento. Su valor ser: 0, I, 2, ..., n-1, 0, 1, 2 ,...
indC ons ndice del elem ento donde el consum idor debe obtener el si
guiente elem ento. Su valor ser: 0, 1, 2, ..., n-1, 0, 1, 2 ,...
elem entosV acos N m ero de elem entos vacos en un instante determ inado.
elem entosLlenos N m ero de elem entos llenos en un instante determ inado.
y p o r los m todos:
alm acenar A lm acena un dato en el siguiente elem ento vaco.
obtener O btiene el siguiente dato an no extrado.
//////////////////////////////////////////////////////////////////
// S i n c r o n i z a c i n de h i l o s : wait y n o tify .
//
publi c c la s s CMatri z
I
private i n t [ ] m;
private i n t i n d P r o d = 0 ; // I n d i c e p r o d u c t o r
private i n t i n d C o n s = 0 : // I n d i c e c o n s u m i d o r
private in t elem entosVacios, elementosLlenos:
catch ( In te r r u p te d E x c e p tio n e) I I
I
e l e m e n t o s V a c o s - ;
elementosLle nos-H-;
S y s t e m . o u t . p r i n t ( vac1 o s : " + e l e m e n t o s V a c o s + " , llenos: " +
elementosLlenos + " \r"):
m [ i n d P r o d ] - num;
i n d P r o d - ( i n d P r o d + 1) % m . l e n g t h ;
II D e s p e r t a r h i l o s ;
noti f y A l 1();
//////////////////////////////////////////////////////////////////
En el problem a del productor y del consum idor los recursos que estos hilos
deben adquirir para poder ejecutarse son los elem entos vacos y los elem entos lle
nos de la m atriz, respectivam ente. C ada uno de estos tipos de recursos los repre
sentarem os por sendas variables que actuarn com o sem foros: elem entosLlenos y
e lem en tos Vacos. Un valor cero equivale a sem foro en rojo y un v alor distinto de
cero a sem foro en verde.
elem entosLlenos es un sem foro inicialm ente en rojo para el consum idor
(porque no hay ningn elem ento lleno, esto es, no se puede obtener) que repre
senta los elem entos actualm ente llenos de la m atriz y elem entosV acos es un se
m foro inicialm ente en verde para el productor (porque todos los elem entos estn
vacos, esto es, se puede alm acenar) que representa los elem entos actualm ente
CA PTU LO 15: H ILOS 6 8 1
II e l e m e n t o s V a c o s e s e l s e m f o r o p a r a e l productor
w h i l e '( e l e m e n t o s V a c o s = = 0)
I
try
1
wa i t ( ) ; // e l hilo s e po ne a d o r m i r y c e d e e l monitor
I
catch ( InterruptedException e) I )
)
ele m ento sV ac o s - -:
el ementosLlenos-H-;
m f i n d P r o d ] = num:
i n d P r o d - ( i n d P r o d + 1) % m.length;
noti f y A l1();
Segn los expuesto, el hilo productor bsicam ente se lim itar a llam ar al m
todo a lm acenar de la clase C M atriz. Esto es:
//////////////////////////////////////////////////////////////////
II S i n c r o n i z a c i n de h i l o s . H ilo productor.
//
public class P ro d u c to r exten ds Thread
I
private CMatriz m atriz;
private boolean c o n t in u a r = tru e :
public P r o d u c t o r ( C M a t r i z m) // c o n s t r u c t o r
682 JA V A : C U R S O D E P R O G R A M A C I N
m atriz - m:
publi c voi d r u n ( )
I
int n me r o : // n me r o p r o d u c i d o
while (continuar)
(
n me r o - ( i n t ) ( M a t h . r a n d o m ) * 1 0 0 ) :
m a t r i z . a l m a c e n a r ( n m e r o ) : // a l m a c e n a e l n mero
//System .out.println"Productor " + getNameO +
// " a l m a c e n a : n mero " + n m e r o ) :
//////////////////////////////////////////////////////////////////
A nlogam ente, el hilo consum idor bsicam ente se lim itar a llam ar al m todo
o btener de la clase C M atriz. Esto es:
//////////////////////////////////////////////////////////////////
// S i n c r o n i z a c i n de h i l o s . H ilo consumidor.
//
public class Consumidor extends Thread
(
p riva te CMatriz m atriz:
p r iv a t e boolean c o n tin u a r = true:
public C o n s u m i d o r ( C M a t r i z m) // c o n s t r u c t o r
I
m a t r i z = m;
P ara probar el com portam iento de am bos hilos puede servir la aplicacin si
guiente:
import j a v a . i o . * :
//////////////////////////////////////////////////////////////////
// S i n c r o n i z a c i n de h i l o s .
//
public class Test
I
public static void m a in ( S t r in g [ ] args)
(
C M a t r i z m a t r i z = new C M a t r i z ( l O ) :
P r o d u c t o r p r o d u c t o r l = new P r o d u c t o r t m a t r i z ) ;
C o n s u m i d o r c o n s u m i d o r l = new C o n s u m i d o r m a t r i z ):
I n p u t S t r e a m R e a d e r i s - new I n p u t S t r e a m R e a d e r S y s t e m . i n ) ;
B u f f e r e d R e a d e r b r = new B u f f e r e d R e a d e r i s );
try
1
b r . r e a d L i n e ) : // e j e c u c i n d e t e n i d a hasta pulsar [Entrar]
// I n i c i a r l a e j e c u c i n d e l o s h i l o s
p r o d u c t o r l . s t a r t t ):
c o n s u m i d o r l . s t a r t { );
b r . r e a d L i n e ( ) : // e j e c u c i n d e t e n i d a hasta pulsar [Entrar]
I
c a t c h ( l O E x c e p t i o n e) I)
// P e r m i t i r a l o s h i l o s f i n a l i z a r
p r o d u c t o r l . t e r m i n a r ( );
consumi d o r l . t e r m i n a r ! );
//////////////////////////////////////////////////////////////////
EJERCICIOS PROPUESTOS
1. E scribir una aplicacin que lance tres hilos que ordenen otras tantas m atrices,
todas de la m ism a dim ensin, utilizando, el prim ero el m todo de ordenacin de
la burbuja, el segundo el de insercin y el tercero el m todo quicksort. V isualizar
684 JA VA: C U R SO D E PRO G R A M A CI N
2. S upongam os una lista de objetos, relacionados con alum nos que cursan una d e
term inada asignatura, que deseam os ordenar para despus obtener una lista de los
aprobados. U tilizando tuberas, podem os plantear la solucin del problem a segn
m uestra la figura siguiente:
C ada o bjeto alum no alm acenar inform acin relativa al nom bre del alum no, al
nom bre de la asignatura y a la nota.
Para obtener el resultado solicitado, los pasos a seguir bsicam ente pueden ser los
siguientes:
1. C rear el fichero con la inform acin de los alum nos ordenada por el nom bre
del alum no.
2. A brir un flujo desde el fichero que perm ita leer la inform acin del m ism o.
3. Invocar a un m todo o rdenar que reciba com o parm etro el flujo abierto en el
punto 2 y devuelva una referencia a un objeto P ip e d ln p u tS tre a m (o a su su-
perclase), que se corresponda con el extrem o de una tubera en la que un hilo
lanzado por este m todo coloque los alum nos clasificados por la nota. Para
realizar la ordenacin, el hilo cargar la inform acin en una m atriz, la ordena
r y despus la volcar en la tubera.
4. Invocar a un m todo aprobados que reciba com o argum ento el flujo de datos
resultante del punto 3 y devuelva una referencia a un objeto P ip e d ln p u tS
tre a m (o a su superclase), que se corresponda con el extrem o de una tubera
en la que o tro hilo lanzado p o r este m todo coloque los alum nos aprobados.
NDICE
aadir un com ponente a un panel, 730
A aadir un elem ento a una m atriz, 297
abstraccin. 32 aplicacin, 11; 63; 264
abstract. 330 append, 187
A ccesibilidad. 723 applet, 8; 11; 707, 705
acceso aleatorio, 457 crear, 705
acceso secuencial, 429; 479 parm etros, 711
accesos directos. 699 A PPLET. etiqueta. 705
A ckerman, 586 appletview er, 10
acos, 115 rbol. 542
A ctionEvent, 729 binario, 543
A ctionListener, 727 binario de bsqueda, 546
actionPerform ed, 728 binario perfectam ente equilibrado, 558
add, 730 recorrer, 544
addA ctionListener, 727 archivo, 420
addA djustm entListener, 727 argum entos, 73
addFocusListener, 728 pasar, 219
addltem Listener, 728 argum entos en la lnea d e rdenes, 221
addK eyListener, 728 A rithm eticException, 148
addM ouseListener, 728 arrastrar y colocar, 723
addM ouseM otionListener, 728 arraycopy, 218
addW indow Listener, 728 A rraylndexO utO fB oundsException, 168
A djustm entListener, 727 A rrays, 233
adm inistrador de interfaz de usuario, 731 ASCII, 765
adm inistradores de diseo, 730 asignacin d e objetos, 274
asignar, 731 asignar un adm inistrador de diseo, 731
algoritm o B oyer y M oore, 602 asin, 1 15
algoritm o d e planificacin determ inista, 649 ASP. 704
algoritm os hash, 616 atan. 115
m bito de una variable. 85 atan2. 115
anidar if, 124 atm icas, operaciones, 660
anidar w hile. do, o for, 136 atrapar la excepcin, 403
anim acin, 718 atributos, 26; 255
ANSI. 763 con el m ism o nom bre, 341
770 JA V A: C U R S O DE PROGRAM A CIN
M static, 291
mtodos, 27; 256
m ail, 692 de una subclase, 340
m ain, 13; 29; 73; 79 en lnea, 371
argum entos, 222 mezcla natural, 606
m anejadores de eventos. 727 m iembro de una clase, 30
M ap, 566 m iem bros del objeto, 77
m quina Java. 649 miembros heredados, 336
mquina virtual. 6 m iem bros que son punteros, 279
m arcos en pginas HTM L, 702 m ilisegundos transcurridos desde el I de enero
mark, 613 de 1970.242
M ath, 114 m in. 115
matrices, 164 M IN JV A LU E. 104
de objetos, 294 m kdir. 436
mtodos. 168 m dem . 692
verificar si son iguales, 234 m odificador, 72
matriz m odificadores de acceso, 257
acceder a un elem ento, 167 monitor, 659; 667
asignar un valor a todos sus elem entos, 234 m onitores reentrantes, 663
asociativa, 172 M ouscListener, 728
buscar un valor. 233 M ouseM otionListener, 728
com o valor retom ado, 217
crear, 166
de cadenas de caracteres. 196
N
de longitud 0. 297 NaN. 104; 206
de objetos String. 203 N E G A T IV E JN E IN IT Y . 104
declarar. 165 new, 73; 74; 79
es un objeto. 166 new A udioClip, 717
multidim ensional. 191 ncw Linc, 613
num rica multidim ensional, 192 new s, 693
ordenar, 235 nivel de proteccin predeterm inado, 77
pasar com o argum ento. 215 nodo de un rbol, 544
sparse, 213 notify. 663; 667
max, 115 notifyA ll, 667
M AX_VALUE, 104 nuil, 43; 111; 203; 498
m em oria para objetos String. 238 NumberFormat, 226
memoria, asignar y liberar. 74 NumberForm atException, 106
m ensaje, 24 nm ero racional, 306
mensajes, 75 nm eros aleatorios, 240
m ensajes en la barra de estado, 718
M essageForm at. 233
Method. 97 O
mtodo. 24; 28; 72 O bject. 92; 97; 168; 235; 287; 509; 758
abreviado, 263 O bjcctlnputStream , 451
abstracto. 330
O bjectO utputStream , 450
consulta dinm ica, 371 objeto, 24
de insercin. 595 aplicacin. 63
de la burbuja. 592 String, crear, 238
d e la clase. 78 tem poral, 309
de quicksort. 596 objetos, guardar/leer en/de un fichero. 449
final, 268 ocultacin de datos, 257
recursivo, 224
sobrecargado. 262
776 JA V A : C U R S O D E P R O G R A M A C I N
operadores, 52 P O S IT IV E JN F IN IT Y , 104
a nivel de bits, 55 PO ST. 740
aritm ticos, 52 postordcn, 544
condicional, 57 pow. 115
de asignacin, 56 predeterm inado, 258
de relacin. 53 preem ptive, 649
instanceof, 530 preorden, 544
lgicos, 54 preparado. 636
new. 73; 74; 79 print, 101
tem ario, 57 println, 13; 26; 101
unitarios, 55 PrintStream , 26; 100
ordenacin. 591 PrintW riter, 102
ordenar un fichero. 605 prioridad de un hilo, 651
utilizando acceso aleatorio, 614 private. 258
out, 13; 26; 96 proceso, 633
OutO M em oryError. 74; 413 proceso ligero, 635
OutputStream , 94 productor-consum idor, 678
program a. 4; 634
program acin orientada a objetos. 23
P proteccin de una clase, 68
package, 305 protected, 258
pgina dinm ica. 703 protocolo, 689
pginas de transferencia de ficheros, 693
ASP, 704 proyecto, 18
JSP, 737 public, 68; 258
web, 695 public. clase, 32
paint, 708 pblica. 67
palabras clave. 47 PushbackR eader. 425
panel de contenido, 730
panel raz. 730
Q
paquete, 67; 303
awt, 710 quicksort, 596
crear, 304
java.io, 421
java.text, 226
R
java.til, 228 racional, 306
proteccin de, 68 raz de un rbol, 544
parm etros, 73 random , 115; 241; 242
de un applet, 711 R andom A ccessFile, 458
pasados por referencia, 83; 215 read. 93; 113; 197; 425
pasados por valor, 83; 215 Reader, 93
parselnt, 104 readLine. 99; 111; 203
pasar argum entos, 82 readUTF, 463
PI. 115 ready. 425; 458
pila, 527 recolector de basura, 75; 279
planificacin, 649 recorrer un rbol, 544
planificador, 637 recursin. 585
planificador de hilos, 641 recursividad, 224
plantillas, 509 recursos, 715
play, 716 redefinir miem bros de la superclase. 343
polimorfismo, 34; 360 reentrantes, m onitores, 663
POO, 23 referencia. 79
POP 2 y 3, 691
A P N D IC E F: N D IC E 7 7 7
C om o veis faltan pginas, si, falta la p a ite de los applets y dem s (paite 3 del libro).
E scan ear est m al, es ilegal, p ero tam b in lo es tener W indows sin com prarlo
U tiliza linux, y vers lo que verdaderam ente se pu d e h a c er con u n sistem a operativo.