Você está na página 1de 704

RESUMEN DEL CONTENIDO

PA R TE 1. PRO G R A M A C I N B SIC A .................................... 1


C A P T U L O 1. FA SES EN EL D E SA R R O L L O DE UN P R O G R A M A .................... 3

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 5. C L A SES DE USO C O M N ...................................................................... 89

C A P T U L O 6. SE N TEN C IA S DE 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

PARTE 2. PRO G R A M A C I N A V AN ZA DA ............................251


C A P T U L O 9. C LA SES Y P A Q U E T E S ............................................................................ 253

C A P T U L O 10. S U B C LA SES E IN T E R F A C E S ............................................................ 329

C A P T U L O 11. E X C E P C IO N E S ......................................................................................... 397

C A PTU L O 12. TR A B A JA R C O N F IC H E R O S ............................................................. 419

C A PTU L O 13. EST R U C T U R A S D IN M IC A S ............................................................ 495


V I I I JA V A: CU R SO DE PROGRAM A CIN

C A PTU L O 14. A L G O R IT M O S .......................................................................................... 585

C A P T U L O 15. H IL O S ............................................................................................................ 633

PARTE 3. PRO G RA M A S PARA IN T E R N E T ......................... 685


C A PTU LO 16. A PA R TIR DE A Q U ............................................................................... 687

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

C. PLA TA FO 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 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

PA R TE I. PRO G RA M A CI N B SIC A ................................... 1

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

M EC A N ISM O S B SIC O S DE LA P O O ..................................................................... 24


O b je to s............................................................................................................................... 24
M ensajes............................................................................................................................ 24
M to d o s............................................................................................................................. 24
C la s e s ................................................................................................................................. 25
C M O C REA R U N A C L A S E DE O B JE T O S ........................................................... 26
C A R A C T E R ST IC A S DE LA P O O ............................................................................... 32
A bstraccin....................................................................................................................... 32
E n cap su lam ien to ............................................................................................................. 33
H e re n c ia ............................................................................................................................ 33
P o lim orfism o.................................................................................................................... 34
C O N ST R U C TO R ES Y D E S T R U C T O R E S................................................................. 34
E JE R C IC IO S R E S U E L T O S ............................................................................................. 34
E JE R C IC IO S P R O PU E ST O S.......................................................................................... 36

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

PRESEN TA CI N DE LA SIN TA X IS DE JA V A ..................................................... 37


C A R A C TER E S D E JA V A ................................................................................................ 38
Letras, dgitos y o tro s .................................................................................................... 38
E spacios en b la n c o ......................................................................................................... 38
C aracteres especiales y signos de p u n tu a c i n ........................................................ 39
S ecuencias de esc a p e ..................................................................................................... 39
T IPO S DE D A T O S .............................................................................................................. 40
Tipos p rim itiv o s.............................................................................................................. 40
b y te................................................................................................................................ 41
sh o rt.............................................................................................................................. 41
i n t .................................................................................................................................. 41
lo n g .............................................................................................................................. 41
c h a r................................................................................................................................ 42
flo a t.............................................................................................................................. 42
d o u b le........................................................................................................................... 43
b o o lean ........................................................................................................................ 43
T ip o s re fere n ciad o s........................................................................................................ 43
L IT E R A L E S ........................................................................................................................... 43
L iterales e n te ro s .............................................................................................................. 44
Literales reales................................................................................................................. 44
Literales de un solo ca rc te r........................................................................................ 45
L iterales de cadenas de c a rac te res............................................................................. 45
ID E N T IFIC A D O R E S.......................................................................................................... 46
C O N T E N ID O X I

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

SEN TEN C IA i f ...................................................................................................................... 121


ANUDAMIENTO D E SEN TEN C IA S if .......................................................................... 124
E STR U C T U R A else i f ......................................................................................................... 126
SEN TEN C IA s w itc h ............................................................................................................. 129
SEN TEN C IA w h ile ............................................................................................................... 133
Bucles an id ad o s................................................................................................................. 136
SEN TEN C IA d o ... w h ile ................................................................................................... 139
SEN TEN C IA f o r .................................................................................................................... 142
SEN TEN C IA b re a k ............................................................................................................... 146
SEN TEN C IA c o n tin u ......................................................................................................... 146
E T IQ U E T A S ........................................................................................................................... 147
SEN TEN C IA S try ... c a tc h .................................................................................................. 148
EJER C IC IO S R E S U E L T O S ............................................................................................... 149
EJER C IC IO S P R O P U E S T O S ............................................................................................ 159
CONTENIDO X I I I

C A P T U L O 7. M A T R IC E S .................................................................................................. 163

IN T R O D U C C I N A LAS M A T R IC E S ....................................................................... 164


M A TR IC ES N U M R IC A S U N ID IM E N S IO N A L E S .............................................. 165
D eclarar una m a triz ....................................................................................................... 165
C rear una m a triz ............................................................................................................. 166
Iniciar una m a triz ........................................................................................................... 167
A cceder a los elem entos de una m atriz..................................................................... 167
M todos de una m a triz .................................................................................................. 168
T rabajar con m atrices u n id im e n sio n a les................................................................. 169
M atrices aso c ia tiv a s....................................................................................................... 172
C A D EN A S DE C A R A C T E R E S ...................................................................................... 175
L eer y escribir una cadena de c a ra c te re s................................................................. 176
T rabajar con cadenas de c a ra c te re s ........................................................................... 178
C lase S trin g ...................................................................................................................... 181
S tring(String v a lo r).................................................................................................. 181
String to S trin g O ........................................................................................................ 182
String concat(S tring s t r ) ......................................................................................... 182
int com pareT o(String o tro S trin g )........................................................................ 182
int lengthQ ................................................................................................................... 184
String to L o w erC ase().............................................................................................. 184
String toU pperC aseO ............................................................................................... 184
String trim O ................................................................................................................ 184
boolean startsW ith(String p re fijo )....................................................................... 184
boolean endsW ith(String s u fijo ).......................................................................... 184
String substring(int Indicelnicial. int In d ice F in a l)......................................... 185
ch ar charA t(int n d ic e )............................................................................................ 185
int indexO ftint c a r)................................................................................................... 185
int indexO fiS tring s tr ) ............................................................................................. 185
String replace(char car, char n u ev o C ar)............................................................ 185
static S tring valueO fitipo d a to )............................................................................ 186
char[] to C h arA rray O ............................................................................................... 186
byte(] getB ytes()........................................................................................................ 186
C lase S trin g B u ffcr.......................................................................................................... 186
S trin g B u ffer([arg ])................................................................................................... 186
int lengthO .................................................................................................................. 187
int capacityO ............................................................................................................... 187
StringB uffer append(tipo x ) .................................................................................. 187
StringB uffer insert(int ndice, tipo x ) ................................................................. 187
StringB uffer delete(int p l , int p 2 ) ....................................................................... 188
StringB uffer replace(int p l, int p2, String s t r ) ................................................. 188
StringB uffer re v e rse Q ............................................................................................. 188
String substring(int Indicelnicial, int In d ice F in a l)......................................... 189
X IV JA V A: C U R SO DE PROGRAM A CIN

ch ar charA t(int n d ic e )............................................................................................ 189


void setC harA t(int ndice, char c a r ) ................................................................... 189
String to S trin g O ....................................................................................................... 189
Clase S trin g T o k en izer................................................................................................... 189
C onversin de cadenas de caracteres a datos n u m rico s.................................... 191
M A TR IC ES DE R EFE R EN C IA S A O B JE T O S ........................................................ 191
M atrices num ricas m ultidim ensionales................................................................... 192
M atrices de cadenas de caracteres............................................................................. 196
M atrices de objetos S trin g ........................................................................................... 203
E JE R C IC IO S R E S U E L T O S ............................................................................................. 205
E JE R C IC IO S P R O P U E S T O S .......................................................................................... 210

C A P T U L O 8. M T O D O S ................................................................................................... 215

PA SA R UNA M A TR IZ C O M O A R G U M E N T O A UN M T O D O ..................... 215


M A T R IZ C O M O V A LO R R ET O R N A D O PO R U N M T O D O ......................... 217
R EFE R E N C IA A UN TIPO P R IM IT IV O .................................................................... 219
A R G U M EN TO S EN LA LN EA DE R D E N E S ..................................................... 221
M TO D O S R E C U R S IV O S .............................................................................................. 224
V ISU A LIZA R DATO S C O N F O R M A T O .................................................................. 225
D ar form ato a n m eros.................................................................................................. 226
L o calid ad ..................................................................................................................... 227
A lin eac i n .................................................................................................................. 228
C lase para form atos n u m ric o s............................................................................ 229
D ar form ato a fechas/horas.......................................................................................... 231
D ar form ato a m en sajes................................................................................................ 233
LA C L A SE A rra y s............................................................................................................... 233
binaryS earch.................................................................. 233
equals.................................................................................. 234
fill........................................................................................................................................ 234
s o rt....................................................................................................................................... 235
LA C L A SE O b je c t............................................................................................................... 235
boolean equals(O bject o b j).......................................................................................... 236
String toStringO ............................................................................................................... 237
void fin alizeO .................................................................................................................. 237
M S S O B R E R E FE R EN C IA S Y O B JE T O S S tr in g ................................................ 238
EJER C IC IO S R E S U E L T O S ............................................................................................. 240
E JER C IC IO S P R O P U E S T O S .......................................................................................... 247
C O N TEN ID O X V

PA R TE 2. PRO G RA M A CI N A V AN ZA DA........................... 251


C A P T U L O 9. C L A S E S Y P A Q U E T E S ......................................................................... 253

D EFIN IC I N DE UN A C L A S E ....................................................................................... 253


A tributos............................................................................................................................ 255
M todos de una c la s e ...................................................................................................... 256
C ontrol de acceso a los m iem bros de la clase.......................................................... 257
A cceso predeterm inado.......................................................................................... 257
A cceso p b lic o ........................................................................................................... 258
A cceso p riv ad o ........................................................................................................... 258
A cceso protegido........................................................................................................ 258
IM PLE M E N TA C I N D E UNA C L A S E ........................................................................ 259
M TO D O S S O B R E C A R G A D O S .................................................................................... 262
IM PL EM E N T A C I N DE UN A A P L IC A C I N ......................................................... 264
C O N T R O L DE A C C ESO A UNA C L A S E ................................................................... 265
R EFE R E N C IA th is................................................................................................................ 266
V A R IA B LE S. M TO D O S Y C LA SES F IN A L E S .................................................... 267
IN IC IA C I N DE UN O B JE T O ........................................................................................ 269
C o n stru cto r......................................................................................................................... 269
S obrecarga del c o n stru c to r............................................................................................ 272
L lam ar a un constructor.................................................................................................. 274
A signacin de o b je to s ..................................................................................................... 274
C onstructor c o p ia ............................................................................................................. 275
D E ST R U C C I N DE O B JE T O S ....................................................................................... 276
D estru cto r........................................................................................................................... 277
E jecutar el recolector de basura.................................................................................... 279
R EFE R EN C IA S C O M O M IEM B R O S DE U N A C L A S E ........................................ 279
C O M PA R A R O B JE T O S .................................................................................................... 287
M todo e q u a ls ................................................................................................................. 287
M IEM B R O S ST A T IC DE UNA C L A S E ...................................................................... 288
A tributos s ta tic .................................................................................................................. 289
A cceder a los atributos s ta tic ........................................................................................ 290
M todos s ta tic ................................................................................................................... 291
Iniciador e s t tic o .............................................................................................................. 292
M A TR IC ES D E O B JE T O S................................................................................................. 294
P A Q U E T E S ........................................................................................................................... 303
C rear un paquete............................................................................................................... 304
UN EJEM PLO DE D ISE O DE UN A C L A S E ...................................................... 306
EJER C IC IO S R E S U E L T O S .............................................................................................. 319
E JER C IC IO S P R O P U E S T O S ............................................................................................ 326
X V I JA V A : C U R SO DE PROGRAM A CIN

C A P T U L O 10. S U B C L A S E S E IN T E R F A C E S ......................................................... 329

C LA SES Y M TO D O S A B S T R A C T O S ..................................................................... 330


SU B C LA SES Y H E R E N C IA .......................................................................................... 331
DEFINIR UNA S U B C L A S E ............................................................................................ 334
C ontrol de acceso a los m iem bros de las clases..................................................... 336
Qu m iem bros hereda una subclase........................................................................... 336
A TR IB U TO S C O N EL M ISM O N O M B R E ................................................................ 341
R E D EFIN IR M TO D O S DE LA S U P E R C L A S E .................................................... 343
C O N ST R U C T O R E S DE LAS S U B C L A S E S .............................................................. 345
D E STR U C TO R E S DE LAS S U B C L A S E S ................................................................. 347
JER A R Q U A DE C L A S E S ............................................................................................... 349
R EFE R E N C IA S A O B JETO S DE UNA S U B C L A S E ............................................. 356
C onversiones im plcitas................................................................................................ 357
C onversiones ex p lcitas................................................................................................ 359
P O L IM O R F IS M O ................................................................................................................ 360
M TO D O S EN L N E A ..................................................................................................... 370
IN T E R F A C E S ....................................................................................................................... 371
D efinir una in te rfa z ....................................................................................................... 371
Un ejem plo: la interfaz IF e c h a ................................................................................... 372
U tilizar una in terfaz....................................................................................................... 374
Clase abstracta frente a in terfaz.................................................................................. 377
U tilizar una interfaz com o un tip o ............................................................................. 378
Interfaces frente a herencia m ltip le ........................................................................ 379
Para qu sirve una in te rfa z .......................................................................................... 380
Im plem entar m ltiples in te rfa c e s.............................................................................. 380
C LA SES A N ID A D A S ....................................................................................................... 381
C lases in tern as................................................................................................................. 382
C lases definidas dentro de un m to d o ...................................................................... 383
C lases an n im as.............................................................................................................. 384
EJER C IC IO S R E S U E L T O S ............................................................................................. 386
EJER C IC IO S P R O P U E S T O S ..................................... 396

C A P T U L O 11. E X C E P C I O N E S ...................................................................................... 397

E X C EPC IO N ES DE JA V A ............................................................................................... 399


M A N EJA R E X C E P C IO N E S ........................................................................................... 401
Lanzar una ex c ep ci n .................................................................................................... 402
A trapar una ex cep ci n ................................................................................................... 402
B LO Q U E DE F IN A L IZ A C I N ....................................................................... 405
D EC LA R A R E X C E P C IO N E S ......................................................................................... 406
C R E A R Y LA N Z A R E X C E P C IO N E S ......................................................................... 408
C O N T E N ID O X V I I

C U N D O U T IL IZA R E X C E PC IO N E S Y C U N D O N O .................................... 413


E JE R C IC IO S R E S U E L T O S ............................................................................................. 413
E JE R C IC IO S P R O P U E S T O S .......................................................................................... 418

C A P T U L O 12. T R A B A JA R C O N F IC H E R O S ......................................................... 419

V ISI N G E N E R A L D E LOS FLU JO S D E E /S ......................................................... 421


Flujos q ue no procesan los datos de E /S ................................................................... 422
Flujos q ue procesan los datos de E /S ........................................................................ 424
A B R IEN D O FIC H ER O S PARA A C C ESO S E C U E N C IA L .................................. 429
Flujos de b y tes................................................................................................................. 430
F ileO u tp u tS trean i..................................................................................................... 430
F ileln p u tS tream ......................................................................................................... 433
C lase F ile ........................................................................................................................... 434
Flujos de c a ra c te re s........................................................................................................ 437
F ile W riter.................................................................................................................... 438
F ile R e a d e r................................................................................................................... 439
Flujos de d ato s................................................................................................................. 440
D ataO utputS tream .................................................................................................... 441
D ata ln p u tS trea m ....................................................................................................... 442
U n ejem plo de acceso s e c u e n c ia l............................................................................... 443
SER IA C I N DE O B JE T O S ............................................................................................. 448
E scribir objetos en un fich ero ......................... 450
L eer objetos desde un fich ero ...................................................................................... 451
Seriar objetos que referencian a o b je to s................................................................... 453
A B R IE N D O FIC H ER O S PA R A A C C E SO A L E A T O R IO .................................... 457
La clase R an d om A ccessF ile........................................................................................ 457
La clase C P e rs o n a .......................................................................................................... 460
La clase C L istaT fnos...................................... 461
C onstructor C L istaT fn o s........................................................................................ 461
E scribir un registro en el fic h e ro .......................................................................... 463
A adir un registro al final del fic h e ro ................................................................ 464
L eer un registro del fic h e ro ................................................................................... 464
E lim inar un registro del fichero............................................................................ 465
B uscar un registro en el fich ero ............................................................................ 465
U n ejem plo de acceso aleatorio a un fic h e ro .......................................................... 466
M odificar un reg istro ............................................................................................... 469
A ctualizar el fic h e ro ................................................................................................ 471
U TILIZA C I N DE D ISPO SIT IV O S E S T N D A R .................................................. 472
E JER C IC IO S R E S U E L T O S ............................................................................................. 473
E JER C IC IO S P R O P U E S T O S .......................................................................................... 493
X V I I I JA V A : C U R SO D E PROGRAM A CIN

C A P T U L O 13. E S T R U C T U R A S D IN M IC A S ........................................................ 495

LISTA S L IN E A L E S ........................................................................................................... 496


Listas lineales sim plem ente enlazadas...................................................................... 496
O peraciones b s ic a s ...................................................................................................... 499
Insercin de un elem ento al com ienzo de la lis ta ........................................... 500
Insercin de un elem ento en g e n e ra l.................................................................. 502
B orrar un elem ento de la lista............................................................................... 503
R ecorrer una lis ta ..................................................................................................... 504
B orrar todos los elem entos de una lista .............................................................. 504
B uscar en una lista un elem ento con un valor x .............................................. 504
UNA C L A S E PARA LISTA S L IN E A L E S .................................................................. 505
C lase genrica para listas lin e a le s ............................................................................. 509
C lase L in k e d L ist............................................................................................................ 519
LISTA S C IR C U L A R E S ..................................................................................................... 522
C lase C L istaC ircularS E ................................................................................................ 523
P IL A S ....................................................................................................................................... 527
C O L A S .................................................................................................................................... 529
E JE M P L O .............................................................................................................................. 530
LISTA D O B L E M EN T E E N L A Z A D A .......................................................................... 533
Lista circular doblem ente e n la z a d a ........................................................................... 534
C lase C L istaC ircularD E ......................................................................................... 534
E je m p lo ....................................................................................................................... 540
R B O L E S .............................................................................................................................. 542
rboles b in a rio s ............................................................................................................. 543
Form as de recorrer un rbol b in a rio ......................................................................... 544
RBOLES B IN A R IO S DE B S Q U E D A .................................................................... 546
C lase C A rbolB inB .......................................................................................................... 547
B uscar un nodo en el rb o l.......................................................................................... 550
Insertar un nodo en el rb o l......................................................................................... 551
B orrar un nodo del r b o l .............................................................................................. 553
U tilizacin de la clase C A rb o lB in B ......................................................................... 555
RBOLES B IN A R IO S P E R FEC TA M EN TE E Q U IL IB R A D O S ........................ 558
C lase C A rb o lB inE .......................................................................................................... 559
U tilizacin de la clase C A rbolB inE ........................................................................... 564
C LA SES R EL A C IO N A D A S DE LA B IB LIO TEC A JA V A .................................. 566
EJERCICIO S R E S U E L T O S ............................................................................................. 567
EJER C IC IO S P R O P U E S T O S .......................................................................................... 581

C A P T U L O 14. A L G O R IT M O S ....................................................................................... 585

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

C A P T U L O 15. H I L O S ......................................................................................................... 633

C O N C E PTO D E P R O C E S O ............................................................................................. 633


H IL O S ...................................................................................................................................... 635
E stados de un h i l o .......................................................................................................... 636
C undo se debe crear un hilo ....................................................................................... 637
C m o se crea un h ilo ..................................................................................................... 638
H ilo derivado de T h read ......................................................................................... 640
H ilo asociado con una c la s e .................................................................................. 641
D e m o n io s.......................................................................................................................... 643
F inalizar un h i l o .................................................................. 644
C ontrolar un h i l o ............................................................................................................ 646
P re p a ra d o .................................................................................................................... 647
B lo q u e a d o .................................................................................................................. 647
D o rm id o ...................................................................................................................... 648
E sp eran d o .................................................................................................................... 649
Planificacin de h ilo s .................................................................................................... 649
Q u ocurre con los hilos que tengan igual prioridad?.................................. 650
A signar prioridades a los h ilo s ................................................................................... 651
SIN C R O N IZ A C I N DE H IL O S .................................................................................... 654
XX JA V A : C U R SO DE PROGRAM A CIN

Secciones c rtic a s ........................................................................................................... 655


C rear una seccin c rtic a ........................................................................................ 659
M onitor reentrante.................................................................................................... 662
U tilizar w ait y n o tify ..................................................................................................... 663
Por qu los m todos alm acenar y obtener utilizan un b u c le ? ..................... 669
ln te rb lo q u e o ..................................................................................................................... 670
G R U PO DE H IL O S ............................................................................................................ 671
G rupo p re d efin id o .......................................................................................................... 671
G rupo e x p lcito ................................................................................................................ 673
T U B E R A S ............................................................................................................................ 673
E SPER A A C TIV A Y P A S IV A ........................................................................................ 678
EJER C IC IO S R E S U E L T O S ............................................................................................. 678
EJER C IC IO S P R O P U E S T O S .......................................................................................... 683

PARTE 3. PRO G RA M A S PARA IN T E R N E T ......................... 685


C A P T U L O 16. A P A R T IR D E A Q U ............................................................................. 687

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

C iclo de vida de un a p p le t............................................................................................ 711


Pasar parm etros a un a p p le t....................................................................................... 711
F u e n te s .............................................................................................................................. 713
C o lo r................................................................................................................................... 713
M ostrar una im agen........................................................................................................ 714
R eproducir un fichero de s o n id o ................................................................................ 7 16
M ostrar inform acin en la barra de e s ta d o ............................................................. 718
C rear una anim acin...................................................................................................... 718
R estricciones de seguridad con los ap p lets............................................................. 722
IN T ER FA Z G R F IC A ...................................................................................................... 723
Estructura de una aplicacin........................................................................................ 724
C rear un com ponente S w in g ....................................................................................... 726
M anejo de ev en to s.......................................................................................................... 727
C o n ten ed o res.................................................................................................................... 729
O rganizar ios controles en un c o n te n e d o r........................................................ 730
E stablecer la apariencia de las v en tan a s.................................................................. 731
U n ejem plo de una interfaz grfica............................................................................ 732
A pplets que utilizan com ponentes S w in g ................................................................ 734
S E R V L E T S ............................................................................................................................ 737
Estructura de un se rv le t................................................................................................ 738
Softw are necesario para ejecutar un servlet............................................................ 742
Ejecutar un serv le t.......................................................................................................... 743
Invocando al servlet desde una pgina H T M L ...................................................... 744
EJER C IC IO S R E S U E L T O S ............................................................................................. 746
EJER C IC IO S P R O P U E S T O S .......................................................................................... 749

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.

P oner un program a en m archa es sinnim o de ejecutarlo. C uando ejecutam os


un program a, nosotros slo vem os los resultados que produce (el procesador de
textos m uestra sobre la pantalla el texto que escribim os; el ju eg o visualiza sobre
la pantalla las im genes que se van sucediendo) pero no vem os el guin seguido
por el ordenador para conseguir esos resultados. Ese guin es el program a.

A hora, si nosotros escribim os un program a, entonces s que sabem os cm o


trabaja y por qu trabaja de esa form a. Esto es una form a m uy diferente y curiosa
de ver un program a de ordenador, lo cual no tiene nada que ver con la experiencia
adquirida en la ejecucin de distintos program as.
4 JA V A : C U R SO D E PRO G R A M A Ct N

A hora, piense en un ju eg o cualquiera. La pregunta es qu hacem os si quere


m os ensear a otra persona a ju g a r? Lgicam ente le explicam os lo que debe ha
cer; esto es, los pasos que tiene que seguir. D icho de otra form a, le dam os
instrucciones de cm o debe actuar. Esto es lo que hace un program a de ordena
dor. Un program a no es nada m s que una serie de instrucciones dadas al ordena
d o r en un lenguaje entendido por l, para decirle exactam ente lo que querem os
que haga. Si el ordenador no entiende alguna instruccin, lo com unicar general
m ente m ediante m ensajes visualizados en la pantalla.

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.

Un lenguaje ensam blador utiliza cdigos nem otcnicos para indicarle al


hardw are (com ponentes fsicos del ordenador) las operaciones que tiene que reali-
C A PTU LO 1: FASES EN E L D ESA RRO LLO DE UN PROGRAM A 5

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:

MOV AH. 4CH

El cdigo M O V expresa una operacin consistente en m over alguna inform a


cin desde una posicin de m em oria a otra.

Para traducir un program a escrito en ensam blador a lenguaje m quina


(cdigo binario) se utiliza un program a llam ado ensam blador que ejecutam os m e
diante el propio ordenador. Este program a tom ar com o datos nuestro program a
escrito en lenguaje ensam blador y dar com o resultado el m ism o program a pero
escrito en lenguaje m quina, lenguaje que entiende el ordenador.

C ada m odelo de ordenador, dependiendo del procesador que utilice, tiene su


propio lenguaje ensam blador. D ebido a esto decim os que estos lenguajes estn
orientados a la m quina.

H oy en da son m s utilizados ios lenguajes orientados al problem a o lengua


jes de alto nivel. E stos lenguajes utilizan una term inologa fcilm ente com prensi
ble que se aproxim a m s al lenguaje hum ano. En este caso la traduccin es
llevada a cabo por o tro program a denom inado com pilador.

C ada sentencia de un program a escrita en un lenguaje de alto nivel se des


com pone en general en varias instrucciones en ensam blador. Por ejem plo:

printft "hola" ):

L a funcin p r i n t f del lenguaje C le dice al ordenador que visualice en el m o


nitor la cadena de caracteres especificada. E ste m ism o proceso escrito en lenguaje
ensam blador necesitar de varias instrucciones. Lo m ism o podram os decir del
m todo p rin tln de Java:

System .out.printlrit " h o l a );

A diferencia de los lenguajes ensam bladores, la utilizacin de lenguajes de


alto nivel no requiere en absoluto del conocim iento de la estructura del procesador
que utiliza el ordenador, lo que facilita la escritura de un program a.
6 JA VA : C U R SO DE PROGRAM A CIN

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.

Q u es una m quina virtual? U na m quina que no existe fsicam ente sino


que es sim ulada en un ordenador por un program a. P or qu utilizar una m quina
virtual? Porque, por tratarse de un program a, es m uy fcil instalarla en cualquier
ordenador, basta con copiar ese program a en su disco duro, por ejem plo. Y, qu
ventajas reporta? Pues, en el caso de Java, que un program a escrito en este len
guaje y com pilado, puede ser ejecutado en cualquier ordenador del m undo que
tenga instalada esa m quina virtual. E sta solucin hace posible que cualquier o r
denador pueda ejecutar un program a escrito en Java independiente de la platafor
ma que utilice, lo que se conoce com o transportabilidad de program as.

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.

A diferencia de un com pilador, un intrprete verifica cada lnea del program a


cuando se escribe, lo que facilita la puesta a punto del program a. En cam bio la
ejecucin resulta m s lenta ya que acarrea una traduccin sim ultnea.
C A PTU LO I : FASES EN E L D ESA RRO LLO DE UN PRO G R A M A 7

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.

U na de las ventajas significativas de Java sobre otros lenguajes de program a


cin es que es independiente de la plataform a, tanto en cdigo fuente com o en bi
nario. Esto quiere decir que el cdigo producido por el com pilador Java puede
transportarse a cualquier plataform a (Intel, Sparc, M otorola, etc.) que tenga ins
talada una m quina virtual Java y ejecutarse. Pensando en Internet esta caracters
tica es crucial ya que esta red conecta ordenadores m uy distintos. En cam bio,
C++, por ejem plo, es independiente de la plataform a slo en cdigo fuente, lo c u
al significa que cada plataform a diferente debe proporcionar el com pilador ade
cuado para obtener el cdigo m quina que tiene que ejecutarse.

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.

Los cdigos de bytes de Java son un conjunto de instrucciones correspon


dientes a un lenguaje m quina que no es especfico de ningn procesador, sino de
la m quina virtual de Java. D nde se consigue esta m quina virtual? H oy en da
casi todas las com paas de sistem as operativos y de navegadores han im plem en-
tado m quinas virtuales segn las especificaciones publicadas p o r Sun M icrosys
tems, propietario de Java, para que sean com patibles con el lenguaje Java. Para las
aplicaciones de Internet (denom inadas applets) la m quina virtual est incluida en
el navegador y para las aplicaciones Java convencionales, puede venir con el sis
tem a operativo, con el paquete Java, o bien puede obtenerla a travs de Internet.

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.

La explosin de Internet en 1994, gracias al navegador grfico M osaic para la


W ord W ide W eb ( W W W ), no pas desapercibida para el grupo investigador de
Sun. Se dieron cuenta de que los logros alcanzados en su proyecto de investiga
cin eran perfectam ente aplicables a Internet. C om parativam ente, Internet era
com o un gran conjunto de aparatos electrnicos de consum o, cada uno con un
procesador diferente. Y es cierto; bsicam ente. Internet es una gran red m undial
que conecta m ltiples ordenadores con diferentes sistem as operativos y diferentes
arquitecturas de m icroprocesadores, pero todos tienen en com n un navegador
que utilizan para com unicarse entre s. E sta idea hizo que el grupo investigador
abandonara el proyecto de desarrollar un lenguaje que perm itiera la com unicacin
entre aparatos electrnicos de consum o y dirigiera sus investigaciones hacia el d e
sarrollo de un lenguaje que perm itiera crear aplicaciones que se ejecutaran en
cualquier ordenador de Internet con el nico soporte de un navegador.

A partir de aqu ya todo es conocido. Se em pez a hablar de Java y- de sus


aplicaciones, conocidas com o applets. U n applet es un program a escrito en Java
que se ejecuta en el contexto de una pgina W eb en cualquier ordenador, indepen
CA PTU LO 1: FASES EN E L D E SA R R O L LO DE UN PRO G R A M A 9

dientem ente de su sistem a operativo y de la arquitectura de su procesador. Para


ejecutar un applet slo se necesita un navegador que soporte la m quina virtual de
Java com o, por ejem plo, M icrosoft Internet E xplorer o Netscape. U tilizando un
navegador de stos, se puede descargar la pgina W eb que contiene el applet y
ejecutarlo. Precisam ente en este cam po, es donde Java com o lenguaje de progra
m acin no tiene com petidores. N o obstante, con Java se puede program ar cual
q uier cosa, razn por la que tam bin puede ser considerado com o un lenguaje de
propsito general; pero, desde este punto de vista, hoy por hoy. Java tiene m uchos
com petidores que le sobrepasan con claridad; por ejem plo A da o C++.

POR QU APRENDER JAVA?


Una de las ventajas m s significativas de Java es su independencia de la platafor
ma. En el caso de que tenga que desarrollar aplicaciones que tengan que ejecutar
se en sistem as diferentes esta caracterstica es fundam ental.

O tra caracterstica im portante de Java es que es un lenguaje de program acin


orientado a objetos (POO). Los conceptos en los que se apoya esta tcnica de pro
gram acin y sus ventajas sern expuestos en el captulo siguiente.

A dem s de ser transportable y orientado a objetos. Java es un lenguaje fcil


de aprender. T iene un tam ao pequeo que favorece el desarrollo y reduce las p o
sibilidades de com eter errores; a la vez es potente y flexible.

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.

REALIZACIN DE UN PROGRAMA EN JAVA


En este apartado se van a exponer los pasos a seguir en la realizacin de un pro
gram a, por m edio de un ejem plo.

L a siguiente figura, m uestra de form a esquem tica lo que un usuario de Java


necesita y debe hacer para desarrollar un program a.
10 JA VA : C U R SO DF. PROGRAM ACIN

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

Evidentem ente, para poder escribir program as se necesita un entorno de d esa


rrollo Java. Sun M icrosystem s, propietario de Java, proporciona uno de form a
gratuita, Java D evelopm ent K it (JD K ), que se puede obtener en la direccin de
Internet:
http://www.sun.com

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.

Para instalar la versin que incluye el C D m encionado en una plataform a


W indow s, hay que ejecutar el fichero j2 sd kl_ 3 _ 0 -w in .ex e. De m anera predeter
m inada el paquete ser instalado en jd k l.3 , pero se puede instalar en cualquier
otra carpeta. A continuacin puede instalar en jd k l.3 \d o c s la docum entacin que
se proporciona en el fichero j2 sd kl_ 3 _ 0 -d o c.zip . Puede ver m s detalles sobre la
instalacin al final del libro. U na vez finalizada la instalacin, se puede observar
el siguiente contenido:

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 jr e es el entorno de ejecucin de Java utilizado por el SDK. Es si


m ilar al intrprete de Java (java), pero destinado a usuarios finales que no re
quieran todas las opciones de desarrollo proporcionadas con la utilidad java.
Incluye la m quina virtual, la biblioteca de clases, y otros ficheros que so
portan la ejecucin de program as escritos en Java.

La carpeta lib contiene bibliotecas de clases adicionales y ficheros de soporte


requeridos por las herram ientas de desarrollo.

La carpeta dem o contiene ejem plos.

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.

Cmo crear un programa


Un program a puede ser una aplicacin o un applet. C on este libro aprender prin
cipalm ente a escribir aplicaciones Java. D espus aplicar lo aprendido para escri
bir algunos applets. Em pecem os con la creacin de una aplicacin sencilla: el
clsico ejem plo de m ostrar un m ensaje de saludo.
1 2 JA VA : C U R S O DE PROGRAM A CIN

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.

Interfaz de lnea de rdenes


Em pecem os por editar el fichero fuente Java correspondiente a la aplicacin. Pri
m eram ente visualizarem os el editor de textos que vayam os a utilizar; por ejem plo,
el B lock de notas o el Edil. El nom bre del fichero elegido para guardar el progra
m a en el disco, debe tener com o extensin ja v a ; por ejem plo H olaM undo.java.

U na vez visualizado el editor, escribirem os el texto correspondiente al pro


gram a fuente. E scrbalo tal com o se m uestra a continuacin. O bserve que cada
sentencia del lenguaje Java finaliza con un p u n to y com a y que cada lnea del
program a se finaliza pulsando la tecla E ntrar (E n ter o J ).

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

Qu hace este programa?

C om entam os brevem ente cada lnea de este program a. No apurarse si algunos de


los trm inos no quedan m uy claros ya que todos ellos se vern con detalle en ca
ptulos posteriores.

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.

A continuacin se escribe el m todo principal m a in . O bserve que un m todo


se distingue p o r el m odificador () que aparece despus de su nom bre y que el blo
que de cdigo correspondiente al m ism o d efine las acciones que tiene que ejecutar
dicho m todo. C uando se ejecuta una aplicacin, Java espera que haya un m todo
m ain . Este m todo define el punto de entrada y de salida de la aplicacin.

El m todo p r in tln del objeto o u t m iem bro de la clase S y stem de la biblioteca


Java, escribe com o resultado la expresin que aparece especificada entre com illas.
Observe que la sentencia com pleta finaliza con punto y com a.

Guardar el programa escrito en el disco

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.

Compilar y ejecutar el programa

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

Previam ente, para que el sistem a operativo encuentre la utilidad ja v a c , utili


zando la lnea de rdenes hay que aadir a la variable de entorno path la ruta de la
carpeta donde se encuentra esta utilidad y otras que utilizarem os a continuacin.
Por ejem plo:

pa t h = %p a t h % : c : \ j d k l . 3 \ b i n

La expresin % path% representa el valor actual de la variable de entorno


path. U na ruta va separada de la anterior por un punto y com a.

En la figura siguiente se puede observar el proceso seguido para com pilar


H olaM undo.java desde la lnea de rdenes.
1 4 JA VA : CU R SO D E PROGRAM A CIN

-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 : \ K a p 0 1 \ H o laM undo > ia u a c lio Ia M undo . j a u a

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.

Al com pilar un program a, se pueden presentar errores d e com pilacin, debi


do s a que el program a escrito no se adapta a la sintaxis y reglas del com pilador.
Estos errores se irn corrigiendo hasta obtener una com pilacin sin errores.

Para ejecutar el fichero resultante de la com pilacin, invocarem os desde la l


nea de rdenes al intrprete de cdigo de bytes ja v a con el nom bre de dicho fiche
ro com o argum ento, en nuestro caso H olaM undo, y pulsarem os E ntrar para que
se m uestren los resultados.

En la figura siguiente se puede observar el proceso seguido para ejecutar H o


laM undo desde la lnea de rdenes. H ay que respetar las m aysculas y las m ins
culas en los nom bres que se escriben. A s m ism o, cabe resaltar que la extensin
.class no tiene que ser especificada.

Una vez ejecutado, se puede observar que el resultado es el m ensaje: H ola


m undo!!!.
CA PTU LO 1: FASES EN E L D E SA R R O L LO D E UN PRO G R A M A 15

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 *

C : \R.iptl1 \l ln !,iMundo> j.iu oc H o l a M u n d o . j o u o

C:\Cop 01\H o U M u n d o > 4 ir

E l u o l u n r n de I.i unid .nl C no t i e n e e t i u u c t a


E l n n c r o de s e r i e d e l u o l u n c n e s 2 E 1 I -071:8
d i r e c t o r i o de C : \ C d p 0 1 \ H o l o M u n d o

< 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

C : \ C o p 0 1 \ l l o lo M u n d o > jo v ii lio I Mun d o


li n i o m u id o ! I !
C:\Cop01\lloloM undo

Biblioteca de funciones

Java carece de instrucciones de E/S, de instrucciones para m anejo de cadenas de


caracteres, etc. con lo que este trabajo queda para la biblioteca de clases provista
con el com pilador. U na biblioteca es un fichero separado en el disco (con exten
sin .lib, .jar o .dll) que contiene las clases que definen las tareas m s com unes,
para que nosotros no tengam os que escribirlas. C om o ejem plo, hem os visto ante
riorm ente el m todo p rin tln del objeto o u t m iem bro d e la clase S ystem . Si este
m todo no existiera, sera labor nuestra el escribir el cdigo necesario para visua
lizar los resultados en la ventana.

En el cdigo escrito anteriorm ente se puede observar que p ara utilizar un


m todo de una clase de la biblioteca sim plem ente hay que invocarlo para un o b
jeto de su clase y pasarle los argum entos necesarios entre parntesis. Por ejem plo:

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

Guardar el program a ejecutable en el disco

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

Al ejecutar el program a, pueden ocurrir errores durante la ejecucin. Por


ejem plo, puede darse una divisin por cero. Estos errores solam ente pueden ser
detectados p o r Java cuando se ejecuta el program a y sern notificados con el c o
rrespondiente m ensaje de error.

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.

La form a m s sencilla y eficaz para realizar este proceso, es u tilizar un pro


gram a depurador. El entorno de desarrollo de Java proporciona para esto la utili
dad jd b . ste es un depurador de lnea de rdenes un tanto com plicado de utilizar,
por lo que, en principio, tiene escasa aceptacin. N orm alm ente los entornos de
desarrollo integrados que anteriorm ente hem os m encionado (excepto FreeJava)
incorporan las rdenes necesarias para invocar y depurar un 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 esde un entorno integrado, habr que establecer las opcin correspondiente


del com pilador.

U na vez com pilado el program a, se inicia la ejecucin en m odo depuracin y


se contina la ejecucin con las rdenes tpicas de ejecucin paso a paso.

Entorno de desarrollo integrado


Cuando se utiliza un entorno de desarrollo integrado lo prim ero que hay que hacer
una vez instalado dicho entorno es asegurarse de que las opciones que indican las
rutas de las herram ientas Java, de las bibliotecas, de la docum entacin y de los
fuentes, o bien sim plem ente de la ruta donde se instal el JD K , estn establecidas.
Por ejem plo, si utiliza el entorno de desarrollo integrado p cG R A S P que se propor
ciona en el CD, en el m en File del m ism o encontrar una orden G lobal P refe-
C A PTU LO I : FASES EN E L D E SA R R O L LO D E UN PRO G R A M A 17

rences... que le perm itir especificar la ruta de la carpeta donde ha instalado el


JD K . O tros entornos proporcionarn una orden O pciones o equivalente.

En la siguiente figura se puede observar el aspecto del entorno de desarrollo


integrado pcG R A SP .

p c G IA S P (HuldM untio i<iva) F ie l


P Temcoie* P*ec ompei Qun ytp

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.

p u b lic a ta tic v o id m am (Stnng[) args) xJ

System.out.println("Hola m u n d o ' ! 1" ) ;


1

' 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

Fea Holp. preti F1 L n l.C d l i r

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:

1. Suponiendo que ya est visualizado el entorno de desarrollo, aadim os un


nuevo fichero Java (File, N ew ), editam os el cdigo que com pone la aplicacin
y lo guardam os con el nom bre H olaM undo.java (F ile, Save).

2. A continuacin, para com pilar la aplicacin, ejecutam os la orden C om pile del


m en Compiler.

3. Finalm ente, para ejecutar la aplicacin, suponiendo que la com pilacin se


efectu satisfactoriam ente, seleccionarem os la orden Run Captured, o bien
Run, del m en Run.

En captulos posteriores, im plem entar aplicaciones com puestas por varios fi


cheros fuente. En este caso, los pasos a seguir son los siguientes:

1. Suponiendo que ya est visualizado el entorno de desarrollo, aadim os (File,


N ew ) y editam os cada uno de los ficheros que com ponen la aplicacin y los
guardam os con los nom bres adecuados (File, Save).
1 8 JA VA : C U R SO DE PROGRAM ACIN

2. Para com pilar la aplicacin visualizarem os el fichero que contiene la clase


aplicacin (la clase que contiene el m todo m a in ) y ejecutam os la orden
C om pile del m en C ompiler. Se puede observar que todas las clases que son
requeridas por esta clase principal son com piladas autom ticam ente, indepen
dientem ente de que estn, o no, en diferentes ficheros.

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.

C uando una aplicacin consta de varios ficheros puede resultar m s cm odo


para su m antenim iento crear un proyecto. Esto perm itir presentar una ventana
que m ostrar una entrada por cada uno de los ficheros fuente que com ponen la
aplicacin. Para visualizar el cdigo de cualquiera de estos ficheros, bastar con
hacer doble clic sobre la entrada correspondiente.

IR Ed Tnptate Pnwcl cmpi Bun fn d ow i B*fc

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

| GenwaleCSD | RwnoveCSO | FontSce |----------------- p

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

|a vac C :\T e m p \ C A p lic a c io n . ja v a

P r o c e s e F l n is h e d

fot Help, pret* F1

Para crear un proyecto, los pasos a seguir son los siguientes:

1. Suponiendo que ya est visualizado el entorno de desarrollo, se aaden (File,


N ew ) y editan cada uno de los ficheros que com ponen la aplicacin y se guar
dan con los nom bres adecuados (F ile, Save).

2. Despus se crea un nuevo proyecto (P roject, N ew P roject W orkspace). En la


ventana que se visualiza, haciendo clic en el botn Brow se correspondiente,
se introduce un nom bre para el proyecto y se selecciona el nom bre de la clase
aplicacin (la clase que contiene el m todo m ain). Posteriorm ente, para vi-
CA PTU LO 1: FASES EN EL D ESA RRO LLO DE UN PROGRAM A 19

sualizar la ventana del proyecto, se ejecuta la orden Show Project W orkspace


W indow del m en Project.

3. El paso siguiente es aadir al proyecto el resto de los ficheros que lo com po


nen. Para ello se ejecuta la orden Edil P roject del m en P roject, y a travs del
botn A d d Files se aaden dichos ficheros.

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.

class CAritm etica


I
/*
* Operaciones aritm ticas
*/
public static v o i d main ( S t r in g [] args)
I
int datol. dato2. resultado:

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.

Qu hace este programa?

F ijndonos en el m todo principal, m a in , vem os que se han declarado tres varia


bles enteras (de tipo in t): d a to l, dato2 y resultado.

in t datol. dato2, resultado;

El siguiente paso asigna el valor 20 a la variable d a to l y el valor 10 a la v a


riable dato2.

d a t o l = 20:
d a t o 2 = 10:

A continuacin se realiza la sum a de esos valores y se escriben los datos y el


resultado.

re su lta d o = datol + dato2;


S y s t e m . o u t . p r in t ln d a t o l + " + " + dato2 + " = " + resultado):

El m todo p r in tln escribe un resultado de la forma:

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

Un proceso sim ilar se sigue para calcular la diferencia, el producto y el co


ciente.

Para finalizar, com pile, ejecute la aplicacin y observe los resultados.

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.

A qu objetos nos referim os? Si nos param os a pensar en un determ inado


problem a que intentam os resolver podrem os identificar entidades de inters, las
cuales pueden ser objetos potenciales que poseen un conjunto de propiedades o
atributos, y un conjunto de m todos m ediante los cuales m uestran su com porta
m iento. Y no slo eso, tam bin podrem os ver, a poco que nos fijem os, un con
ju n to de interrelaciones entre ellos conducidas p o r m ensajes a los que responden
m ediante m todos.

V eam os un ejem plo. C onsidere una entidad bancaria. En ella identificam os


entidades que son cuentas: cuenta del cliente 1, cuenta del cliente 2, etc. Pues
bien, una cuenta puede verse com o un objeto que tiene unos atributos, nom bre,
nm ero de cuenta y saldo, y un conjunto de m todos com o IngresarD inero, Reti-
rarD inero, A bonarlntereses, SaldoA ctual, Transferencia etc. En el caso de una
transferencia:

cuentaOl.Transferencia(cuenta02);

Transferencia sera el m ensaje que el objeto cuenta02 enva al objeto cuentaO l,


solicitando le sea hecha una transferencia, siendo la respuesta a tal m ensaje la eje
cucin del m todo Transferencia. T rabajando a este nivel de abstraccin, m ani
pular una entidad bancaria resultar algo m uy sencillo.
24 JA V A: C U R SO DE PROGRAM A CIN

MECANISMOS BSICOS DE LA POO


Los m ecanism os bsicos de la program acin orientada a objetos son: objetos,
m ensajes, m todos y clases.

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.

En adicin, las propiedades (atributos) definidas en la clase perm itirn alm a


cenar inform acin para dicho objeto.
C A PTU LO 2: PRO G R A M A CI N O R IEN TA D A A OBJETOS 2 5

C uando se disea una clase de objetos, la estructura m s interna del objeto se


oculta a los usuarios que lo vayan a utilizar, m anteniendo com o nica conexin
con el exterior, los m ensajes. Esto es, los datos que estn dentro de un objeto so
lam ente podrn ser m anipulados por los m todos asociados al propio objeto.

o bjeto

m e n s a je s d ato s

m to d o s

Segn lo expuesto, podem os decir que la ejecucin de un program a orientado


a objetos realiza fundam entalm ente tres cosas:

1. C rea los objetos necesarios.


2. L os m ensajes enviados a unos y a otros objetos dan lugar a que se procese
internam ente la inform acin.
3. Finalm ente, cuando los objetos no son necesarios, son borrados, liberndo
se la m em oria ocupada por los m ismos.

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.

Un objeto de una determ inada clase se crea en el m om ento en que se define


una variable de dicha clase. P or ejem plo, la siguiente lnea declara el objeto
clienteOI de la clase o tipo CCuenta.

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 lgunos autores em plean el trm ino instancia (traduccin directa de instan-


ce), en el sentido de que una instancia es la representacin concreta y especfica
de una clase; por ejem plo, clienteO I es un instancia de la clase C Cuenta. Desde
este punto de vista, los trm inos instancia y objeto son lo m ism o. El autor prefiere
utilizar el trm ino objeto, o bien ejem plar.

C uando escribe un program a utilizando un lenguaje orientado a objetos, no se


definen objetos verdaderos, se definen clases de objetos, donde una clase se ve
com o una plantilla para m ltiples objetos con caractersticas sim ilares.
26 JA VA : C U R SO DE PROGRAM A CIN

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.

CMO CREAR UNA CLASE DE OBJETOS


Segn lo expuesto hasta ahora, un objeto contiene, p o r una parte, atributos que
definen su estado, y por otra, operaciones que definen su com portam iento. T am
bin sabem os que un objeto es la representacin concreta y especfica de una cla
se. C m o se escribe una clase de objetos? C om o ejem plo, podem os crear una
clase C O rdenador. A bra su entorno de program acin integrado favorito y escriba
paso a paso el ejem plo que a continuacin em pezam os a desarrollar:

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 son las caractersticas individuales que diferencian un objeto de


otro. El color de una ventana W indow s, la diferencia de otras; el D .N .I. de una
persona la identifica entre otras; el m odelo de un ordenador le distingue entre
otros; etc.

La clase C O rdenador puede incluir los siguientes atributos:

0 M arca: M itac, Toshiba, Ast


0 Procesador: Intel, AM D
0 Pantalla: TFT, D STN , STN

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

0 D ispositivo: encendido, apagado


0 Presentacin: activa, inactiva

T odos los atributos son definidos en la clase por variables:

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.

No vam os a profundizar en los detalles de la sintaxis de este ejem plo ya que


el nico objetivo ahora es entender la definicin de una clase con sus partes bsi
cas. El resto de la sintaxis y dem s detalles se irn exponiendo poco a poco en su
cesivos captulos.

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.

C om o ejem plo, vam os a agregar a la clase C O rdenador un m todo que res


ponda a la accin de ponerlo en m archa:
28 JA V A: CU R SO DE PRO G R A M A CI N

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 . " ) :

C om o se puede observar un m todo consta d e su nom bre precedido por el tipo


del valor que devuelve cuando finalice su ejecucin (la palabra reservada void in
dica que el m todo no devuelve ningn valor) y seguido p o r una lista de parm e
tros separados p o r com as y encerrados entre parntesis (en el ejem plo, no hay
parm etros). Los parntesis indican a Java que el identificador (E ncenderO rdena-
dor) se refiere a un m todo y no a un atributo. A continuacin se escribe el cuerpo
del m todo encerrado entre { y }. U sted ya conoce algunos m todos, llam ados en
otros contextos funciones: seguro que conoce la funcin logaritm o que devuelve
un valor real correspondiente al logaritm o del valor pasado com o argum ento.

El m todo E ncenderO rdenador com prueba si el ordenador est encendido; si


lo est, sim plem ente visualiza un m ensaje indicndolo; si no lo est, se enciende y
lo com unica m ediante un m ensaje.

A greguem os un m todo m s para que el objeto nos m uestre su estado:

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

El m todo E stado visualiza los atributos especficos de un objeto. L a secuen


cia de escape Vi, as se denom ina, introduce un retom o de carro m s un avance de
lnea (caracteres A SC II. CR LF).

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.

H agam os lo m s sencillo, aadir el m todo m a in a la clase C O rdenador. El


cdigo com pleto, incluyendo el m todo m ain . se m uestra a continuacin:

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

public static v o i d main (String args)


I
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 nador.Pan talla - "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 );
M i O r d e n a d o r . E s t a d o ( );
)
3 0 JA V A: C U R SO DE PROGRAM A CIN

El m todo m a in siem pre se declara pblico y esttico, no devuelve un resul


tado y tiene un parm etro args que es una m atriz de una dim ensin de cadenas de
caracteres. En los captulos siguientes aprender para qu sirve. A nalicem os el
m todo m a in para q ue tenga una idea de lo que hace:

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.

En general, para acceder a un m iem bro de una clase (atributo o m todo) se


utiliza la sintaxis siguiente:

nom bre_objeto, n o m b r e jn ie m b ro

G uarde la aplicacin con el nom bre C O rdenador.java. D espus com plela y


ejectela. Se puede observar que los resultados son los siguientes:

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

El ordenador est encendido.

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

public class CMiOrdenador


I
public static v o i d main (StringU args)
I
// ...

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

else II s i no e s t encendido, encenderlo.


I
OrdenadorEncendido = true;
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 s e ha e n c e n d i d o . " ) :
I
I

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."):

La aplicacin C M iO rdenador.java que acabam os de com pletar tiene dos cla


ses: la clase aplicacin C M iO rdenador y la clase C O rdenador. O bserve que la
clase aplicacin es pblica (p u b lic) y la otra no. C uando incluyam os varias clases
en un fichero fuente, slo una puede ser pblica y su nom bre debe coincidir con el
del fichero donde se guardan. Al com pilar este fichero. Java crear tanto ficheros
.class com o clases separadas hay.

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.

La abstraccin y la encapsulacin estn representadas por la clase. La clase es


una abstraccin, porque en ella se definen las propiedades o atributos de un de
term inado conjunto de objetos con caractersticas com unes, y es una encapsula
cin porque constituye una caja negra que encierra tanto los datos que alm acena
cada objeto com o los m todos que perm iten m anipularlos.

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

den tener m s de una superclase, lo que se conoce com o herencia mltiple. En


este caso, una clase com parte los m todos y propiedades de varias clases. E sta ca
racterstica, proporciona un poder enorm e a la hora de crear clases, pero com plica
excesivam ente la program acin, por lo que es de escasa o nula utilizacin. Java,
intentando facilitar las cosas, soluciona este problem a de com portam iento com
partido utilizando interfaces.

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.

Todo esto ser objeto de un estudio am plio en captulos posteriores.

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.

Un d estructor es un procedim iento especial de una clase que es llam ado a u


tom ticam ente siem pre que se destruye un objeto de esa clase. Su funcin es rea
lizar cualquier tarea final en el m om ento de destruir 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

fraccionario sera 0,333333, valor m s fcil de m anipular, pero a costa d e perder


precisin. Evidentem ente, 1 / 3 * 3 = 1, pero 0,333333 * 3 = 0,999999.

Pensando en un nm ero racional com o si de un objeto se tratara, es fcil de


ducir que sus atributos son dos: el num erador y el denom inador. Y los m todos
aplicables sobre los nm eros racionales son num erosos: sum a, resta, m ultiplica
cin, sim plificacin, etc. Pero en base a los conocim ientos adquiridos, slo aadi
rem os dos m todos sencillos: uno, A signarD atos, para establecer los valores del
num erador y del denom inador; y otro, VisualizarRacional, para visualizar un n
m ero racional.

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:

v o i d A s i g n a r D a t o s t i n t num, int den)


(
N u me r a d o r = num;
i f ( d e n = = 0 ) den = 1 : //el d e n o m i n a d o r no p u e d e s e r cero
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 ()
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

public static v o i d main ( S t r in g [ ] args)


I
// P u n t o de e n t r a d a a l a a p l i c a c i n
C R a c i o n a l r l = new C R a c i o n a 1 C ) : // c r e a r un o b j e t o C R a c i o n a l

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 ;

U na vez editado el program a, gurdelo en el disco con el nom bre CRacio-


nal.java.
36 JA VA : C U R SO D E PROGRAM A CIN

Qu hace esta aplicacin?

Fijndonos en el m todo principal, m a in , vem os que se ha declarado un objeto r l


de la clase CRacional.

CRacional r l = new C R a c i o n a l O :

En el siguiente paso se enva el m ensaje A signarD atos al objeto r l . El objeto


responde a este m ensaje ejecutando su m todo A signarD atos que alm acena el
valor 2 en su num erador y el valor 5 en su denom inador; am bos valores han sido
pasados com o argum entos.

r l .A s i g n a r D a t o s t 2 . 5 ) :

Finalm ente, se enva el m ensaje V isualizarR acional al objeto r l. El objeto


responde a este m ensaje ejecutando su m todo VisualizarRacional que visualiza
sus atributos num erador y denom inador en form a de quebrado; en nuestro caso, el
nm ero racional 2/5.

r l . V i s u a l i z a r R a c i o n a l ( );

Para finalizar, com pile, ejecute la aplicacin y observe que el resultado es el


esperado.

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

ELEMENTOS DEL LENGUAJE


En este captulo verem os los elem entos que aporta Java (caracteres, secuencias de
escape, tipos de datos, operadores, etc.) para escribir un program a. El introducir
este captulo ahora es porque dichos elem entos los tenem os que utilizar desde el
principio; algunos ya han aparecido en los ejem plos del captulo 1 y 2. C onsidere
este captulo com o soporte para el resto de los captulos; esto es, lo que se va a
exponer en l, lo ir utilizando en m enor o m ayor m edida en los captulos sucesi
vos. Por lo tanto, lim tese ahora sim plem ente a realizar un estudio con el fin de
inform arse de los elem entos con los que contam os.

PRESENTACIN DE LA SINTAXIS DE JAVA


Las palabras clave aparecern en negrita y cuando se utilicen deben escribirse
exactam ente com o aparecen. En cam bio, el texto que aparece en cursiva, significa
que ah debe ponerse la inform acin indicada por ese texto. Por ejem plo:
if (e x p r e s i n b oo leana)
s e n t e n c i a ( s ) a e j e c u t a r si la e x p r e s i n b o o l e a n a es v e r d a d :
else
s e n t e n c i i s ) a e j e c u t a r si la e x p r e s i n b o o l e a n a es falsa;

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

C uando dos o m s opciones aparecen entre llaves { } separadas por I, se


elige una, la necesaria para la expresin que se desea construir. Por ejem plo:
constante_entera[ M I L I ] .
38 JA VA : C U R SO DE PROGRAM A CIN

CARACTERES DE JAVA

Los caracteres de Java pueden agruparse en letras, dgitos, espacios en blanco, ca


racteres especiales, signos de puntuacin y secuencias de escape.

Letras, dgitos y otros


E stos caracteres son utilizados para form ar las constantes, los identificadores y las
p a labras clave de Java. Son los siguientes;

Letras m aysculas de los alfabetos internacionales:


A - Z (son v lid a s las letras acentuadas y la )

Letras m insculas de los alfabetos internacionales:


a - z (son v l i d a s las letras acentuadas y la )

D gitos de los alfabetos internacionales, entre los que se encuentran:


0 1 2 3 4 5 6 7 8 9

C aracteres: $ y cualquier carcter U nicode por encim a de 00C0.

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

L os caracteres espacio en blanco (A SC II SP), fabulador horizontal (A SC II HT),


avance de pgina (A SC II FF), nueva lnea (A SC II LF), retom o de carro (A SC II
C R) o C R L F (estos dos caracteres son considerados com o uno solo: V?), son ca
racteres denom inados espacios en blanco, porque la labor que desem pean es la
m ism a que la del espacio en blanco: actuar com o separadores entre los elem entos
de un program a, lo cual perm ite escribir program as m s legibles. P or ejem plo, el
siguiente cdigo:

p u b l i c s t a t i c v o i d main ( S t r i n g f ] args) i System .out.p rin t(


" H o l a , qu t a l e s t i s . \ n ); I

puede escribirse de una form a m s legible as:

public s t a t ic v o i d main (StringH args)


I
System .out.printt"Hola, qu t a l est is.\n");
C A PTU LO 3: ELEM ENTOS D E L L EN G U A JE 3 9

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:

Caracteres especiales y signos de puntuacin


Este grupo de caracteres se utiliza de diferentes form as; p o r ejem plo, p ara indicar
que un identificador es una funcin o un array; para especificar una determ inada
operacin aritm tica, lgica o de relacin, etc. Son los siguientes:

. . : : ? ' " ( ) [ ] ( ] <! | / +

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.

El lenguaje Jav a tiene predefinidas las siguientes secuencias de escape:

S ecuencia A S C II D efinicin

\n CR+LF Ir al principio de la siguiente lnea


\t HT T abulador horizontal
\b BS R etroceso (backspace)
\r CR R etorno de carro sin avance de lnea
\f FF A lim entacin de pgina (slo para im presora)
1 C om illa sim ple
\" 1 C om illa doble
\\ \ B arra invertida (backslash)
\ddd C arcter A SC II. R epresentacin octal
\ ud d d d C arcter A SC II. R epresentacin Unicode
\u0007 BEL A lerta, pitido
\ u000 B VT T abulador vertical (slo para im presora)
40 JA V A: C U R SO DE PROGRAM A CIN

O bserve en el ejem plo anterior la secuencia de escape Vz en la llam ada al


m todo p rin t.

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:

datol = 20; d a t o 2 = 10: resu ltad o = datol + dato2;

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:

int datol. dato2, resultado:

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.

T ipos enteros: by te, s h o rt, int. lo n g y c h a r.


T ipos reales: flo a t y double.

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.

Se les llam a prim itivos porque estn integrados en el sistem a y en realidad no


son objetos, lo cual hace que su uso sea m s eficiente. M s adelante verem os
tam bin que la biblioteca Java proporciona las clases: B ytc, C h a ra c te r, S h o rt,
In te g e r, L o ng. F lo a t, D o u b le y B oolean, para encapsular cada uno de los tipos
expuestos, proporcionando as una funcionalidad aadida para m anipularlos.
C A P T U L O 3: ELEM ENTOS D E L LEN G U A JE 4 1

byte

El tipo b y te se utiliza para declarar datos enteros com prendidos entre -1 2 8 y


+27. Un byte se define com o un conjunto de 8 bits, independientem ente de la
plataform a en que se ejecute el cdigo byte de Java. El siguiente ejem plo declara
la variable b de tipo b y te y le asigna el valor inicial 0. Es recom endable iniciar
toda variable que se declare.

byte b = 0 :

short

El tipo s h o rt se utiliza para declarar datos enteros com prendidos entre -3 2 7 6 8 y


+32767. Un valor s h o rt se define com o un dato de 16 bits de longitud, indepen
dientem ente de la plataform a en la que resida el cdigo byte de Java. El siguiente
ejem plo declara i y j com o variables enteras de tipo sh o rt:

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 */

En general, el uso de enteros de cualquier tipo produce un cdigo com pacto y


rpido. A s m ism o, podem os afirm ar que la longitud de un s h o rt es siem pre m e
nor o igual que la longitud de un int.

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 a = -1L: /* L indica que la constante 1 es long */


l o n g b = 1 25:
42 JA V A: C U R SO D E PRO G R A M A CI N

long c = 0xlF00230F; /* v a lo r en h e x a d e c i m a l */

En general, podem os afirm ar que la longitud de un in t es m enor o igual que la


longitud de un long.

char

El tipo c h a r es utilizado para declarar datos enteros en el rango \u 0 0 0 0 a \uF F F F


en U nicode (0 a 65535). L os valores 0 a 127 se corresponden con los caracteres
A SCII del m ism o cdigo (ver los apndices). El ju eg o de caracteres A SC II con
form an una parte m uy pequea del juego de caracteres Unicode.

c h a r c a r = 0;

En Java para representar los caracteres se utiliza el cdigo Unicode. Se trata


de un cdigo de 16 bits (esto es, cada carcter ocupa 2 bytes) con el nico prop
sito de internacionalizar el lenguaje. El cdigo Unicode actualm ente representa
los caracteres de la m ayora de los idiom as escritos conocidos en todo el mundo.

El siguiente ejem plo declara la variable ca r de tipo c h a r a la que se le asigna


el carcter a ' com o valor inicial (observe que hay una diferencia entre "a" y a\ a
entre com illas sim ples es interpretada por el com pilador Java com o un valor, un
carcter, y a sin com illas sera interpretada com o una variable). Las cuatro decla
raciones siguientes son idnticas:

char car = ' a :


char c a r = 97; /* la ' a ' es el d e c i m a l 97 * /
char car = 0x0061; /* la a es el he xa d e c im a l 0061 */
char car = \u 0061 : /* la a ' e s el Unicode 0061 */

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

El tipo d o u b le se utiliza para declarar un dato en com a flotante de 64 bits en el


form ato IE EE 754 (1 bit para el signo, 11 bits para el exponente y 52 para la
m antisa). L os datos de tipo d o u b le alm acenan valores con una precisin aproxi
m ada de 16 dgitos. Para especificar explcitam ente que una constante (un literal)
es de tipo d o u b le, hay que aadir al final de su v alo r la letra d ' o D ; p o r om i
sin, una constante es considerada de tipo d o u b le. El siguiente ejem plo declara
las variables a, b y c, de tipo real de precisin doble:

double a = 3 . 1 4 1 5 9 : / * una c o n s t a n t e e s d o u b l e por om isin */


double b = 2.2e+5: / * 2 . 2 e - 5 - 2 . 2 p o r 10 e l e v a d o a 5 * /
double c = 2/3D:

boolean

El tipo b o o lean se utiliza para indicar si el resultado de la evaluacin de una ex


presin booleana es verdadero o falso. Los dos posibles valores de una expresin
booleana son tr u e y false. Los literales tr u e y false son constantes definidas co
mo palabras clave en el lenguaje Java. Por tanto, se pueden u tilizar las palabras
tru e y false com o valores de retorno, en expresiones condicionales, en asignacio
nes y en com paraciones con otras variables booleanas.

El contenido de una variable booleana no se puede convertir a otros tipos, pe


ro s se puede convertir en una cadena de caracteres.

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.

Un literal en Java puede ser: un entero, un real, un valor booleano, un carc


ter, una cadena de caracteres y un valor nulo.
44 JAVA: C U R SO D E PROGRAM A CIN

Literales enteros
El lenguaje Java perm ite especificar un literal entero en base 10, 8 y 16.

En general, el signo + es opcional si el valor es positivo y el signo - estar


presente siem pre que el valor sea negativo. Un literal entero es de tipo in t a no ser
que su valor absoluto sea m ayor que el de un in t o se especifique el sufijo / o L,
en cuyo caso ser long. Lo expuesto queda resum ido en la lnea siguiente:

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:

4326 con stante entera int


4326L con stante entera long
3426000000 c o n sta n te entera long

Un literal entero octal puede tener uno o m s dgitos del 0 a 7, precedidos por
0 (cero). Por ejem plo:

0326 constante entera i n t en b a s e 8

Un literal entero hexadecim al puede tener uno o m s dgitos del 0 a 9 y letras


de la A a la F (en m aysculas o en m insculas) precedidos por Ox o OX (cero se
guido de x). Por ejem plo:

256 nmero decimal 2 56


0400 nmero decimal 2 5 6 e x p r e s a d o en o c t a l
0x100 n mero decimal 2 5 6 e x p r e s a d o en h e x a d e c i m a l
-0400 n mero decimal - 2 5 6 e x p r e s a d o en o c t a l
-0x100 nmero decimal - 2 5 6 e x p r e s a d o en h e x a d e c i m a l

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 ]

donde exponente representa cero o m s dgitos del 0 al 9 y E o e es el sm bolo de


exponente de la base 10 que puede ser positivo o negativo (2 E -5 = 2 x IQ-5 ). Si
CA PTU LO 3: ELEM EN TO S D E L LEN G U A JE 4 5

la constante real es positiva no es necesario especificar el signo y si es negativa


lleva el signo m enos (- ). Por ejem plo:

17.24
17.244283
.008e3
27E-3

U na constante real tiene siem pre tipo d o u b le , a no ser que se aada a la m is


ma u n a / o F, en cu yo caso ser de tipo flo at. P or ejem plo:

17.24F constante real de t i p o float

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:

17.24D constante real de t i p o double

Literales de un solo carcter


Los literales de un solo carcter son de tipo c h a r. E ste tipo de literales est for
mado por un nico carcter encerrado entre com illas sim ples. U na secuencia de
escape es considerada com o un nico carcter. A lgunos ejem plos son:

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

El valor de una constante de un solo carcter es el valor que le corresponde en


el ju eg o de caracteres de la m quina.

Literales de cadenas de caracteres


Un literal de cadena de caracteres es una secuencia de caracteres encerrados entre
com illas dobles (incluidas las secuencias de escape com o \ ). Por ejem plo:

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.print"Escriba un n me r o e n t r e 1 y 5\n0 pulse E n t r a r );

Las cadenas de caracteres en Java son objetos de la clase S t r in g que estudia


rem os m s adelante. Esto es, cada vez que en un program a se utilice un literal de
caracteres. Jav a crea de form a autom tica un objeto S t r in g con el valor del literal.

Las cadenas de caracteres se pueden concatenar (unir) em pleando el operador


+. Por ejem plo, la siguiente sentencia concatena las cadenas D istancia: ", distan
cia, y Km.".

System.out.p rin tln ("D ista n cia : " + distancia + " Km.");

Si alguna de las expresiones no se corresponde con una cadena, com o se su


pone que ocurre con distancia. Java la convierte de form a autom tica en una ca
dena de caracteres. M s adelante aprender el porqu de esto.

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

lo cual indica que un identificador consta de uno o m s caracteres (vase el apar


tado anterior Letras, dgitos y otros) y que el p rim er carcter debe ser una letra,
el ca rcter d e subrayado o el carcter d la r ($). N o pueden com enzar por un d
gito ni pueden contener caracteres especiales (vase el apartado anterior "C aracte
res especiales ).

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.

Los identificadores pueden tener cualquier nm ero de caracteres. Algunos


ejem plos son:

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:

abstract default if pri vate throw


boolean do i mp1e me n t s protected throws
break double import publi c transient
byte el s e instanceof return try
case extends i nt short void
catch final interface stati c v o l a t i 1e
char f i n a 11 y 1 ong super whi 1 e
el a s s f 1o a t n a t i ve s wi t c h
const for new s y n c h r o n i zed
continu goto package thi s

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:

C om entario tradicional. Un com entario tradicional em pieza con los caracte


res /* y finaliza con los caracteres */. Estos com entarios pueden ocupar ms
de una lnea, pero no pueden anidarse. P or ejem plo:

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

DECLARACIN DE CONSTANTES SIMBLICAS


D eclarar una constante sim blica significa d ec irle al com pilador Java el nombre
de la constante y su valor. Esto se hace utilizando el calificador fin a l y/o el static.

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

C om o se observa en el ejem plo anterior, declarar una constante sim blica su


pone anteponer el calificador final, o bien los calificadores fin a l y static. al tipo y
nom bre de la constante, que ser iniciada con el valor deseado. D istinguim os dos
casos: que la constante est definida en el cuerpo de la clase, fuera de todo m to
do, com o sucede con d e l y cte2 , o que est definida dentro de un m todo, como
sucede con ele3. En el prim er caso, la constante puede estar calificada, adem s de
con final, con static; en este caso, slo existir una copia de la constante para to
dos los objetos que se declaren de esa clase (en nuestro caso, la clase es CEle
m entosJava). Si no se especifica static, cada objeto incluira su propia copia de la
constante; es claro que esta form a de proceder no parece lgica por tratarse de la
m ism a constante, razn por la que no se hace uso de ella. En el segundo caso no
se puede utilizar static, la constante slo es visible dentro del m todo, y slo
existe durante la ejecucin del m ism o; en este caso se dice que la constante es lo
cal al m todo. U na constante local no pueden ser declarada static.
CA PTU LO 3: ELEM ENTOS DEL LENGUAJE 4 9

U na vez que se haya declarado una constante, por definicin, no se le puede


asignar o tro valor. Por ello, cuando se declara una constante debe ser iniciada con
un valor. Por ejem plo, despus de haber declarado cte3 segn se m uestra en el
ejem plo anterior, una sentencia com o la siguiente dara lugar a un error:

cte3 - 3.14;

Por qu utilizar constantes?


U tilizando constantes es m s fcil m odificar un program a. Por ejem plo, supon
gam os que un program a utiliza N veces una constante de valor 3.14. Si hemos
definido dicha constante com o fin a l slalic double P i = 3.14 y posteriorm ente ne
cesitam os cam biar el valor de la m ism a a 3.1416, slo tendrem os que m odificar
una lnea, la que define la constante. En cam bio, si no hem os declarado Pi, sino
que hem os utilizado el valor 3.14 directam ente N veces, tendram os que realizar
N cam bios.

DECLARACIN DE UNA VARIABLE


U na variable representa un espacio de m em oria para alm acenar un v alor de un
determ inado tipo. El valor de una variable, a diferencia de una constante, puede
cam biar durante la ejecucin de un program a. Para utilizar una variable en un
program a, prim ero hay que declararla. La declaracin de una variable consiste en
enunciar el nom bre de la m ism a y asociarle un tipo:

tipo identificador [. ideriti f i c a d o r ] ...

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.

Por definicin, una variable declarada dentro de un bloque, entendiendo por


bloque el cdigo encerrado entre los caracteres '{ y *}, es accesible directa
mente, esto es, sin un objeto, slo dentro de ese bloque. M s adelante, cuando
tratem os con objetos m atizarem os el concepto de accesibilidad.

Segn la definicin anterior, las variables da, m es y ao son accesibles desde


todos los m todos no s ta tic de la clase CElem entos Java. E stas variables, declara
das en el bloque de la clase pero fuera de cualquier otro bloque, se denom inan va
riables m iem bro de la clase (atributos de la clase).

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.

Iniciacin de una variable


Las variables m iem bro de una clase son iniciadas por om isin por el com pilador
Java para cada objeto que se declare de la m isma: las variables num ricas con 0,
los caracteres con Y) y las referencias a las cadenas de caracteres y el resto de las
referencias a otros objetos con nuil. T am bin pueden ser iniciadas explcitam ente.
En cam bio, las variables locales no son iniciadas por el com pilador Java. Por lo
tanto, es nuestra obligacin iniciarlas, de lo contrario el com pilador visualizar un
m ensaje de erro r en todas las sentencias que hagan referencia a esas variables.

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)

CONVERSIN ENTRE TIPOS DE DATOS


Cuando Java tiene que evaluar una expresin en la que intervienen operandos de
diferentes tipos, prim ero convierte, slo para realizar las operaciones solicitadas,
los valores de los operandos al tipo del operando cuya precisin sea m s alta.
Cuando se trate de una asignacin, convierte el v alor de la derecha al tipo de la
variable de la izquierda siem pre que no haya prdida de inform acin. E n otro ca
so, Java exige q ue la conversin se realice explcitam ente. L a figura siguiente re
sume los tipos colocados de izquierda a derecha de m enos a m s precisos; las
flechas indican las conversiones im plcitas perm itidas:

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

La expresin es convertida al tipo especificado si esa conversin est perm iti


da; en otro caso, se obtendr un error. La utilizacin apropiada de construcciones
cast garantiza una evaluacin consistente, pero siem pre que se pueda, es m ejor
evitarla ya que suprim e la verificacin de tipo proporcionada por el com pilador y
por consiguiente puede conducir a resultados inesperados, o cuando m enos, a una
prdida de precisin en el resultado. Por ejem plo:

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

El siguiente ejem plo m uestra c m o u tilizar estos operadores. C om o ya hem os


venido diciendo, observe que prim ero se declaran las variables y despus se reali
zan las operaciones deseadas con ellas.

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.

En una asignacin, el resultado obtenido en una operacin aritm tica es c o n


vertido im plcita o explcitam ente al tipo de la variable que alm acena dicho re
sultado (vase "C onversin entre tipos de datos ). Por ejem plo, del resultado de
x/y slo la parte entera es asignada a c. y a que c es de tipo int. Esto indica que los
reales son convertidos a enteros, truncando la parte fraccionaria.

Un resultado real es redondeado independientem ente del valor de la prim era


cifra decim al suprim ida. O bserve la operacin x/y para x igual a 2 e y igual a 3. El
resultado es 0.6666667 en lugar de 0.6666666.

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 ___________________________________________________

< P rim er operando menor que el segundo?


> P rim er operando m ayor que el segundo?
<= P rim er operando m enor o igual que el segundo?
>= P rim er operando mayor o igual que el segundo?
!= P rim er operando distinto que el segundo?
==______________ P rim er operando igual que el segundo?____________
54 JA VA : C U R S O DE PROGRAM A CIN

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

Un operador d e relacin equivale a una pregunta relativa a cm o son dos ope


randos entre s. Por ejem plo, la expresin x= = y equivale a la pregunta x es igual
a y ? U na respuesta s equivale a un valor verdadero (true) y una respuesta no
equivale a un valor falso (false).

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.

El resultado de una operacin lgica es de tipo b o o lean . P or ejem plo:

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.

El siguiente ejem plo m uestra cm o utilizar estos operadores:

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

Operadores a nivel de bits


Estos operadores perm iten realizar con sus operandos las operaciones A N D , OR,
XOR y desplazam ientos, bit por bit. Los operandos tienen que ser enteros.

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.

Los operandos tienen que ser de un tipo prim itivo entero.


56 JA VA : C U R S O DE PROGRAM A CIN

int a = 255. r = 0. m - 32:

r - a & 017: // i 15. Po n e a c e r o t o d o s l o s b i t s d e a


II e x c e p t o l o s 4 b i t s de me n o r p e s o .
r - r | m: II r = 4 7 . Pone a 1 t o d o s l o s b i t s d e r que
II e s t n a 1 en m.
r - a & -07; // r = 2 4 8 . Po ne a 0 l o s 3 b i t s de me n o r p e s o de a
r = a 7: II r - 1 . D e s p l a z a m i e n t o de 7 b i t s a l a d e r e c h a .
r = m << 1: II r=64. Equivale a r = m * 2
r = m >> 1: II r=16. E q u iv a le a r = m / 2

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 .

El operador de increm ento increm enta su operando independientem ente de


que se utilice com o sufijo o com o prefijo; esto es, n + + y ++n producen el m ismo
resultado. Idem para el operador de decrem ento.

A hora bien, cuando el resultado de una operacin de increm ento se asigna a


una variable, com o se puede o bservar en x = ++n y x = + + , si el operador de
increm ento se utiliza com o prefijo prim ero se realiza la operacin de increm ento y
despus la asignacin; y si se utiliza com o sufijo, prim ero se realiza la operacin
de asignacin y despus la de increm ento. dem para el operador de decrem ento.

Operador condicional
El operador condicional (?;), llam ado tam bin operador ternario, se utiliza en ex
presiones condicionales, que tienen la form a siguiente:

operandoI ? operando2: operando3

La expresin o p era n d o l debe ser una expresin booleana. La ejecucin se


realiza de la siguiente forma:

Si el resultado de la evaluacin de op era n d o l es tru e , el resultado de la ex


presin condicional es operando2.

Si el resultado de la evaluacin de o p era n d o l es false. el resultado de la ex


presin condicional es operando3.

El siguiente ejem plo asigna a m a yo r el resultado de (a > b ) ? a : b , que ser a


si a es m ayor que b y b a no es m ay o r que b.

double a = 10.2. b = 20.5, m a y o r = 0;


m a y o r = ( a > b ) ? a : b;
58 JA VA : C U R S O DE PROGRAM A CIN

PRIORIDAD Y ORDEN DE EVALUACIN


La tabla q ue se presenta a continuacin, resum e las reglas de prioridad y asociati-
vidad de todos los operadores. Las lneas se han colocado de m ayor a m enor prio
ridad. Los operadores escritos sobre una m ism a lnea tienen la m ism a prioridad.

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

U na ecuacin se puede ver com o un objeto que envuelve el exponente, los


coeficientes y los m todos que perm itan m anipularla. Para hacer sencillo el ejem
plo que tratam os de exponer, el exponente lo suponem os fijo de valor 3, los coefi
cientes sern variables, y aadirem os dos m todos: uno que perm ita establecer la
ecuacin con la que deseam os trabajar y otro que perm ita evaluarla para un valor
de x dado. R esum iendo, los objetos C E cuacion tendrn unos atributos que sern
los coeficientes y unos m todos E cuacin y ValorPara para m anipularlos.

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.

El m todo ValorPara evaluar la ecuacin para el valor de x pasado com o ar


gum ento. Este m todo, utilizando la sentencia return. devolver com o resultado
el valor calculado. O bserve que el tipo devuelto por el m todo es double:

Tipo del valor Parmetro que s e pasar


J retornado J como argumento

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

Han aparecido algunos conceptos nuevos (argum entos pasados a un m todo y


valor retornado por un m todo). No se preocupe, slo se trata de un prim er con
tacto. M s adelante estudiarem os todo esto con m ayor profundidad. Para una
m ejor com presin de lo dicho, piense en el m todo o funcin llam ado logaritm o
que seguro habr utilizado m s de una v ez a lo largo de sus estudios. E ste m todo
devuelve un valor real correspondiente al logaritm o del valor pasado com o argu
mento: x = log(y). B ueno, pues com prelo con el m todo ValorPara y com proba
r que estam os hablando de m todos anlogos.

Segn lo expuesto y aplicando los conocim ientos adquiridos en el captulo 2,


escribam os en prim er lugar la clase C E cuacion com o se m uestra a continuacin.
Observe que no es pblica.

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

El siguiente paso es aadir al m ism o fichero fuente una clase aplicacin p


blica que utilice la clase de objetos C Ecuacion. E sta clase aplicacin puede ser de
la form a siguiente:

public class CMiApl icaciori


I
public static void m a in ( S t r in g [ ] args)
I
C E c u a c i o n e c l = new C E c u a c i o n ( );
e c l . E c u a c i n d , - 3 . 2 . 0. 7 ) ;

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

R ecuerde que el m todo m a in ; es p o r donde em pieza a ejecutarse la aplica


cin. Este m todo crea un objeto e c l de la clase C E cuacion, enva al objeto e c l el
m ensaje E cuacin para establecer los coeficientes de la ecuacin y a continuacin
le enva el m ensaje ValorPara con el objetivo de evaluar la ecuacin para el valor
de x pasado com o argum ento.

U na vez escrita la aplicacin debe guardarla con el nom bre C M iAplica-


cion.java (nom bre de la clase pblica) y com pilarla. D espus puede ejecutarla y
observar los resultados. Incluso puede atreverse a evaluar otras ecuaciones para
distintos valores de x.

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

2. Q u resultados se obtienen al realizar las operaciones siguientes? Si hay errores


en la com pilacin, corrjalos y d una explicacin de por qu suceden.

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

4. Escriba el valor A SC II de la q' y de la 'Q ' sin consultar la tabla.

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.

6. E scriba el cdigo necesario para evaluar la expresin:

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.

ESTRUCTURA DE UNA APLICACIN JAVA


Puesto que Jav a es un lenguaje orientado a objetos, un program a Java se com pone
solam ente de objetos. R ecuerde que un objeto es la concrecin de una clase, y que
una clase equivale a la generalizacin de un tipo especfico de objetos. La clase
define los atributos del objeto a s com o los m todos para m anipularlos. M uchas
de las clases que utilizarem os pertenecen a la biblioteca de Java, por lo tanto ya
estn escritas y com piladas. P ero otras tendrem os que escribirlas nosotros m is
m os, dependiendo del problem a que tratem os de resolver en cada caso.

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

U na clase que contiene un m todo m a in es una plantilla para crear lo que


vam os a denom inar objeto aplicacin, objeto que tiene com o m isin iniciar y fi-
64 JA V A: C U R SO DE PROGRAM A CIN

nalizar la ejecucin de la aplicacin. Precisam ente, el m todo n ia in es el punto de


entrada y de salida de la aplicacin.

Segn lo expuesto, la solucin de cualquier problem a no debe considerarse


inm ediatam ente en trm inos de sentencias correspondientes a un lenguaje, sino de
objetos naturales del problem a m ism o, abstrados de alguna m anera, que darn
lugar a los objetos que intervendrn en la solucin del program a. El em pleo de
este m odelo de desarrollo de program as, nos conduce al diseo y program acin
orientada a objetos, m odelo que ha sido em pleado para desarrollar todos los
ejem plos de este libro.

Para ex plicar cm o es la estructura de un program a Java, vam os a plantear un


ejem plo sencillo de un program a que presente una tabla de equivalencia entre
grados centgrados y grados fa h ren h eit, com o indica la figura siguiente:

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.

A nalicem os el problem a. D e qu trata el program a? De grados. Entonces


podem os pensar en objetos grados que encapsulen un valor en grados centgra
dos y los m todos necesarios para asignar al objeto un valor en grados centgra
dos, as com o para obtener tanto el dato grados centgrados com o su equivalente
en grados fa h renheit. En base a esto, podram os escribir una clase C G rados como
se puede observar a continuacin:

class CGrados
I
prvate f lo a t gradosC; // g r a d o s centgrados

public void C e n tg ra d o sA sig n a rtflo a t gC)


I
// E s t a b l e c e r e l atributo grados centgrados
g r a d o s C = gC:
CA PTU LO 4 : ESTRU C TU R A DE UN PRO G R A M A 6 5

public float FahrenheitObtener)


I
// R e t o r n a r l o s g r a d o s f a h r e n h e i t equivalentes a gradosC
r e t u r n 9F/5F * g r a d o s C + 32:

public float Cent1grados0btener()


I
return gradosC; // r e t o r n a r los grados centgrados

El cdigo anterior m uestra que un objeto de la clase C G rados tendr una es


tructura interna form ada p o r el atributo:

gradosC , grados centgrados,


y una interfaz de acceso form ada p o r los m todos:

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

Entonces, qu tiene que hacer el objeto aplicacin? Pues, visualizar cuntos


grados fa h ren h eit son - 3 0 C, - 2 4 C n grados centgrados 96 C. Y, cm o
hace esto? E nviando al objeto CG rados los m ensajes C entgradosA signar y F ah
renheitO btener una vez para cada valor desde - 3 0 a 100 grados centgrados con
66 JA VA : C U R SO DE PROGRAM A CIN

increm entos de 6. El objeto C G rados responder ejecutando los m todos vincula


dos con los m ensajes que recibe. Segn esto, el cdigo de la clase que dar lugar
al objeto aplicacin puede ser el siguiente:

import j a v a . 1 ang.System : // i m p o r t a r la clase System

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:

public static void m a in (S trin g [] args)


I
// D e c l a r a c i n de v a r i a b l e s
C G r a d o s g r a d o s - new C G r a d o s ( ) :
int gradosCent = lim ln f e r io r :
f l o a t g r a d o s F a h r = 0:

while (gradosCent < - lim Su p e rio r) // m i e n t r a s hacer:

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

U na vez analizado el problem a, cree una nueva aplicacin desde su entorno


de desarrollo y escriba la clase CGrados', observe que no es pblica. A continua
cin, escriba la clase aplicacin C A pG rados en el m ism o fichero fuente; observe
CA PTU LO 4: ESTRU C TU R A DE UN PRO G R A M A 6 7

que es pblica. D espus, guarde la aplicacin que ha escrito en un fichero utili


zando com o nom bre el de la clase aplicacin; esto es, CApGrados.jcivci. Final
m ente, com pile y ejecute la aplicacin.

N o se preocupe si no entiende todo el cdigo. A hora lo que im porta es que


aprenda cm o es la estructura de un program a, no por qu se escriben unas u otras
sentencias, cuestin que aprender m s tarde en ste y en sucesivos captulos.
Este ejem plo le servir com o plantilla para inicialm ente escribir sus propios pro
gram as. Posiblem ente su prim era aplicacin utilice solam ente un objeto aplica
cin, pero con este ejem plo tendr un concepto m s real de lo que es una
aplicacin Java.

En el ejem plo realizado podem os observar que una aplicacin Java consta de:

Sentencias im p o rt (para establecer vnculos con otras clases de la biblioteca


Jav a o realizadas por nosotros).
U na clase aplicacin pblica (la que incluye el m todo m ain).
O tras clases no pblicas.

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:

D efiniciones y/o declaraciones.


S entencias a ejecutar.

E n un fichero se pueden incluir tantas definiciones de clase com o se desee,


pero slo una de ellas puede ser declarada com o pblica (pu b lic). R ecuerde que
cada clase pblica debe ser guardada en un fichero con su m ism o nom bre y exten
sin .java.

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.

Paquetes y proteccin de clases


Un paquete es un conjunto de clases, lgicam ente relacionadas entre s, agrupadas
bajo un nom bre (por ejem plo, el paquete ja v a .io agrupa las clases que perm iten a
un program a realizar la entrada y salida de inform acin); incluso, un paquete pue
de contener a otros paquetes. A nlogam ente a com o las carpetas o directorios
ayudan a o rganizar los ficheros en un disco duro, los paquetes ayudan a organizar
las clases en grupos para facilitar el acceso a las m ism as cuando las necesitem os
en un program a. A prender a crear paquetes m s adelante, ahora es suficiente con
que aprenda a utilizar los paquetes de la biblioteca de Java.
68 JA VA : CU R SO DE PROGRAM A CIN

La propia biblioteca de clases de Java est organizada en paquetes dispuestos


jerrquicam ente. En la figura siguiente se m uestran algunos de ellos:

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.

Para referirnos a una clase de un paquete, tenem os que hacerlo utilizando su


nom bre com pleto, excepto cuando el paquete haya sido im portado im plcita o ex
plcitam ente, com o verem os a continuacin. P or ejem plo, ja v a .la n g.S y ste n i hace
referencia a la clase Sy ste m del paquete ja v a .la n g ("java.lang" es el nom bre
com pleto del paquete lang).

Las clases que guardam os en un fichero cuando escribim os un program a,


pertenecen al paquete predeterminado sin nom bre. Por ejem plo, las clases CGra-
dos y CApGrados de la aplicacin anterior pertenecen, por om isin, a este pa
quete. D e esta form a Java asegura que toda clase pertenece a un paquete.

Proteccin de una clase


La proteccin de una clase determ ina la relacin que tiene con otras clases de
otros paquetes. D istinguim os dos niveles de proteccin: de paquete y pblico.
U na clase con nivel de proteccin de paquete slo puede ser utilizada por las cla
ses de su paquete (no est disponible para otros paquetes, ni siquiera para los sub-
paquetes). En cam bio, una clase pblica puede ser utilizada por cualquier otra
clase de otro paquete. Q u se entiende p o r utilizar? Q ue una clase puede crear
objetos de otra clase y m anipularlos utilizando sus m todos.

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

2. Im portando la clase, com o se indica en el prrafo siguiente, lo que posibilita


referirse a ella sim plem ente por su nom bre. Por ejem plo:

System.out.println(gradosFahr);

Para im portar una clase de un paquete desde un program a utilizarem os la


sentencia im p ort. En un program a Java puede aparecer cualquier nm ero de sen
tencias im p o rt, las cuales deben escribirse antes de cualquier definicin de clase.
Por ejem plo:

i mpor t j a v a . l a n g . S y s t e m : // i m p o r t a r la clase System

public class CApGrados


1
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 );
11...
\

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

public class CApGrados


I
I I ...
S y s t e m , o u t . p r i n t l n( g r a d o sC e n t + " C" + " \ t + g r a d o s F a h r + " F " ) ;
11...
I

En realidad, para ser exactos, la sentencia im p o rt del ejem plo anterior im


p orta todas las clases pblicas del paquete ja v a .la n g que realm ente se usen en el
cdigo del program a.

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:

A dem s, una variable puede ser iniciada en la propia definicin:

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:

La definicin de un m todo, declara el m todo y adem s incluye el cuerpo del


m ism o. En cam bio, la declaracin de un m todo se corresponde con la cabecera
de dicho m todo (su aplicacin podr verla en clases abstractas e interfaces).
CA PTU LO 4: ESTRU C TU R A DE UN PROGRAM A 7 1

public float FahrenheitObtenert)


I
// R e t o r n a r l o s g r a d o s f a h r e n h e i t e q u i v a l e n t e s a gradosC
r e t u r n 9 F / 5 F * g r a d o s C + 32;

La declaracin o la definicin de una variable pueden realizarse a nivel ele la


clase (atributos de la clase) o a nivel de! m todo (dentro de la definicin de un
m todo). Pero, la definicin de un m todo, siem pre ocurre a nivel de la clase.

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)

public void unMe todo ( . l i s t a de p a r m e t r o s )


- I
Nivel del m to d o D e c l a r a c i n de v a r i a b l e s

S e n t e r ic i as

En un m todo, las definiciones o declaraciones se pueden realizar en cual


quier lugar; o m ejor dicho, en el lugar ju sto donde se necesiten y no necesaria
mente al principio del m todo, antes de todas las sentencias.

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

Sentencia compuesta o bloque


U na sentencia com puesta o bloque, es una coleccin de sentencias sim ples inclui
das entre llaves - { } -. U n bloque puede contener a otros bloques. U n ejem plo de
una sentencia de este tipo es el siguiente:

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

La definicin de un m todo consta de una cabecera y del cuerpo del m todo en


cerrado entre llaves. La sintaxis para escribir un m todo es la siguiente:

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

Un m odificador es una palabra clave que m odifica el nivel de proteccin pre


determ inado del m todo. Vase el apartado P roteccin de los m iem bros de una
clase" expuesto un poco m s adelante.

El tipo del resultado especifica qu tipo de valor retorna el m todo. ste,


puede ser cualquier tipo prim itivo o referenciado. Para indicar que no se devuelve
nada, se utiliza la palabra reservada void. El resultado de un m todo es devuelto a
la sentencia que lo invoc, por m edio de la siguiente sentencia:

r e t u r n [ ( ] expresin[ ) ] :
CA PTU LO 4: ESTRU C TU R A D E UN PROGRAM A 7 3

L a sentencia re tu rn puede ser o no la ltim a y puede aparecer m s de una vez


en el cuerpo del m todo. En el caso de que el m todo no retorne un valor (void),
se puede om itir o especificar sim plem ente return. P or ejem plo:

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:

public void CentigradosAsignar(float gC)


I
// E s t a b l e c e r e l atributo grados centgrados
g r a d o s C = gC:
1

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:

public static void m a in (S trin g [] args)


I
// C u e r p o d e l mt od o
I

C om o se puede observar, el m todo m a in es pblico (pu b lic), esttico


(static), no devuelve nada (v o id ) y tiene un argum ento de tipo S t r in g que alm a
cenar los argum entos pasados en la lnea de rdenes cuando se invoca a la apli
cacin para su ejecucin, concepto que estudiarem os posteriorm ente en otro
captulo. Para m s detalles, puede ver un poco m s adelante los apartados Pro
teccin de los m iem bros de una clase y M iem bro de un objeto o de una clase .

Crear objetos de una clase

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.

Cmo acceder a los miembros de un objeto


Para acceder desde un m todo de la clase aplicacin o de cualquier otra clase a un
m iem bro (atributo o m todo) de un objeto de otra clase diferente se utiliza la sin
taxis siguiente: objeto.m iem bro. Por ejem plo:

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.

Cuando el m iem bro accedido es un m todo, la interpretacin que se hace en


program acin orientada a objetos es que el objeto ha recibido un m ensaje, el es
pecificado p o r el nom bre del m todo, y responde ejecutando ese m todo. Los
m ensajes que puede recibir un objeto se corresponden con los nom bres de los
m todos de su clase. P or ejem plo, una sentencia com o:

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 ):

se interpreta com o que el objeto grados recibe el m ensaje C entgradosAsignar.


Entonces el objeto responde a ese m ensaje ejecutando el m todo de su clase que
tenga el m ism o nom bre. Lgicam ente, com o el m todo se ejecuta para un objeto
concreto, el cuerpo del m ism o no necesita especificar explcitam ente de qu o b
jeto es el m iem bro accedido. Esto es, en el ejem plo siguiente se sabe que gradosC
pertenece al objeto que est respondiendo al m ensaje CentgradosAsignar.

public void C e n tig ra d o sA sig n a r(flo a t gC)


I
// E s t a b l e c e r el atributo grados centgrados
g r a d o s C - gC:
I

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

seguro que nos preguntaram os a quin se asigna el valor gra d o sC en tl Los m


todos static que estudiarem os m s tarde son una excepcin a la regla.

Proteccin de los miembros de una clase


Los m iem bros de una clase son los atributos y los m todos, y su nivel de protec
cin determ ina quin puede acceder a los m ism os. Los niveles de proteccin a los
que nos referim os son: de p a q u ete, pblico, privado y protegido. D e este ltimo
hablarem os en un captulo posterior.

Por ejem plo, en la clase C G rados de la aplicacin realizada al principio de


este captulo, hem os definido los atributos privados y los m todos, pblicos:

class CGrados
I
prvate f lo a t gradosC; // g r a d o s centgrados

p u b lc void C e n tg ra d o sA sig n a rtflo a t gC)


I
// E s t a b l e c e r el atributo grados centgrados
g r a d o s C = gC:
I
// ...

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.

Si un m todo de otra clase, por ejem plo el m todo m a in de la clase C A pG ra


dos, incluyera una sentencia com o la siguiente,

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.

U n m iem bro de una clase declarado p b lico es accesible desde cualquier m


todo definido dentro o fuera de la clase o paquete actual. Por ejem plo, en la clase
CApG rados, se puede observar cm o el objeto grados de la clase C G rados creado
en el m todo m a in accede a su m todo C entgradosA signar con el fin de m odifi
car el valor de su m iem bro privado gradosC .
C A PTU LO 4: ESTRU C TU R A DE UN PRO G R A M A 7 7

public class CApGrados


I
// ...
public static void m a in ( S t r in g t ] args)
I
// D e c l a r a c i n de v a r i a b l e s
C G r a d o s g r a d o s = new C G r a d o s O :
II...
while ( g r a d o s C e n t < = 1 i i n S u p e r i o r ) // w h i l e ... hacer:
I
// 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 centgrados
grados.CentIgradosAsignar(gradosCent)
II...

G eneralm ente los atributos de una clase de objetos se declaran privados, es


tando as ocultos para otras clases, siendo posible el acceso a los m ism os nica
m ente a travs de los m todos pblicos de dicha clase. El m ecanism o de
ocultacin de m iem bros se conoce en la program acin orientada a objetos com o
encapsulacin: proceso de ocultar la estructura interna de datos de un objeto y
p erm itir el acceso slo a travs de la interfaz pblica definida, entendiendo por
interfaz pblica el conjunto de m iem bros pblicos de una clase. Q u beneficios
reporta la encapsulacin? Q ue un usuario de una determ inada clase no pueda es
cribir cdigo en base a la estructura interna del objeto, sino slo en base a la in
terfaz pblica; esta form a de proceder obliga a pensar en objetos y a trabajar con
ellos. En el captulo C lases que expondrem os m s adelante abundarem os ms
sobre lo dicho y sobre otras m uchas cuestiones.

El nivel de proteccin predeterm inado para un m iem bro de una clase es el de


paquete. Un m iem bro de una clase con este nivel de proteccin puede ser accedi
do desde todas las otras clases del m ism o paquete.

Miembro de un objeto o de una clase


Sabem os que una clase agrupa los atributos y los m todos que definen a los obje
tos de esa clase. Pero, cada objeto que creem os de esa clase m antiene una copia
tanto de los atributos com o de los m todos? L gicam ente, cada objeto m antiene
su propia copia de los atributos para alm acenar sus datos particulares; pero, de los
m todos slo hay una copia para todos los objetos, lo cual tam bin es lgico, por
que cada objeto slo requiere utilizarlos; por ejem plo, cuando necesite m odificar
sus atributos. D esde este anlisis se dice que los m iem bros son del objeto; esto es,
un m ism o atributo tiene un valor especfico para cada objeto, y un objeto ejecuta
un m todo en respuesta a un m ensaje recibido.
78 JA VA : C U R SO DE PROGRAM A CIN

Esta form a de concebir los objetos puede suponer, en ocasiones, un desperdi


cio de espacio de alm acenam iento; por ejem plo, volviendo a la clase COrdenador
que expusim os en el captulo 2, podram os pensar en aadir un nuevo atributo que
fuera el tiem po de garanta. Si suponem os que este tiem po es el m ism o para todos
los ordenadores, sera m s eficiente definir un atributo que no form ara parte de la
estructura de cada objeto, sino que fuera com partido por todos los objetos. En este
caso, direm os que el atributo es d e la clase de los objetos, no del objeto.

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.

Para acceder a un atributo static de la clase puede utilizar un objeto de la cla


se, o bien el nom bre de la clase com o puede verse en el ejem plo siguiente:

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

public static v o i d main (Stringf] args)


I
II G a r a n t a e x i s t e a u n q u e no h a y a o b j e t o s definidos de l a clase
C O r d e n a d o r . G a r a n t a - 1:

U tilizar una expresin com o M Ordenador. G aranta, siendo M iO rdenador un


objeto de la clase C O rdenador, aunque sea correcta, no se aconseja porque puede
resultar engaosa. Parece que nos estam os refiriendo al atributo G aranta del o b
je to M iO rdenador, cuando en realidad nos estam os refiriendo a todos los objetos
que el program a haya creado de la clase C O rdenador.

A nlogam ente, un m todo declarado static es un m todo de la clase. Este tipo


de m todos no se ejecutan para un objeto particular, sino que se aplican en gene
ral donde se necesiten, lo que im pide que puedan acceder a un m iem bro del obje
to. Una aplicacin puede acceder a un m todo esttico de la m ism a form a que se
ha expuesto para un atributo esttico.

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

se hubiera utilizado un m todo no static, tendra que ser invocado a travs de un


objeto de la clase, lo que, siendo correcto, resultara engaoso.

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

public static void E s t a b l e c e r G a r a n t 1 a ( b y t e g)


I
Garanta - g; // G a r a n t a es un m i e m b r o de l a clase
1
1

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.

G rficam ente puede im aginarse una referencia y el objeto referenciado, ubi


cados en algn lugar del espacio de m em oria correspondiente a su aplicacin, as:

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

En realidad una referencia es la posicin de m em oria donde se localiza un


objeto. O bservar que anteriorm ente nos hem os referido a la referencia grados
com o el objeto grados. Esto es una form a de abreviar que no crea confusin, ya
que grados es nica y referencia un nico objeto C G rados. U na expresin com o
el objeto referenciado por la variable grados" resulta dem asiado larga y no
aporta m s inform acin. Expresndonos en estos trm inos, cuando se asigne un
objeto a otro, o bien se pasen objetos com o argum entos a m todos, lo que se estn
copiando son referencias, no el contenido de los objetos.

El siguiente ejem plo aclarar este concepto. Se trata de la aplicacin C Racio


nal que expusim os al final del captulo 2, com puesta p o r la clase C R acional a la
que hem os aadido un nuevo m todo esttico que perm ite sum ar dos nm eros ra
cionales, devolviendo com o resultado el nm ero racional resultante de la sum a.

class CRacional
I
prvate int Numerador:
prvate int Denominador:

public void A sig n a rD a to stin t num. int den)


I
N u me r a d o r = num:
i f ( d e n = = 0 ) den = 1; //el d e n o m i n a d o r no pu ede s e r c e r o
D e n o m i n a d o r = den;
I

public void VisualizarRacional( )


I
S y s te m .o u t .p rin tln (N u m e ra d o r + /" + Denominador):
I
CA PTU LO 4: ESTRU C TU R A DE UN PRO G R A M A 8 1

public static CRacional SumarCCRacional a. CRacional b)


I
C R a c i o n a l r = new C R a c i o n a l O :
i n t num = a . N u m e r a d o r * b . D e n o m i n a d o r +
a . Denominador * b.Numerador:
i n t den = a . D e n o m i n a d o r * b . D e n o m i n a d o r ;
r.A signa rD a to sfn u m , den);
r e t u r n r:

public static v o i d main (String[] args)


I
// P u n t o de e n t r a d a a l a a p l i c a c i n
C R a c i o n a l r l . r2:
r l = 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
rl .AsignarD atos(2, 5):
r2 = r l :

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.

A nalizada la clase C R acional pasem os a estudiar el m todo m a in . La prim era


parte de este m todo declara dos variables r l y r2 de tipo C R acional, crea un
nuevo objeto r l de tipo C R acional asignndole el valor 2/5. y asigna el valor de
r l a r2.

A continuacin, asigna a r l un nuevo valor 3/7, cul es el valor de r2? C om


probam os que es el m ism o que el de r l . Q u ha ocurrido? Q ue cuando se asign
82 JA VA : CU R SO DE PROGRAM A CIN

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

Si realm ente lo que deseam os es que r l y r2 sealen a objetos separados, hay


que utilizar new con am bas referencias para crear objetos separados:

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

C om o hem os visto, una variable de un tipo referenciado se puede asignar a


otra del m ism o tipo. En cam bio, no existe aritm tica de referencias (por ejem plo,
a una referencia no se le puede sum ar un entero) ni tam poco se puede asignar di
rectam ente un entero a una referencia.

Pasando argumentos a los mtodos


La segunda parte del m todo m a in del ejem plo anterior, crea un objeto r2 y le
asigna el valor 2/5. A continuacin, invoca al m todo esttico S um ar pasndole
com o argum entos los objetos r l y r2 que querem os sum ar. El resultado devuelto
por Sum ar ser un objeto C Racional que quedar referenciado p o r r3.

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.

C uando se invoca a un m todo, el prim er argum ento es pasado al prim er pa


rm etro, el segundo argum ento es pasado al segundo parm etro y as sucesiva
m ente. En Jav a todos los argum entos que son objetos son pasados por referencia.

public static CRacional SumarCRacional a, CRacional b)


I
C R a c i o n a l r = new C R a c i o n a l ( );
i n t num = a . N u me r a do r * b . D e n o m i n a d o r +
a .D en omin ado r * b.N um e ra do r;
i n t den = a . D e n o m i n a d o r * b . D e n o m i n a d o r ;
r . A s i g n a r D a t o s t n u m , den):
r e t u r n r;
I

A continuacin, el m todo Sum ar utiliza new para crear un nuevo objeto r al


que asigna el resultado de la sum a de los objetos a y b. F inalm ente devuelve r.
O tra vez m s lo que se devuelve es una referencia que Se copia en r3. Finalizado
este proceso la variable r desaparece por ser local, no sucediendo lo m ism o con el
objeto que sealaba, ya que ahora est sealado por r3.

El recolector de basura de Java elim inar un objeto cuando no exista ninguna


referencia al m ism o.

PROGRAMA JAVA FORMADO POR MLTIPLES FICHEROS


Segn lo que hem os visto, un program a Java es un conjunto de objetos que se
com unican entre s. Para crear los objetos, escribim os plantillas que denom inam os
clases. Por ejem plo, en la aplicacin acerca de nm eros racionales escribim os una
sola clase, pero en la aplicacin acerca de conversin de grados centgrados a
F ahrenheit, escribim os dos clases. En am bas aplicaciones, alm acenam os todo su
cdigo en un nico fichero .java. Esto no debe inducim os a pensar que todo pro
gram a tiene que estar escrito en un nico fichero. De hecho no es as, ya que ge-
84 JA V A: C U R SO DF. PROGRAM A CIN

neralm ente se alm acena cada clase en un nico fichero para favorecer su m ante
nim iento y posterior reutilizacin.

Com o ejem plo, reconstruyam os la aplicacin C R acional creando ahora dos


clases separadas: C R acional y C Aplicacion.

La clase C R acional incluir su estructura de datos y su interfaz pblica, ex


cepto el m todo m a in que ser ahora incluido en C Aplicacion. C uando haya es
crito la clase C R acional gurdela en el fichero C Racional.java.

public class CRacional


I
private int Numerador;
prvate int Denominador:

public void AsignarDatostint num. i n t den)


I
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 n o puede s e r c e r o
D e n o m i n a d o r = den;

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

public static CRacional SumartCRacional a. CRacional b)


I
C R a c i o n a l r - new C R a c 1 o n a l ( ) :
i n t num = a . N u m e r a d o r * b . D e n o m i n a d o r +
a . Denominador * b.Numerador;
i n t den - a . Den ominador * b . D e n o m i n a d o r ;
r.Asigna rD atostn um , den);
r e t u r n r;

Escriba ahora la clase C Aplicacion que se m uestra a continuacin y gurdela


en el fichero C Aplicacion.java.

public class CAplicacion


I
p u b l i c s t a t i c v o i d main ( S t r i n g f ] a r g s )
i
// P u n t o de e n t r a d a a l a a p l i c a c i n
C Ra cio nal r l . r2;
CA PTU LO 4: ESTRU C TU R A D E UN PROGRAM A 8 5

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

CRa cio nal r3:


r?. = 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
r2 .A sig n a rD a to s(2 , 5):
r3 = C R a c i o n a l . S u m a r r l , r 2 ); // r 3 = 3 / 7 + 2/5
r3.VisualizarRacional(): // s e v i s u a l i z a 2 9 / 3 5

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)

public v o i d unMe todo ( . l i s t a de p a r m e t ro s )


V a ria b le lim itada
a un m to d o Variables locales

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.

U na variable declarada dentro de un m todo es una variable local al mtodo.


L os parm etros de un m todo son tam bin variables locales al m todo. Y una va
riable declarada dentro de un bloque correspondiente a una sentencia com puesta
tam bin es una variable local a ese bloque.

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.

U na vez abstradas las caractersticas generales de la clase de objetos cuentas


bancarias, el paso siguiente es escribir el cdigo que da lugar a la im plem entacin
de dicha clase. sta puede ser m s o m enos as:
/**
* E s t a c l a s e i m p l e m e n t a una c u e n t a b a n c a r i a que
* s i m u l a e l c o m p o r t a m i e n t o b s i c o de una c u e n t a
* a b i e r t a en una e n t i d a d b a n c a r i a c u a l q u i e r a .
*/
public class CCuentaBancaria
I
p riv a t e double t i p o D e l n t e r s :
p rv a t e double saldo :

public void EstablecerTipoDelnterstdouble ti)


I
i f ( t i < 0)
I
System .out.printlnU El t i p o de i n t e r s no puede s e r n e g a t i v o " ) :
r e t u r n : // r e t o r n a r
CA PTU LO 4: ESTRU C TU R A DE UN PROGRAM A 8 7

ti poDelnters = t i ;

public void IngresarDinero(doub1e ingreso)


I
saldo += ingreso:

public void R e tira rD in e roid o u b le cantidad)


I
if ( saldo - cantidad < 0)
1
System .out.println("N o tiene saldo s u f i c i e n t e " );
return;
I
// Hay s a l d o s u f i c i e n t e . R etirar la cantidad,
saldo - - cantidad:
I

public double S a ld o A c t u a l()


I
return saldo:
I

public void A b o n a rIn te re se s()


I
s a ld o += s a ld o * tipoDelnters / 100:

public static v o i d main (StringH args)


I
// A b r i r una c u e n t a c o n 1 . 0 0 0 . 0 0 0 a un 2%
C C u e n t a B a n c a r i a C u e n t a O l - new C C u e n t a B a n c a r i a t );
C u e n ta O l. In gre sa rD i n e r o ( 1000000):
CuentaOl.EstablecerTipoDeInters(2):

// 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()):

A nalicem os brevem ente el cdigo. El m todo E stablecerTipoD ehiters veri


fica si el valor pasado com o argum ento es negativo, en cuyo caso lo notifica y
term ina. Si es positivo, lo asigna al m iem bro tipoD elnters.
88 JA V A : C U R SO D E PROGRAM A CIN

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.

El m todo SaldoA ctual devuelve el valor del saldo actual en la cuenta.

El m todo A bonarlntereses acum ula los intereses sobre el saldo actual.

Finalm ente, el m todo m a in crea e inicia un objeto de la clase C CuentaBan-


caria y realiza sobre el m ism o las operaciones program adas con el fin de com pro
bar su correcto funcionam iento.

EJERCICIOS PROPUESTOS
1. E scriba la aplicacin C ApG rados.java y com pruebe los resultados.

2. En el captulo 1 hablam os acerca del depurador. Si su entorno integrado favorito


aporta la funcionalidad necesaria para depurar un program a, pruebe a ejecutar la
aplicacin C ApG rados.java paso a paso y verifique los valores que van tom ando
las variables a lo largo de la ejecucin.

3. M odifique los lm ites inferior y superior de los grados centgrados, el increm ento,
y ejecute de nuevo la aplicacin.

4. C argue en su entorno de desarrollo integrado la aplicacin C ApG rados.java y


m odifique la sentencia:

return 9F/5F * g r a d o s C + 32;

correspondiente al m todo F ahrenheitO btener de la clase C G rados, com o se


m uestra a continuacin:

return 9/5 * g r a d o s C + 32;

Despus, com pile y ejecute la aplicacin. Explique lo que sucede.

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

CLASES DE USO COMN


A unque las clases que hem os aprendido a escribir en los captulos anteriores son
la base de nuestras aplicaciones, la potencia, en la prctica, del lenguaje Java vie
ne dada por su biblioteca de clases. Hay dos paquetes que destacan p o r las clases
de propsito general que incluyen: ja v a .io y ja v a.lan g.

El paquete ja v a .io contiene las clases de objetos que proporcionan los m to


dos necesarios para escribir inform acin en diversos dispositivos, por ejem plo en
la salida estndar (que se corresponde norm alm ente con la pantalla d e su ordena
dor) y para leer inform acin desde otros dispositivos, por ejem plo, desde la entra
da estndar (que es norm alm ente el teclado de su ordenador).

El paquete ja v a .la n g contiene clases que se aplican al lenguaje m ism o. Por


ejem plo, clases especiales que encapsulan los tipos prim itivos de datos, la clase
Sy ste m q ue proporciona los objetos para m anipular la entrada/salida (E/S) estn
dar, clases para m anipular cadenas de caracteres, una clase que proporciona los
m todos correspondientes a las funciones m atem ticas de uso m s frecuente, una
clase para analizar otras clases, etc.

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.

DATOS NUMRICOS Y CADENAS DE CARACTERES


La finalidad de una aplicacin es procesar datos que, generalm ente, sern obteni
dos de algn m edio externo p o r la propia aplicacin (por ejem plo, del teclado o de
un fichero en disco) y procesados p o r la m ism a con el fin de obtener unos resulta
dos. E stos datos se pueden clasificar en: num ricos y cadenas d e caracteres.
90 JA V A : C U R S O DE PROGRAM A CIN

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:

variable operador_de_asignacin valor

U na sentencia de asignacin es asim trica. Esto quiere decir que se evala la


expresin de la derecha y el resultado se asigna a la variable especificada a la iz
quierda. P o r ejem plo:

d = a + b * c: //el valor de a + b * c s e a s i g n a a d

Pero no sera vlido escribir:

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:

double radio, rea:


// .. .
rea = 3.141592 * radio * radio:

Las cadenas de caracteres sern alm acenadas en objetos de la clase S t r in g o


en m atrices, cuyo estudio se ha pospuesto para un captulo posterior. U n objeto de
la clase S t r in g se define y se le asigna un valor, as:

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

Lgicam ente, cuando la variable tiene asignado un valor y se le asigna uno


nuevo, el valor anterior es destruido y a que el valor nuevo pasa a ocupar la m ism a
localizacin de m em oria. En el ejem plo siguiente, se puede observar con respecto
a la situacin anterior, que el contenido de n va r se m odifica con un nuevo valor
20, y que la referencia sv a r tam bin se m odifica; ahora contiene la referencia a un
nuevo objeto S t r in g "adis .

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.

La com unicacin entre el origen de cierta inform acin y el destino, se realiza


m ediante un flu jo de inform acin (en ingls stream ).

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

U n flu jo es un objeto que hace de interm ediario entre el program a, y el origen


o el destino de la inform acin. Esto es, el program a leer o escribir en el flu jo sin
im portarle desde dnde viene la inform acin o a dnde va y tam poco im porta el
tipo de los datos que se leen o escriben. Este nivel de abstraccin hace que el pro
gram a no tenga que saber nada ni del dispositivo ni del tipo de inform acin, lo
que se traduce en una facilidad m s a la hora de escribir program as.
92 JA V A: C U R SO DE PROGRAM A CIN

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.

El m todo m s im portante de esta clase es read. Este m todo se presenta de


tres form as:

public int r e a d O th rows IO E x c e p tio n


public int r e a d { b y t e [ ] b ) th rows IO E x c e p tio n
public int r e a d ( b y t e [ ] b, i n t off. i n t len) t h r o w s I O E x c e p t i o n

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

P o r ejem plo, suponiendo que tenem os definido un objeto flu jo E (flujo de en


trada) de alguna subclase de In p u tS tre a m . el siguiente cdigo lee un byte del
origen vinculado con flu jo E :

i n t n:
n = f 1u j o E . r e a c K ):

La segunda versin del m todo read lee un nm ero de bytes de un flujo de


entrada y los alm acena en una m atriz b (m s adelante, dedicarem os un captulo a
ex plicar las m atrices de datos). D evuelve un entero correspondiente al nm ero de
bytes ledos, o bien -1 si no hay bytes disponibles p ara leer porque se ha alcanza
do el final del flujo.

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.

A nlogam ente, la clase R e a d e r es una clase abstracta que es superclase de


todas las clases que representan un flujo para leer caracteres desde un origen. Sus
94 JA V A : C U R SO DE PROGRAM A CIN

m todos son anlogos a los de la clase In p u tS tre a m , con la diferencia de que


utilizan parm etros de tipo c h a r en lugar de byte.

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.

El m todo m s im portante de esta clase es write. E ste m todo se presenta de


tres formas:

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

b y t e [ ] b = new b y t e [ 1 2 8 1 ; II m a t r i z 'b ' de 128 b y t e s


flujoS.w rite(b ):

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.

A nlogam ente, la clase W r it e r es una clase abstracta que es superclase de to


das las clases que representan un flujo para escribir caracteres a un destino. Sus
C A PTU LO 5: CL A SES DE USO C O M N 9 5

mtodos son anlogos a los de la clase O u tp u tS tre a m , con la diferencia de que


utilizan parm etros de tipo c h a r en lugar de byte.

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.

Las excepciones en Java son objetos de subclases de T h ro w a b le . Por ejem


plo, el paquete ja v a .io define una clase de excepcin general denom inada IO E x -
eeption para excepciones de entrada salida.

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

En el ejem plo anterior, el m anejo de la excepcin se ha reducido a visualizar


un m ensaje del erro r ocurrido.
96 JA V A: C U R SO DE PRO G R A M A CI N

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.

Flujos estndar de E/S


La biblioteca de Java proporciona tres flujos estndar, m anipulados por la clase
S y ste m del paquete ja v a .Ia n g, que son autom ticam ente abiertos cuando se inicia
un program a y cerrados cuando ste finaliza:

System .in. R eferencia a la entrada estndar del sistem a, que normalmente


coincide con el teclado. Se utiliza para leer datos introducidos p o r el usuario.

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.

Los siguientes ejem plos ilustran la utilizacin de los flujos in y out:

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

El m todo read devuelve un entero (in t) correspondiente al valor A SC II del


carcter ledo. A hora este valor puede ser convertido a otro tipo com o byte:

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

Determinar la clase a la que pertenece un objeto

La clase O b je c t del paquete ja v a .la n g es la clase raz de la jerarq u a de clases de


Java. Esto quiere decir que el resto de las clases se deriva directa o indirectam ente
de esta clase, lo que a su vez significa que todas heredan todos sus m iem bros. Por
lo tanto, todos los objetos disponen de los m todos proporcionados p o r Object.

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

La lnea anterior indica que g e tC la s s devuelve un objeto de la clase C la ss,


O bjetoC lass, cuyos m todos perm itirn obtener inform acin acerca de la clase del
objeto referenciado por cualquierO bjeto. Por ejem plo, el m todo ge tN a m e de
vuelve una cadena correspondiente al nom bre de la clase; g e tM e th o d s devuelve
una m atriz de la clase M e t h o d con los nom bres de todos los m todos, etc.

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

El m todo m a in de la aplicacin anterior, prim ero solicita un dato que sera


introducido a travs del teclado, despus visualiza el dato, y finalm ente o b tien e)
visualiza los nom bres de las clases de los objetos correspondientes a los flujos
estndar. C uando ejecute la aplicacin el resultado ser sim ilar al siguiente:

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

La capacidad de conocer detalles de otras clases (incluidas las nuestras) a tra


vs de una clase habilitada por Java se conoce com o reflexin.

BufferedlnputStream

La clase B u ffe r e d ln p u tS tre a m se deriva indirectam ente de In p u tS tre a m , por lo


tanto hereda todos los m iem bros de sta: por ejem plo, el m todo re a d expuesto
anteriorm ente. Esta clase, aunque no aporta m todos nuevos, s aporta una carac
terstica muy interesante de la que se benefician todos sus m todos: un buffer que
acta com o una m em oria interm edia para lecturas futuras. Para entender esto ob
serve la figura siguiente:

Segn el esquem a anterior, cuando una aplicacin ejecute una sentencia de


entrada (que solicite datos) los datos obtenidos del origen pueden ser depositados
en el buffer en bloques m s grandes que los que realm ente est leyendo la aplica
cin (por ejem plo, cuando se leen datos de un disco la cantidad m nim a de infor
m acin transferida es un bloque equivalente a una unidad de asignacin). Esto
aum enta la velocidad de ejecucin porque la siguiente vez que la aplicacin nece
site m s datos no tendr que esperar por ellos porque ya los tendr en el buffer.
Por otra parte, cuando se trate de una operacin de salida, los datos no sern en
viados al destino hasta que no se llene el b uffer (o hasta que se fuerce el vaciado
del m ism o im plcita o explcitam ente), lo que reduce el nm ero de accesos al dis
positivo fsico vinculado que siem pre resulta m ucho m s lento que los accesos a
m em oria, aum entado por consiguiente la velocidad de ejecucin.

C uando el origen es el teclado y el destino el program a, el esquem a es el


m ism o. Esto perm ite introducir los datos por anticipado para una aplicacin en
ejecucin de la que se sabe que m s adelante va a solicitarlos a travs del teclado.
CA PTU LO 5: CL A SES DE U SO C O M N 9 9

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

Bajo un flujo de la clase B u ffe re d R e a d e r subyace otro flujo de caracteres (objeto


de una clase derivada de R e ad e r), o bien de bytes (objeto de una clase derivada
de In p u tS tre a n i). Esto es, cada peticin de lectura hecha a un flujo de la clase
B u ffe re d R e a d e r es dirigida a otro flujo de caracteres o de bytes subyacente.

} ( Flujo \ r x
__________ I F |ui | L O rig en

s u b y a c e n te r

V J V J

La figura anterior traducida a cdigo dependiente de los flujos m encionados


en el prrafo anterior, puede interpretarse as:

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 ) :

La clase In p u t S t r e a m R e a d e r establece un puente para pasar flujos de bytes


a flujos de caracteres.

c a ra c te re s bytes

La clase B u ffe re d R e a d e r proporciona m todos anlogos a B u ffe r e d ln p u t


Stre am , y adem s otros com o re ad Lin e . Este m todo perm ite leer una lnea de
texto que devuelve en un objeto de la clase S trin g . Se entiende por lnea de texto
la cadena form ada por los caracteres que hay hasta encontrar uno de los siguien
tes: V , 'Vi' o am bos; estos caracteres son ledos pero no alm acenados.
1 0 0 JA VA : C U R SO DE PROGRAM A CIN

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

A nalicem os el m todo m a in de la aplicacin anterior. Prim eram ente define


un flujo de entrada, flu jo E , del cual se podrn leer lneas de texto. Despus, se
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. La ltim a parte del cuerpo de m a in lee
una lnea de texto introducida a travs del teclado y la visualiza.

PrintStream

La clase P rin tS tr e a m se deriva indirectam ente de O u tp u tS tre a m , por lo tanto


hereda todos los m iem bros de sta; por ejem plo el m todo w rite expuesto ante
riorm ente. O tros m todos de inters que aporta esta clase, que ya hem os utilizado,
son; p rin t y p rin tln . La sintaxis para estos m todos es la siguiente:

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:

System .out.p rint"El valor no p u e d e s e r n e g a t i v o \ n " ):


C A P T U L O 5: CL A SES DE U SO C O M N 101

es equivalente a esta otra:

System .out.println("El v a l o r no p u e d e s e r n e g a t i v o " ) :

En el ejem plo anterior, se puede observar que p r in t aade al final de la cade


na de caracteres un carcter 'Vi' que p rin tln no aade.

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

Los resultados que produce la aplicacin anterior son los siguientes:

L enguaje Java
abe
4
-9223372036854775808
3 . 4028235E38
3.141592653589793
true
102 JA V A: C U R SO D E PROGRAM A CIN

O bserve que se puede im prim ir un objeto; el p rim er m todo p r in tln imprime


un objeto S trin g . C uando se utiliza p r in t o p rin tln para im prim ir un objeto, el
dato im preso depende del tipo del objeto. En el ejem plo se puede observar que la
im presin de un objeto S t r in g hace que se im prim a la cadena de caracteres que
alm acena. S in em bargo, la im presin de un objeto C la s s dara lugar a que se im
prim iera una cadena de caracteres correspondiente al nom bre de la clase del ob
jeto que estuviera siendo inspeccionado.

La clase anloga a P rin tS tr e a m es P rin tW r ite r, clase derivada de YVriter,


pero los m todos proporcionados por am bas son prcticam ente los m ism os, por lo
que no com entarem os esta ltim a. U na diferencia entre am bas es que cuando se
ejecuta un m todo de P rin tS tre a m , el b uffer de salida es vaciado autom tica
m ente (los datos se m uestran), no sucediendo lo m ism o con P r in t W r ite r; en este
caso habra que forzar el vaciado del b uffer de salida invocando a su mtodo
flush. P or ejem plo:

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

Trabajar con tipos de datos primitivos


H agam os un breve recorrido por la jerarq u a de clases vista desde un esquema
grfico para ver dnde se sitan las que hem os com entado;
C A P T U L O 5: CL A SES DE USO COM N 103

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.

Clases que encapsulan los tipos prim itivos

El paquete ja v a .Ia n g proporciona las clases Byte, C h a ra c te r, Sh o rt. Integer,


L o n g , Flo at, D o u b le y Boolean, que encapsulan cada uno de los tipos prim itivos,
proporcionando as una funcionalidad aadida para m anipularlos. Analicem os,
por ejem plo, la clase Integer.

Un objeto de la clase In te g e r contiene un atributo de tipo int, que es el obje


tivo de la clase. A dem s, proporciona otros atributos y varios m todos tiles para
tratar con un entero; por ejem plo, para convertir un int en un S t r in g o un S t r in g
en un int. A lgunos de ellos son los siguientes:
1 0 4 JA V A: C U R SO DE PROGRAM A CIN

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.

El resto de las clases tienen m todos anlogos. N o obstante, es necesario re


saltar que las clases Flo at y D o u b le no tienen un m todo parse... En cam bio, in
cluyen otros atributos que pueden observarse en la tabla siguiente. Por ejemplo,
para la clase F lo at (dem para la clase D ou b le ):

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:

1. D efinir un flujo de entrada de la clase Bu ffe re d R e ad e r.


2. L eer la cadena de caracteres.

3. C onvertir el objeto S t r in g en un entero.

El siguiente cdigo corresponde a los puntos enunciados:

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

En el ejem plo anterior se observa que al no disponer ia clase F lo a t de un


m todo anlogo a p a rse ln t, se ha tenido que recurrir a crear un objeto F lo a t a
partir de la cadena de caracteres, para despus obtener el v alo r float que encap-
sula dicho objeto.

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

Partiendo de la cadena devuelta por el m todo anterior, podem os escribir


tam bin, por ejem plo, un m todo d a to ln t que la convierta en un nm ero entero y
devuelva este valor com o resultado:

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

Si el valor devuelto p o r el m todo dato no fuera vlido para convertirlo en un


nm ero entero, el m todo p a rse ln t lanzara una excepcin de tipo Num berFor-
m a tE x c e p tio n que podram os m anejar. Para no com plicar el tem a que estamos
exponiendo, y puesto que dedicarem os un captulo posterior a explicar las excep
ciones, si se lanza una excepcin del tipo descrito, el m todo sim plem ente devol
ver un valor significativo (una constante m iem bro de la clase). Segn esto
podram os m odificar el m todo anterior as:

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

O bserve que el argum ento del m todo p a rse ln t es la cadena de caracteres de


vuelta p o r el m todo dato. Si ocurre un error, por ejem plo, porque se introduce
una cadena que no es convertible a un nm ero entero, el sistem a lanzar una ex
cepcin de tipo N u m b e rF o rm a tE x c e p tio n que ser atrapada por el bloque catcli
lo que dar lugar a que el m todo d a to ln t devuelva el valor M IN _V A L U E , defini
do com o una constante de la clase.

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 . * :

public class Leer


1
public static String da t o ( )
I
String 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 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 );
// 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 t ):
I
catch(IOException 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 )):
I
return sdato: // d e v o l v e r el dato te cl ea d o

public static short datoShortO


I
try
I
return S h o r t .pars eS h o rt( da to ( )):
I
c a t c h t N u m b e r F o r m a t E x c e p t i o n e)
I
return S h o r t . MI N _ V A L U E ; // v a l o r rns p e q u e o

public static int datontO


I
try
I
return I n t e g e r . p a r s e l n t ( d a t o ( )):
I
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 I n t e g e r . M I N _ V A L U E ; // v a l o r ms p e q u e o
108 JA V A: C U R SO DE PROGRAM A CIN

public static long datoLon gO


I
try
I
return Long.pars eLongtd ato()):
I
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 Long.MIN_VALUE; // v a l o r ms pe q u e o

public static float datoFloatO


I
try
I
F l o a t f = new F l o a t ( d a t o ( ) ) ;
r e t u r n f . f l o a t V a l u e ( ):
')
c a t c h i N u m b e r F o r m a t E x c e p t i o n e)
I
return Float.NaN; // No e s un Nmer o; valor float.

public static double da t o Do u bl e O


{
try
I
D o u b l e d = new D o u b l e ( d a t o ( ) ) :
r e t u r n d . d o u b l e V a l u e t ):
1
c a t c h i N u m b e r F o r m a t E x c e p t i o n e)
I
return Double.NaN; // No e s un N me r o ; valor double.
I
I
I

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:

nom breC lase.nom breM todo

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

public class LeerDatos


I
public static void m a in (S trin g [] args)
I
s h o r t d a t o _ s h o r t = 0;
i n t d a t o _ i n t - 0:
l o n g d a t o _ l o n g - 0:
f l o a t d a t o _ f l o a t = 0:
d o u b l e d a t o _ d o u b l e = 0:

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.

DNDE SE UBICAN LAS CLASES QUE DAN SOPORTE?


Para que Jav a pueda utilizar una clase debe conocer dnde est alm acenada en el
sistem a de ficheros. De otra form a, cuando se com pile el program a se obtendr un
erro r indicando que esa clase no existe. Java utiliza dos elem entos para localizar
las clases: el nom bre del paquete y las rutas especificadas por la variable CLASS-
PATH.
1 10 JA V A: CU R SO D E PRO G R A M A CI N

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.

Si recuerda, en el captulo 1, al explicar cm o se com pilaba y ejecutaba un


program a, se dijo que haba que establecer la variable de entorno PATH. Pues
bien, para establecer la variable C LA SSP A TH proceda de form a anloga. Por
ejem plo, si alm acenam os las clases que vayan a ser com partidas por otros pro
gram as, com o es el caso de la clase Leer, en la carpeta jd k l.3 \m isC la se s, asigne a
la variable C LA SSP A TH esta ruta:

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.

CARCTER FIN DE FICHERO

Desde el punto de vista de un usuario de una aplicacin, un dispositivo de entrada


o de salida estndar es tratado por el lenguaje Java com o si de un fichero de datos
en el disco se tratara. Un fichero de datos no es m s que una coleccin de infor
m acin. Los datos que introducim os por el teclado son una coleccin de inform a
cin y los datos que visualizam os en el m onitor son tam bin una coleccin de
inform acin.
F in a l del
.. iNambie ' fichero
.. Ihlambm__
..iMomliie___
IN m L t e _____
Nombre
Acidos
Principio del
------- ' Direccin
fichero

T odo fichero tiene un principio y un final. C m o sabe un program a que est


leyendo datos de un fichero, que se ha llegado al final del m ism o y por lo tanto no
hay m s datos? P or una m arca de fin de fichero. En el caso de un fichero grabado
en un disco esa m arca estar escrita al final del m ism o. En el caso del teclado la
inform acin procede de lo que nosotros tecleam os, por lo tanto si nuestro progra
ma requiere detectar la m arca de fin de fichero, tendrem os que teclearla cuando
dem os por finalizada la introduccin de inform acin. Esto se hace pulsando las
teclas C trl+ D en UNIX o C trl+ Z en una aplicacin de consola en W indows.
CA PTU LO 5: CL A SES D E U SO COM N 111

Y a que un fichero o un dispositivo siem pre es m anejado a travs de un flujo,


hablar del final del flujo es sinnim o de hablar del fichero. P or eso, de ahora en
adelante nos referirem os al flujo en lugar de al fichero o dispositivo vinculado.

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 . * ;

public class Test


I
public static void m ain (S tring [] args)
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 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 l u j o S = System.out:

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:

1. Introduciendo un dato vlido:

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

2. Pulsando las teclas C rl+ Z (m arca de final del flujo):

P r e c i o : ( s e p u l s a n las teclas Ctrl+)


NaN
Continua la a p l i c a c i n

U na aclaracin. L a aplicacin anterior utiliza el operador tem ario (?:) para


verificar si se lleg al final del flujo, lo que suceder cuando se pulsen las teclas
Ctrl+Z. La expresin booleana sdato != nuil ser true si se introdujo un dato v
lido, en cuyo caso se asignar a precio el resultado de la expresin (new
F!oat(sdato)).floatValue()\ y ser false si se pulsaron las teclas C trl+ Z, en cuyo
caso se asignar a precio el valor NaN.

La expresin (new Float(sdato)).floatV alue() es equivalente a:

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 :

En captulos posteriores utilizarem os C trl+ Z com o condicin para finalizar la


entrada de un nm ero de datos, en principio indeterm inado.

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

C uando se ejecute el m todo read de la aplicacin anterior, si tecleam os la


opcin b y pulsam os la tecla Entrar.

b [ E n tr a r ]
CA PTU LO 5: CLASES DE USO C O M N 1 13

antes de la lectura, el buffer de entrada contendr la siguiente inform acin:

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

flu jo S .p rin t "P re c io : "):


s d a t o = 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 l n " C o n t i n u a la aplicacin"): 1
I
catch (IOException ignorada)! 1

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:

Opcin (a, b o c): b


Precio: Continua la a p l i c a c i n

A la vista del resultado, se observa que cuando se ejecut re a d L in e no se


detuvo la ejecucin de la aplicacin para introducir el dato solicitado P or qu?
Porque los caracteres sobrantes \r y Vi son vlidos para el m todo re a d L in e . R e
cuerde q ue este m todo perm ite leer una cadena de caracteres hasta encontrar V
(CR), 'Vi' (L F ) o W i ' (C R LF); estos caracteres son ledos pero no alm acenados.
P o r este m otivo es p o r lo que este m todo no necesita esperar a que introduzca
mos un carcter para la variable sdato. R ecuerde tam bin, que cuando explicam os
anteriorm ente las clases B u ffe r e d ln p u tS tre a m y B u ffe re d R e a d e r dijim os que
un buffer perm ita, entre otras cosas, introducir los datos por anticipado. En este
caso, nuestra intencin no era sa. pero la form a en la que hem os introducido un
dato nos han conducido a ello.

La solucin al problem a planteado es lim piar los caracteres indeseables del


buffer de entrada. Hay dos form as sencillas de hacer esto. U na es utilizar el propio
m todo r e a d L in e para hacer una lectura en falso , con la nica intencin de ex
traer todos los caracteres que haya, y otra es utilizar los m todos sk ip y available.
1 1 4 JA V A: C U R SO D E PRO G R A M A CI N

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

flu jo S.p rin t("P re cio : "):


s d a t o = f 1u j o E . r e a d L i n e ( ):
f l u j o S . p r i n t l n ( " C o n t i n u a l a a p i i c a c i n " ):
I
catch (IOException ignorada)! I

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 clase M a t h contiene m todos para ejecutar operaciones num ricas ele


m entales tales com o raz cuadrada, exponencial, logaritm o, y funciones trigono
m tricas. Por ejem plo:

double raz_cuadrada. n = 345.0;


r a i z _ c u a d r a d a = M a t h . s q r t ( n ):
S y s t e m . o u t . p r i n t l n ( " L a r a i z cua dr a da de " + n + es " + r a i z _ c u a d r a d 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

double P I V alor del nm ero n.


tip o a b s (tipo a) V alor absoluto de a. El tipo , igual en todos los
casos, puede ser: double, float, int o long.
double eeil(double a) V alor d o u b le sin decim ales m s pequeo que
es m ayor o igual que a.
double flo o rd o u b le a) V alor d o u b le sin decim ales m s grande que es
m enor o igual que a.
tipo m a \(tip o a , tipo b) V alor m ayor de a y b. El tipo, igual en todos
los casos, puede ser: double. float, in t o long.
tipo m in (/p o a , tipo b) V alor m enor de a y b. El tipo, igual en todos
los casos, puede ser: double. float. in t o long.
double r a n d o m O V alor aleatorio m ayor o igual que 0.0 y m enor
que LO.
double rin t(d o u b le a) V alor d o u b le sin decim ales m s cercano a a
(redondeo de a).
long ro u n d d o u b le a) V alor lo n g m s cercano a a.
int ro u n d (flo a t a ) V alor in t m s cercano a a.
double sq rt(d o u b le a) R az cuadrada de a (a no puede ser negativo).
double exp(double a) V alor de e.
double log(double ) L ogaritm o neperiano (natural) de a.
double pow (double a, double b) V alor de a'}.
double IE E E re m a in d e r(
d o u b le/ / , double f2 )
Resto de una divisin entre nm eros reales:
c = fl/f2 , siendo c el valor entero m s cercano
al valor real de fJ/J2; por lo tanto, el resto pue
de ser positivo o negativo.
double aeosfdouble a) A rco, de 0 .0 a n , cuyo coseno es a.
double asin (d o u b le a) A rco, de -n/2 a n /2 , cuyo seno es a.
double a tan (d o u b le a) A rco, de -n/2 a Tt/1, cuya tangente es a.
double atan 2 (d o u b le a, double b) C onvierte las coordenadas rectangulares (b , a)
a polares: (r, 0).
double sin(double a) Seno de a radianes.
double cos(double a) C oseno de a radianes.
double tan (d o u b le a) T angente de a radianes.
double to D eg reesfdouble rads) C onvertir un ngulo en radianes a grados.
double to R ad ian sfd o u b le grados) C onvertir un ngulo en grados a radianes.
1 1 6 JA V A: C U R SO D E PROGRAM A CIN

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.

La frm ula utilizada para el clculo de los intereses es:

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.

La solucin de este problem a puede ser de la siguiente form a:

Prim ero definim os las variables que vam os a u tilizar en los clculos.

double c, intereses, capital:


f l o a t r;
i n t t;

A continuacin leem os los datos c, r y 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 X a n u a l d e l : " ) :
r = L e e r . d a t o F l o a t t );
System.o ut.p r i n t ( "\nDurante cuntos d as : ):
t = L e e r . d a t o l n t ):

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:

Finalm ente, escribim os el resultado.

System .out.printlnt"Intereses producidos... " + intereses);


S y s t e m . o u t . p r i n t l n ( " C a p i t a l acumulado " + capital):
CA PTU LO 5: CLASES D E USO C O M N 1 17

O bserve que el desarrollo de una aplicacin, en general, consta de tres blo


ques colocados en el siguiente orden:

ENTRADA PROCESO S A L ID A |

La aplicacin com pleta se m uestra a continuacin. O bservar q ue se ha utiliza


do para la entrada de datos los m todos de la clase L eer im plem entada anterior
m ente en este m ism o captulo.

// 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 :

System.out.println"Intereses producidos... " + intereses):


S y s tem .o ut.p r i n t n ( " C a p i t a l acumulado " + capital);
I

2. R ealizar u na aplicacin que d com o resultado las soluciones reales x , y x 2 de una


ecuacin de segundo grado, de la forma:

ax2 + bx + c = O

Las soluciones de una ecuacin de segundo grado vienen dadas p o r la frmula:

- b y l b : 4 a c
1 18 JAVA: C U R SO DE PROGRAM A CIN

Las soluciones son reales slo si b 2-4 a c es m ayor o igual que 0. C on lo


aprendido hasta ahora, la solucin de este problem a puede desarrollarse de la
form a siguiente:

Prim ero definim os las variables necesarias para los clculos:

d o u b l e a. b, c. d. xl, x2:

A continuacin leem os los coeficientes a , b y c de la ecuacin:

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:"):

Si hay races reales las calculam os aplicando la frm ula.

d = Math.sqrt(d):
x l = ( - b + d) / ( 2 * a ) :
x2 = ( - b - d) / ( 2 * a ) :

El m todo s q r t calcula la raz cuadrada de su argum ento. En el ejem plo, se


calcula la raz cuadrada de d y se alm acena el resultado de nuevo en d.

Por ltim o escribim os los resultados obtenidos.

System.out.println"xl = " + xl + ", x2 = " + x 2 ) ;

La aplicacin com pleta se m uestra a continuacin:


CA PTU LO 5: CLASES DE USO COM N 1 19

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

3. Realizar una aplicacin que evale el polinom io


p = 3x5 - 5 x 3 + 2.x - 7
y visualizar el resultado con el siguiente form ato:
Para x = valor, 3 x A 5 - 5 x A3 + 2 x - 7 = resultado
1 2 0 JA V A: C U R SO DE PROGRAM A CIN

4. R ealizar la m ism a aplicacin anterior, pero em pleando ahora coeficientes varia


bles a, b y c.
5. Ejecute la siguiente aplicacin, explique io que ocurre y realice las m odificacio
nes que sean necesarias para su correcto funcionam iento.
i mport j a v a . i o . * :

public class Test


I
public static void m ain(S tring [] args)
I
1n 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 ) :
PrintStream f l u j o S = System.out;
c h a r c a r = 0;
try
I
flu joS.print("Carcter: "):
c a r = ( c h a r ) f l u j o E . r e a d );
flujoS.println(car);
flu joS.print("Carcter: "):
c a r = ( c h a r ) f 1 u j o E . r e a d ( ):
flujoS.println(car);
I
catch(IOException ignorada) (I
)

6. Indique qu resultado da la siguiente aplicacin. A continuacin ejecute la aplica


cin y com pare los resultados.
i mport j a v a . i o . * :

public class Test


I
public static void m a in(S tring [] args)
I
PrintStream f l u j o S = System.out:

char c a r i = A , c a r 2 - 65, c a r 3 = 0:

car3 = ( c h a r X c a r l + a - ' A ')


flujoS.println(car3 + " " + ( i n t ) c a r 3);
car3 = ( c h a r )(c a r 2 + 32):
flujoS.p r i n t l n ( c a r 3 + " + ( i n t ) c a r 3 );
CA PTU LO 6
FJ. Ccb/tUos/RA-MA

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.

A s m ism o, en m s de una ocasin necesitarem os ejecutar un conjunto de


sentencias un nm ero determ inado de veces, o bien hasta que se cum pla una con
dicin im puesta por nosotros. Por ejem plo, en el captulo anterior hem os visto
cm o leer un carcter de la entrada estndar. Pero si lo que querem os es leer, no
un carcter sino todos los que escribam os por el teclado hasta detectar la m arca de
fin de fichero, tendrem os que utilizar una sentencia repetitiva.

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

donde condicin es una expresin booleana, y sentencia I y sentencia 2 repre


sentan a una sentencia sim ple o com puesta. C ada sentencia sim ple debe finalizar
con un punto y com a.

U na sentencia if se ejecuta de la form a siguiente:

1. Se evala la condicin.

2. Si el resultado de la evaluacin de la condicin es verdadero (true) se ejecuta


r lo indicado por la sentencia 1.

3. Si el resultado de la evaluacin de la condicin es falso (false), se ejecutar lo


indicado por la sentencia 2, si la clusula else se ha especificado.

4. Si el resultado de la evaluacin de la condicin es falso, y la clusula else se


ha om itido, la sentencia I se ignora.

5. E n cualquier caso, la ejecucin contina en la siguiente sentencia ejecutable


que haya a continuacin de la sentencia if..

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:

En este ejem plo, la condicin viene im puesta por la expresin x != 0. Enton


ces b = a / x , que sustituye a la sentencia 1 del form ato general, se ejecutar si la
expresin es verdadera (x distinta de 0) y no se ejecutar si la expresin es falsa
(x igual a 0). En cualquier caso, se contina la ejecucin en la lnea siguiente, b =
b + 1. V eam os otro ejem plo:

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

En el ejem plo siguiente, la condicin viene im puesta p o r la expresin a != 0


&& b != 0. Si al evaluar la condicin se cum ple que a y b son distintas de cero,
entonces se ejecuta la sentencia x = i. En otro caso, la sentencia x = i se ignora,
continuando la ejecucin en la lnea siguiente.

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

Un error tpico es escribir, en lugar de la condicin del ejem plo anterior, la si


guiente:

if (a - b * 5)
// ...

En este caso, suponiendo p o r ejem plo que a es de tipo in t, el com pilador


m ostrar un m ensaje de error indicando que no puede convertir un in t a boolean,
porque la sentencia anterior es equivalente a escribir:

a - b * 5:
i f (a)
// ...

donde se observa que a no puede dar un resultado b o o lean . S sera correcto lo si


guiente:

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

En este otro ejem plo que se m uestra a continuacin, la sentencia r e tu r n se


ejecutar solam ente cuando c a r sea igual al carcter V .

if (car == 's ')


return:

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:

Al evaluarse las condiciones anteriores, pueden presentarse los casos que se


indican en la tabla siguiente:

condicin I condicin 2 se ejecuta: sentencia I sentencia 2


F F no s
F V no s
V F no no
V V s no

(V = verdadero, F = falso, no = no se ejecuta, s = s se ejecuta)

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;

A hora podram os dudar de a qu if pertenece la clusula else. C uando en el


cdigo de un program a aparecen sentencias i f ... else anidadas, la regla para dife
renciar cada una de estas sentencias es que cada else se corresponde con el if
ms prxim o que no haya sido em parejado". Segn esto la clusula else est em-
C A P T U L O 6: SEN TEN CIA S DE CO N TRO L 125

parejada con el segundo if. Entonces, al evaluarse ahora las condiciones I y 2,


pueden presentarse los casos que se indican en la tabla siguiente:

condicin I condicin 2 se ejecuta: sentencia 1 sentencia 2


F F no no
F V no no
V F no s
V V s no

(V = verdadero, F = falso, no = no se ejecuta, s = s se ejecuta)

C om o ejem plo se puede observar el siguiente segm ento de program a que es


cribe un m ensaje indicando cm o es un nm ero a con respecto a otro b (m ayor,
m enor o igual):

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.

A s m ism o, si en el ejem plo siguiente ocurre que a no es igual a 0, la ejecu


cin 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

Si en lugar de la solucin anterior, lo que deseam os es que se ejecute s = s +


a cuando a no es igual a 0, entonces tendrem os que incluir entre llaves el segundo
if sin la clusula else; esto es:

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

C om o ejercicio sobre la teora expuesta, vam os a realizar una aplicacin que


d com o resultado el m enor de tres nm eros a, b y c. La form a de proceder es
com parar cada nm ero con los otros dos una sola vez. L a sim ple lectura del cdi
go que se m uestra a continuacin es suficiente para entender el proceso seguido.

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

public static void m a in ( S t r in g [ ] args)


I
float a. b. c. me n o r ;

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

La evaluacin de esta estructura sucede as: si se cum ple la condicin 1, se


ejecuta la sentencia 1 y si no se cum ple se exam inan secuencialm ente las condi
ciones siguientes hasta el ltim o else, ejecutndose la sentencia correspondiente al
prim er else if, cuya condicin sea cierta. Si todas las condiciones son falsas, se
ejecuta la sentencia n correspondiente al ltim o else. En cualquier caso, se conti
na en la prim era sentencia ejecutable que haya a continuacin de la estructura.
Las sentencias 1, 2 ,.... n pueden ser sentencias sim ples o com puestas.

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

La solucin de este problem a puede ser de la form a siguiente:

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 continuacin leem os los datos ar, cc y pu.

System .out.print("Cdigo a r t i c u l o ........... ">


128 JA V A: C U R SO DE PROGRAM A CIN

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 ):

C onocidos los datos, realizam os los clculos y escribim os el resultado.

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 :

System .out.print("Cdigo a r t ic u l o ")


a r = L e e r . d a t o l n t ):
S y s t e m . o u t .p r in t ( " C a n t id a d comprada ")
c c = 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 ( " 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 ):
S y s t e m . o u t . p r i n t l n ( );

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

donde expresin es una expresin entera de tipo c h a r, b y te, s h o rt o in t y expre


sin-constante es una constante tam bin entera y de los m ism os tipos. T anto la
expresin com o las expresiones constantes son convertidas im plcitam ente a int.
Por ltim o, sentencia es una sentencia sim ple o com puesta. En el caso de tratarse
de una sentencia com puesta, no hace falta incluir las sentencias sim ples entre {}.

L a sentencia sw itch evala la expresin entre parntesis y com para su valor


con las constantes de cada case. La ejecucin de las sentencias del bloque de la
sentencia sw itch , com ienza en el case cuya constante coincida con el valor de la
expresin y contina hasta el final del bloque o hasta una sentencia que transfiera
el control fuera del bloque de sw itch ; por ejem plo, b re a k . La sentencia sw itch
puede incluir cualquier nm ero de clusulas case.

Si no existe una constante igual al valor de la expresin, entonces se ejecutan


las sentencias que estn a continuacin de d e fa u lt, si esta clusula ha sido especi
ficada. La clusula d e fa u lt puede colocarse en cualquier parte del bloque y no ne
cesariam ente al final.
1 3 0 JA V A: C U R SO DE PRO G R A M A CI N

En una sentencia sw itch es posible hacer declaraciones en el bloque de cada


case, igual que en cualquier otro bloque, pero no al principio del bloque switch,
antes del prim er case. Por ejem plo:

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

El erro r que se ha presentado en el ejem plo anterior puede solucionarse as:

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

H ay que tener en cuenta que febrero puede tener 28 das, o bien 29 si el ao


es bisiesto. Un ao es bisiesto cuando es m ltiplo de 4 y no de 100 o cuando es
m ltiplo de 400. Por ejem plo, el ao 2000 p o r las dos prim eras condiciones no se
ra bisiesto, pero s lo es porque es m ltiplo de 400; el ao 2100 no es bisiesto
porque aunque sea m ltiplo de 4, tam bin lo es de 100 y no es m ltiplo de 400.

La solucin de este problem a puede ser de la siguiente forma:

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

A continuacin leem os los datos m es y ao.

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

D espus com param os el m es con las constantes 1, 2, ..., 12. Si m es es 1, 3, 5,


7, 8, 10 12 asignam os a d a s el valor 31. Si m es es 4, 6, 9 u 11 asignam os a
das el valor 30. Si m es es 2, verificarem os si el ao es bisiesto, en cuyo caso
asignam os a das el valor 29 y si no es bisiesto, asignam os a d a s el valor 28.
Si m es no es ningn valor de los anteriores enviarem os un m ensaje al usuario
indicndole que el m es no es vlido. T odo este proceso lo realizarem os con
una sentencia switch.

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.

Por ltim o si el m es es vlido, escribim os el resultado solicitado.

if ( mes > - 1 && mes < = 1 2 )


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 " + ao +
" t i e n e " + d i a s + d i a s ):

El program a com pleto se m uestra a continuacin:


13 2 JAVA: C U R SO DE PROGRAM A CIN

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

public static void m a in(S tring [] args)


I
int das = 0 . mes - 0. a o = 0:

S y s t e m . o u t . p r i n t ( " Me s ( # ) : " ) : mes - L e e r . d a t o l n t t ):


System.out.print("Ao ( IHHHt): ) : a o = L e e r . d a t o l n t ( );

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.

La sentencia b re a k que se ha puesto a continuacin de la clusula d efault no


es necesaria; sim plem ente obedece a un buen estilo de program acin. A s, cuando
tengam os que aadir otro caso ya tenem os puesto bre ak. con lo que hem os elim i
nado una posible fuente de errores.

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:

donde condicin es cualquier expresin booleana y sentencia es una sentencia


sim ple o com puesta.

La ejecucin de la sentencia w hile sucede as:


1. Se evala la condicin.
2. Si el resultado de la evaluacin es false (falso), la sentencia no se ejecuta y se
pasa el control a la siguiente sentencia en el program a.
3. Si el resultado de la evaluacin es true (verdadero), se ejecuta la sentencia y
el proceso descrito se repite desde el punto 1.

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 - '\0:


try
I
S y s t e m . o u t . p r i n t ( " \ n O e s e a c o n t i n u a r s / n ( s i o n o ) ):
c a r ( c h a r ) S y s t e m . i n . r e a d ( );
// 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 v a i l a b l e O ) :
w h i l e ( c a r ! = s && c a r ! = n ' )
I
S y s t e m . o u t . p r in t ( "\nDesea c o n tin u a r s/n (si o no) ");
c a r - ( c h a r ) S y s t e m . i n . r e a d ( ):
S y s t e m . i n . s k i p ( S y s t e m . i n . a v a i 1a b l e ( ) ) ;

catch UOException ignorada) 11


13 4 JA V A : C U R SO D E PROGRAM A CIN

Observe que antes de ejecutarse la sentencia w hile se visualiza el mensaje


D esea continuar s/n (s o no) y se inicia la condicin; esto es, se asigna un ca
rcter a la variable c o r que interviene en la condicin de la sentencia while.

L a sentencia w hile se interpreta de la form a siguiente: m ientras el valor de


ca r no sea igual ni al carcter V ni al carcter V , visualizar el m ensaje Desea
continuar s/n (s o no) y leer otro carcter. Esto obliga al usuario a escribir el ca
rcter s ' o 'n en m insculas.

El ejem plo expuesto, puede escribirse de form a m s sim plificada as:

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 . *:

public class CAscii


I
// C d i g o A S C I I de c a da uno de l o s c a r a c t e r e s de un t e x t o
public s t a t i c void m a in ( S t r i n g [ ] args)
I
c h a r c a r = 0: // c a r = c a r c t e r n u l o (\0)

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

A continuacin ejecutam os la aplicacin. Introducim os, p o r ejem plo, el ca


rcter a ' y observam os los siguientes resultados:

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 :

Este resultado dem uestra que cuando escribim os a y pulsam os la tecla E n


tra r para validar la entrada, slo se visualiza el cdigo A SC II de ese carcter; los
caracteres V y Vi introducidos al pulsar E ntrar son ignorados porque as se ha
program ado. C uando se han ledo todos los caracteres del flujo de entrada, se so
licitan nuevos datos. Lgicam ente, habr com prendido que aunque se lea carcter
a carcter se puede escribir, hasta pulsar E ntrar, un texto cualquiera. P or ejem plo:

Introduzca una c a d e n a de t e x t o : hola[Entrar]


El cdigo ASCII de h e s 104
El cdigo ASCII de o e s 111
El cdigo ASCII de 1 e s 108
El cdigo ASCII de a e s 97
Introduzca una cadena de 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 . * ;

public class CAsci i


I
// C d i g o A S C I I de c a d a uno de l o s c a r a c t e r e s de un t e x t o
public s t a t i c void m a in(String[] args)
I
final char eof = ( c h a r ) - l;
c h a r c a r = 0 ; // c a r = c a r c t e r nulo (\0)
try
I
S y s t e m . o u t . p r i n t l n ( " I n t r o d u z c a una c a d e n a d e t e x t o . " ) :
Syste m .o u t .p rin tln ! "P a ra terminar pulse 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 ( )) ! - e of)
I
if ( 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 ) c a r ) ;

catch(IOException ignorada) II

U na solucin posible de esta aplicacin es la siguiente:

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

public s t a t ic void m ain (S trin g[] args)


I
int i = 1. j = 1:
while ( i < - 3 ) // m i e n t r a s i sea menor o i g u a l que 3
I
System .out.print("Para i = + i +
w h i l e ( j <= 4 ) // m i e n t r a s j sea menor o i g u a l que 4
I
S y s t e m . o u t . p r i n t C j - * + j + ",
j + + ; // aumentar j en una u n id ad
I
S y s t e m . o u t . p r i n t l n ( ); // a v a n z a r a una nueva l i n e a
i + + : // aumentar i en una u n id ad
j = 1; // i n i c i a r j de n u ev o a 1

Al ejecu tar este m todo se obtiene el siguiente resultado:

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.

C om o aplicacin de lo expuesto, vam os a realizar un program a que im prim a


los nm eros z, com prendidos entre 1 y 50, que cum plan la expresin:

r = x2 + y 2

donde z, x e y son nm eros enteros positivos. El resultado se presentar de la for


ma siguiente:

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

L a solucin de este problem a puede ser de la siguiente form a:

Prim ero definim os las variables que vam os a utilizar en los clculos.

1 n t x - l . y - l . z - 0 :

A continuacin escribim os la cabecera de la solucin.

System.out.p r i n t l n ( " Z \ t " + " X \ t " + "Y");


S y s t e m , o u t . p r i n t l n ( " _________________________ " ) ;

D espus, para x = 1, e y = 1 , 2 ,3 , .... para x = 2, e y = 2, 3, 4, .... para x = 3,


e y = 3 ,4 , .... hasta x = 50, calculam os la y j x 2 + y 2 ; llam am os a este valor z
(observe que y es igual o m ayor que x para evitar que se repitan pares de valo
res com o x= 3, y= 4 y x= 4, y= 3). Si z es exacto, escribim os z, x e y . Esto es.
para los valores descritos de x e y, hacem os los clculos:

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 ) :

A dem s, siem pre que obtengam os un valor z m ayor que 50 lo desecharem os y


continuarem os con un nuevo v alor de a y los correspondientes valores de y.

El program a com pleto se m uestra a continuacin:

public class CPitagoras


I
// Teo r ema d e P i t g o r a s
public s t a t i c void m a in ( S tr in g [] args)
1
i n t x = l . y = l , z = 0:
System .out.println(Z\t" + " X\t + "Y");
S y s t e m , o u t . p r i n t l n( __________________________ " ) ;

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 :
)

SENTENCIA do ... while


La sentencia d o ... w hile ejecuta una sentencia, sim ple o com puesta, una o ms
veces dependiendo del valor de una expresin. Su sintaxis es la siguiente:

do
s e n te n c ia -,
wh i l e ( c o n d i c i n );

donde condicin es cualquier expresin booleana y sentencia es una sentencia


sim ple o com puesta. O bserve que la estructura d o ... w hile finaliza con un punto y
com a.

La ejecucin de una sentencia d o ... w h ile sucede de la siguiente form a:


1. Se ejecuta el bloque (sentencia sim ple o com puesta) de do.

2. Se evala la expresin correspondiente a la condicin de finalizacin del bu


cle.

3. Si el resultado de la evaluacin es false (falso), se pasa el control a la si


guiente sentencia en el program a.
4. Si el resultado de la evaluacin es tr u e (verdadero), el proceso descrito se re
pite desde el punto 1.

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

C uando se utiliza una estructura d o ... w hile el bloque de sentencias se ejecuta


al m enos una vez, porque la condicin se evala al final. En cam bio, cuando se
140 JAVA: C U R SO D E PROGRAM A CIN

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.

C om o ejercicio, vam os a realizar un program a que calcule la raz cuadrada de


un nm ero n por el m todo de N ew ton. Este m todo se enuncia as: sea r, la raz
cuadrada aproxim ada de n. La siguiente raz aproxim ada r(+; se calcula en funcin
de la anterior as:

rM =

El proceso descrito se repite hasta que la diferencia en v alo r absoluto de las


dos ltim as aproxim aciones calculadas, sea tan pequea com o nosotros queramos
(teniendo en cuenta los lm ites establecidos por tipo de datos utilizado). Segn
esto, la ltim a aproxim acin ser una raz vlida, cuando se cum pla que:

abs(r ru , ) <

La solucin de este problem a puede ser de la siguiente forma:

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

A continuacin leem os los datos n , aprox y epsilon.

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

D espus, se aplica la frm ula de Newton.

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.

C uando la condicin especificada en la estructura d o ... w hile m ostrada ante


riorm ente sea falsa, el proceso habr term inado. S lo queda im prim ir el re
sultado.

System.out.println("La raz c u a d r a d a de + n + e s " + aprox);

El program a com pleto se m uestra a continuacin. Para no perm itir la entrada


de nm ero negativos, se ha utilizado una estructura d o ... w hile que preguntar
por el valor solicitado m ientras el introducido sea negativo.

// 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 PATH


p u b l i c c l a s s CRaizCuadrada
I
// R a z cuadrada. M t o d o de Newt on.

public static void m a in ( S t r in g [] args)


I
double n: // nmer o
double aprox: // apro xi maci n a la r a z cuadrada
double antaprox: // a n t e r i o r aproximacina la raz cuadrada
double epsilon: II c o e f i c i e n t e de e r r o r

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):

Si ejecuta este program a para un valor de n igual a 10, obtendr la siguiente


solucin:

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.

La ejecucin de la sentencia fo r sucede de la siguiente forma:


1. Se inician las variables v i, v2, ...

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

P o r ejem plo, la siguiente sentencia fo r im prim e los nm eros del 1 al 00. Li


teralm ente dice: desde i igual a / , m ientras i sea m enor o igual que 100, incre
m entado la i de uno en uno, escribir el v alor d e i.

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 + ') :

En el siguiente ejem plo se puede observar la utilizacin de la com a com o se


parador de las variables de control y de las expresiones que hacen que evolucio
nen los valores q ue intervienen en la condicin de finalizacin.

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 + " ):

El ejem plo siguiente indica cm o realizar un bucle infinito. Para salir de un


bucle infinito tiene que pulsar las teclas Ctrl+C.

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

C om o aplicacin de la sentencia fo r vam os a im prim ir un tablero de ajedrez


en el que las casillas blancas se sim bolizarn con una B y las negras con una N.
A s m ism o, el program a deber m arcar con * las casillas a las que se puede m over
un alfil desde una posicin dada. La solucin ser sim ilar a la siguiente:

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

D esarrollo del program a:

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

L eer la fila y la colum na en la que se coloca el alfil.

System.out.print fila "); f a l f i l = L e e r . d a t o l n t t ):


System.out.p r i n t ( " c o l u mn a "); c a l f i l = L e e r . d a t o l n t t );

Partiendo de la fila 1, colum na 1 y recorriendo el tablero p o r filas,

for (fila = 1: fila <= 8: fila++)


I
for ( c o l u m n a = 1; c o l u mn a < = 8 : col umna++)
I
// P i n t a r e l t a b l e r o de a j e d r e z
I
S y s t e m . o u t . p r i n t l n ( ): // c a m b i a r d e f i l a
I

im prim ir un *, una B o una N dependiendo de las condiciones especificadas a


continuacin:

0 Im prim ir un * si se cum ple, que la sum a o diferencia de la fila y colum na


actuales, coincide con la sum a o diferencia de la fila y colum na donde se
coloca el alfil.
CA PTU LO 6: SEN TEN CIA S DE C O N TR O L 145

0 Im prim ir una B si se cum ple que la fila m s colum na actuales es par.


0 Im prim ir una N si se cum ple que la fila m s colum na actuales es im par.

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

El program a com pleto se m uestra a continuacin.

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


II
public class CAjedrez
I
// I m p r i m i r un t a b l e r o de a j e d r e z ,
public s t a t i c void m a in ( S t r in g [] args)
I
i n t 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
i n t f i l a , c o l u m n a ; // p o s i c i n a c t u a l del a l f i l

S y s t e m . o u t . p r i n t l n " P o s i c i n del a l f i l : " ) ;


System.out.print(" fila ) ; f a l f i l = 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 o l u mn a " ) ; c a l f i l = 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 l n ) ; // d e j a r una l i n e a en b l a n c o

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

A nteriorm ente vim os que la sentencia b re a k finaliza la ejecucin de una senten


cia sw itch. Pues bien, cuando se utiliza b re a k en el bloque correspondiente a una
sentencia while, do, o for, hace lo m ism o: finaliza la ejecucin del bucle.

C uando las sentencias sw itch, while, do, o fo r estn anidadas, la sentencia


b re a k solam ente finaliza la ejecucin del bucle donde est incluida.

Por ejem plo, el bucle interno de la aplicacin C Pitagoras desarrollada ante


riorm ente, podra escribirse tam bin as:

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.

public class Test


1
public s t a t i c void m a in (S trin g [] args)
i
f o r ( i n t n = 0: n < = 1 0 0 : n + + )
I
II S i n no e s m l t i p l o de 5. s i g u i e n t e iteracin
i f (n X 5 != 0 ) c o n t i nu :
// I mp f i me el s i g u i e n t e m l t i p l o de 5
System.out.printlntn + " ");
CA PTU LO 6: SEN TEN CIA S DE C O N TR O L 147

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

Si ejecu ta u na aplicacin que contenga el cdigo anterior, obtendr el si


guiente resultado:

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

L a solucin visualizada dem uestra que cuando la condicin (x*y+ z)% 11 = = 0


se cum ple, b re a k interrum pe la ejecucin de los tres bucles, continuando la eje
cucin en la sentencia siguiente al bucle m s extem o.
148 JA V A: C U R SO DE PROGRAM A CIN

Si en el cdigo anterior se sustituye b re a k por continu, la solucin sera esta


otra:

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

SENTENCIAS t r y ... catch

En el captulo anterior expusim os que cuando durante la ejecucin de un progra


ma ocurre un error que im pide su continuacin, Java lanza una excepcin que ha
ce que se visualice un m ensaje acerca de lo ocurrido y se detenga la ejecucin.
C uando esto ocurra, si no deseam os que la ejecucin del program a se detenga,
habr que utilizar try para poner en alerta a la aplicacin acerca del cdigo que
puede lanzar una excepcin y utilizar catch para capturar y m anejar cada excep
cin que se lance. Por ejem plo, si ejecuta la aplicacin Test que se m uestra un po
co m s adelante, lanzar la excepcin del tipo A rith m e tic E x c e p tio n que se indica
a continuacin:

E x c e p t io n in th read "m a in " j a v a . 1 a n g .A r i t h m e t i c E x c e p t i o n : / by z e r o


at T e s t . m a in ( T e s t .ja v a :9 )

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.

public e lass Test


I
public static void m a in ( S t r in g [] args)
I
in t datol - 0, dato2 - 0. dato3:

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

M odifiquem os la aplicacin con la intencin de capturar la excepcin lanza


da. El resultado puede ser el siguiente:

public class Test


I
public static void m a in ( S trin g [] args)
I
int datol = 0. dat o2 = 0. dato3 - 0:

System.out.p rin tln ("S e inicia la aplicacin"):


try
I
d a t o l ++:
dato3 = datol / d a t o 2 :
dato2++;
// O t r a s s e n t e n c i a s
I
c a t c h A r i t h m e t i c 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 de t i p o A r i t h m e t i c E x c e p t i o n
S y s t e m . o u t .p r in t ln "E r r o r : " + e .ge tM essage));
dato3 = d a t o l ;
1
System.out.printlndatol + " " + dato2 + " " + dato3);
I
I

A hora, si la sentencia clato3 = d a to l / d a lo ! d a lugar a una divisin p o r cero,


Java detendr tem poralm ente la ejecucin de la aplicacin y lanzar una excep
cin de tipo A rith m e tic E x c e p tio n que ser capturada por la sentencia catch. La
ejecucin de la aplicacin se reanudar a partir de la prim era sentencia pertene
ciente al bloque catch y continuar hasta el final de la aplicacin. Se puede ob
servar que la opcin que se ha tom ado ante la excepcin lanzada ha sido suponer
una divisin entre 1; esto es: dato3 = d a to l. El resultado cuando finalice la apli
cacin ser:

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

teniendo en cuenta los siguientes casos:

1. Si a es igual a 0 y b es igual a 0, im prim irem os un m ensaje diciendo que la


ecuacin es degenerada.

2. Si a es igual a 0 y b no es igual a 0, existe una raz nica con valor - c / b .

3. En los dem s casos, utilizarem os la frm ula siguiente:

- b j b 2 - 4 ac

L a expresin d = b 2 - 4ac se denom ina discrim inante.

Si d es m ayor o igual que 0 entonces hay dos races reales.

Si d es m enor que 0 entonces hay dos races com plejas de la forma:

x + yj, * - yj
Indicar con literales apropiados los datos a introducir, as com o los resultados
obtenidos.

La solucin de este problem a puede ser de la siguiente form a:

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

A continuacin leem os los datos a, b y c.

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 ):

Ledos los coeficientes, pasam os a calcular las races.

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

Im prim ir las races reales.

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) ) :

Im prim ir las races com plejas conjugadas.

System .out.println"Races complejas:"):


Sys te m .o u t .p rin tln r e + + " + Math.abs(im) + " j");
Sys te m .o u t .p rin tln r e + " - " + Math.abs(im) + " j");

El program a com pleto se m uestra a continuacin.

// 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 L AS S PATH


//
public class CEcuacion2Grado
I
// C a l c u l a r l a s r a c e s de una e c u a c i n de 2 g r a d o
public s t a t i c void m a in ( S t r in g [] args)
I
double a. b. c: // c o e f i c i e n t e s d e l a e c u a c i n
double d: // d i s c r i m i n a n t e
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 raz

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

2. E scrib ir un program a para que lea un texto y d com o resultado el nm ero de


palabras con al m enos cuatro vocales diferentes. S uponem os que una palabra est
separada de otra por uno o m s espacios ( ), tabuladores (\t) o caracteres \n . La
entrada de datos finalizar cuando se detecte la m arca de fin de fichero. La ejecu
cin ser de la form a siguiente:

I n t r o d u c i r te x to . Para f i n a l i z a r pulsar Ctrl+z.


En l a U n i v e r s i d a d ha y muc h o s
e s t u d i a n t e s de T e l e c o m u n i c a c i n
[ C t r l ] [ z]

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

La solucin de este problem a puede ser de la siguiente form a:

Prim ero definim os las variables que vam os a utilizar en el program a.

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

A continuacin leem os el texto carcter a carcter.

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

Si la m arca de fin de fichero est justam ente a continuacin de la ltim a pala


bra (no se puls E ntrar despus de la ltim a palabra), entonces se sale del bu
cle w hile sin verificar si esta palabra tena o no cuatro vocales diferentes. Por
eso este proceso hay que repetirlo fuera del while.

if ( ( a + e + i + o + u ) >-4) np++;

Finalm ente, escribim os el resultado.

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 con " +


4 v o c a l e s d i s t i n t a s : " + n p ) ;

El program a com pleto se m uestra a continuacin.

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

3. E scribir un program a para que lea un texto y d com o resultado el nm ero de


caracteres, palabras y lneas del m ism o. Suponem os que una palabra est separad
de otra por uno o m s espacios caracteres lab (\t) o caracteres \ n . L a ejecu
cin ser de la form a siguiente:
CA PTU LO 6: SEN TEN CIA S D E C O N T R O L 155

Intr od u cir texto. Pulse [Entrar] d e s p u s de c a da linea.


Para f i n a l i z a r p u l s a r C t r l + z .

E s t e pr og r ama c u e n t a l o s c a r a c t e r e s , las palabras y


l a s l i n e a s de un d o c u me n t o .
[ C t r l ] [z]
80 13 2

El program a com pleto se m uestra a continuacin. C om o ejercicio analice paso


a paso el cdigo del program a y justifique la solucin presentada com o ejem plo
anteriorm ente.

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

S y s t e m . o u t . p r i n t l n n c a r a c t e r e s + " " + n p a l a b r a s + " " +

n i i n e a s ) ;

I
catchIOException ignorada) II

4. R ealizar un program a que a travs de un m en perm ita realizar las operaciones de


sum ar, restar, m ultiplicar, d ivid ir y salir. Las operaciones constarn solam ente de
dos operandos. El m en ser visualizado p o r un m todo sin argum entos, que de
volver com o resultado la opcin elegida. La ejecucin ser de la form a siguiente:

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

La solucin de este problem a puede ser de la siguiente form a:

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:

A continuacin presentam os el m en en la pantalla para poder elegir la opera


cin a realizar.

o p e r a c i n = m e n ( ):

El m todo m en ser definido com o un m todo s ta tic de la clase aplicacin


para que se pueda invocar sin tener que definir un objeto de esa clase. La de
finicin de este m todo puede ser as:

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

Systern.out.println "\t2. r e s t a r " ) ;


S y s t e m . o u t . p r i n t n ( " \ t 3 . mu t i p l i c a r " ) ;
S y s t e m . o u t . p r i n t l n i \ t 4 . d i v i d i r " ) :
S y s t e m . o u t . p r i n t n ( " \ t 5 . s a l i r " );
S y s t e m . o u t . p r i n t " \ n S e l e c c i o n e la o p e ra c i n deseada: "):
o p = L e e r . d a t o l n t );
I
w h i 1e ( o p < 1 || op > 5 ) :
r e t u r n op:

Si la operacin elegida no ha sido salir, leem os los operandos d a to ! y dato2.

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

A continuacin, realizam os la operacin elegida con los datos ledos e im pri


m im os el resultado.

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

El program a com pleto se m uestra a continuacin.

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:

public static void m a in ( S t r in g [] args)


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

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.

2. R ealizar un program a que perm ita evaluar la serie:


1 6 0 JA V A : C U R SO DE PRO G R A M A CI N

3. Si quiere av eriguar su nm ero de Tarot, sum e los nm eros de su fecha de naci


m iento y a conlinuacin redzcalos a un nico dgito; por ejem plo si su fecha de
nacim iento fuera 17 de O ctubre d e 1970, los clculos a realizar seran:

1 7 + 1 0 + 1970= 1997 = > 1 + 9 + 9 + 7 = 26 = > 2 + 6 = 8

lo que quiere decir que su nm ero de T arot es el 8.

R ealizar un program a que pida una fecha, de la forma:

da d e l m es de axo

donde da, m es y ao son enteros, y d com o resultado el nm ero de Tarot. El


program a verificar si la fecha es correcta, esto es, los valores estn dentro de los
rangos perm itidos.

4. R ealizar un program a que genere la siguiente secuencia de dgitos:

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

El nm ero de filas estar com prendido entre 11 y 20 y el resultado aparecer cen


trado en la pantalla com o se indica en la figura.

5. R ealizar un program a para ju g a r con el ordenador a acertar nm eros. El ordenador


piensa un nm ero y nosotros debem os de acertar cul es, en un nm ero de inten
tos determ inado. Por cada intento sin xito el ordenador nos ir indicando si el
nm ero especificado es m ayor o m enor que el pensado p o r l. El nm ero pensado
por el ordenador se puede obtener m ultiplicando p o r una constante el valor de
vuelto por el m todo ra n d o m de la clase M a th , y los nm eros pensados por no
sotros los introducirem os p o r el teclado.

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:

A es m enor que a ; es equivalente a decir que 65 es m enor que 97, porque


el valor ASCII de A es 65 y el de a es 97.

A + 3 es igual a 'D '; es equivalente a decir que 65 + 3 es igual a 68, y este


valor es el cdigo A SC II del carcter 'D '.
CA PTU LO 7
F.J.Cebalos/RA-MA

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.

En este captulo, aprender a registrar conjuntos de valores, todos del m ism o


tipo, en unas estructuras de datos llam adas m atrices. A s m ism o, aprender a re
gistrar cadenas de caracteres, que no son m s que conjuntos de caracteres, o bien,
si lo prefiere, m atrices de caracteres.

Si las m atrices son la form a de registrar conjuntos de valores, todos del m is


m o tipo (in t, flo at, d o u b le, c h a r. S trin g , etc.), qu harem os p ara alm acenar un
conjunto de valores relacionados entre s, pero de diferentes tipos? P or ejem plo,
alm acenar los datos relativos a una persona com o su nom bre, direccin, telfono,
etc. Ya hem os visto que esto se hace definiendo una clase; en este caso, podra ser
la clase de objetos persona. Posteriorm ente podrem os crear tam bin m atrices de
objetos, cuestin que aprenderem os m s adelante.
1 6 4 JA V A : C U R SO DE PRO G R A M A CI N

INTRODUCCIN A LAS MATRICES


U na m atriz es una estructura hom ognea, com puesta p o r varios elem entos, todos
del m ism o tipo y alm acenados consecutivam ente en m em oria. C ada elem ento
puede ser accedido directam ente p o r el nom bre de la variable m atriz seguido de
uno o m s subndices encerrados entre corchetes.

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.

D esde un punto de vista m atem tico, en m s d e una ocasin necesitarem os


u tilizar variables subindicadas tales com o:

v = [a 0 , a , , a 2,

en el caso de un subndice, o bien

00 ()\ a 02 a oj a,0/1
a i0 a il a !2 ax
m-

a l0 an a2 ... at,y ... ain

si se utilizan dos subndices. E sta m ism a representacin se puede utilizar desde un


lenguaje de program acin recurriendo a las m atrices que acabam os de definir y
que a continuacin se estudian.

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.

Entonces, las m atrices segn su dim ensin se clasifican en unidim ensionales


y m ultidim ensionales; y segn su contenido, en num ricas, de caracteres y de re
ferencias a objetos.

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.

MATRICES NUMRICAS UNIDIMENSIONALES


Igual que sucede con otras variables, antes de utilizar una m atriz hay que decla
rarla. La declaracin de una m atriz especifica el nom bre de la m atriz y el tipo de
elem entos de la misma.

Para crear y utilizar una m atriz hay que realizar tres operaciones: declararla,
crearla e iniciarla.

Declarar una matriz


La declaracin de una m atriz de una dim ensin, se hace indistintam ente de una de
las dos form as siguientes:

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.

L as siguientes lneas de cdigo son ejem plos de declaraciones de matrices:

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.

N otar q ue las declaraciones no especifican el tam ao de la m atriz. El tam ao


ser especificado cuando se cree la m atriz, operacin que se har durante la ejecu
cin del program a.

Segn se ha podido observar, los corchetes se pueden colocar tam bin d es


pus del nom bre de la m atriz. Por lo tanto, las declaraciones anteriores pueden es
cribirse tam bin as:

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

Crear una matriz


Despus de haber declarado una m atriz, el siguiente paso es crearla o construirla.
C rear una m atriz significa reservar la cantidad de m em oria necesaria para conte
ner todos sus elem entos y asignar al nom bre de la m atriz una referencia a ese blo
que. Esto puede expresarse genricam ente as:

nombre - new t i p o [ tamao];

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

L as siguientes lneas de cdigo declaran y crean las m atrices expuestas en los


ejem plos anteriores:

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

Iniciar una matriz


U na m atriz es un objeto; p o r lo tanto, cuando es creada, sus elem entos son auto
m ticam ente iniciados, igual que suceda con las variables m iem bro de una clase.
Si la m atriz es num rica, sus elem entos son iniciados a 0 y si n o es num rica, a un
valor anlogo al 0; p o r ejem plo, los caracteres son iniciados al valor \u 0 0 0 0 \ un
elem ento booleano a false y las referencias a objetos, a nuil.

Si deseam os iniciar una m atriz con otros valores diferentes a los predeterm i
nados, podem os hacerlo de la siguiente form a:

flo at temperatura = 1 1 0 . 2F. 1 2 . 3F. 3.4F. 1 4 . 5F, 1 5 . 6F. 16.7FI:

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.

Acceder a los elementos de una matriz

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

no es m s que una variable subindicada; por lo tanto, se puede utilizar exacta


m ente igual que cualquier otra variable. Por ejem plo, en las operaciones que se
m uestran a continuacin intervienen elem entos de una matriz:

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

C m o podem os asegurarnos de no exceder accidentalm ente el final de una


m atriz? V erificando la longitud de la m atriz m ediante la variable esttica length.
que puede ser accedida por cualquier m atriz. sta es el nico atributo soportada
por las m atrices. Por ejem plo:

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

Mtodos de una matriz


La clase genrica m atriz proporciona un conjunto de m todos que ha heredado
de la clase O b je ct del paquete ja v a.lan g. Entre ellos cabe ahora destacar e quals
(boolean equals(O bject objj) y clone (O bject clo n ef)). El prim ero perm ite verifi
car si dos referencias se refieren a un m ism o objeto, y el segundo perm ite duplicar
un objeto (vea en el captulo siguiente La clase O b je c t).
CA PTU LO 7: M A TRICES 169

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 " ) :

Trabajar con matrices unidimensionales


P ara practicar la teora expuesta hasta ahora, vam os a realizar un program a que
asigne datos a una m atriz unidim ensional m de nE lem entos elem entos y, a conti
nuacin, com o com probacin del trabajo realizado, escriba el contenido de dicha
m atriz. La solucin ser sim ilar a la siguiente:

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

El paso siguiente es asignar un valor desde el teclado a cada elem ento de la


m atriz.

for (i - 0: i < nElementos: i++)


I
System.out.p r i n t " m [ " + i + "] - "):
m [ i ] = L e e r . d a t o l n t ):
1 7 0 JA V A: C U R SO DE PROGRAM A CIN

U na vez leda la m atriz la visualizam os p ara com probar el trabajo realizado.

f o r ( i = 0: i < nE lem entos: i + + )


S y s t e m . o u t . p r i n t ( m [ i ] + " ):

El program a com pleto se m uestra a continuacin:

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

S ystem .out.p rin tln (" Introducir los valores de l a m a t r i z . ):


f o r ( i = 0: i < nE lem entos: i + + )
I
System .out.printt"m [" + i + "] = ");
m [ i ] = L e e r . d a t o I n t ( ):

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

El ejercicio anterior nos ensea cm o leer una m atriz y cm o escribirla. El


paso siguiente es aprender a trabajar con los valores alm acenados en la m atriz.
Por ejem plo, pensem os en un program a que lea la nota m edia obtenida p o r cada
alum no de un determ inado curso, las alm acene en una m atriz y d com o resultado
la nota m edia del curso.

Igual que hicim os en el program a anterior, en prim er lugar crearem os una


m atriz nota con un nm ero determ inado de elem entos solicitado a travs del te
clado. N o se perm itir que este valor sea negativo. En este caso interesa que la
m atriz sea de tipo float para que sus elem entos puedan alm acenar un valor con
decim ales. Tam bin definirem os un ndice i para acceder a los elem entos de la
m atriz, y una variable sum a para alm acenar la sum a total de todas las notas.
C A PTU LO 7: M A TRICES 171

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.

for (i - 0; i < nota.length: i++)


I
S y s t e m . o u t . p r i n t " N o t a media de l alumno " + (i+1) + ");
n o t a [ i ] = L e e r . d a t o F l o a t ( ):
I

Finalm ente se sum an todas la notas y se visualiza la nota m edia. La sum a se


alm acenar en la variable sum a. U na variable utilizada de esta form a recibe el
nom bre de acum ulador. Es im portante que observe que inicialm ente su valor es
cero.

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 ) :

El program a com pleto se m uestra a continuacin.

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

for (i = 0: i < nota.length; i++)


1
S y s te m , o u t . p r i n t C N o t a media del a l u mn o " + ( i + 1) + : ):
n o t a [ i ] = L e e r . d a t o F l o a t );

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

Los dos bucles fo r de la aplicacin anterior podran reducirse a uno com o se


indica a continuacin. N o se ha hecho por m otivos didcticos.

for (i = 0: i < nota.length: 1++)


I
S y s t e m . o u t . p r i n t " N o t a media de l alumno + ( i + 1 ) + ": "):
n o ta [i] = Leer.d a to Flo a t();
suma + = n o t a [ 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]

l a s m a t r i c e s mas u t i l i z a d a s son las unidim ensionales


y la s bidim ensional e s .

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

A ntes de em pezar el problem a, vam os a analizar algunas de las operaciones


q ue despus utilizarem os en el program a. Por ejem plo, la expresin:

z ' 'a ' + 1

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 .

Por la m ism a razn, si realizam os las declaraciones,

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

la siguiente sentencia asigna a c[97 el valor 10.

c [ * a *] - 10:

y esta otra sentencia que se m uestra a continuacin realiza la m ism a operacin,


lgicam ente, suponiendo que ca r tiene asignado el carcter 'a ' .

c[car] = 10:

Entonces, si leem os un carcter (de la a a la z ),

c a r = ( c h a r ) S y s t e m . i n . r e a d ( ):

y a continuacin realizam os la operacin,

c[car]++:

qu elem ento de la m atriz c se ha increm entado? La respuesta es el de subndice


igual al cdigo correspondiente al carcter ledo. H em os hecho coincidir el c a
rcter ledo con el subndice de la m atriz. A s cada vez que leam os una 'a ' se in
crem entar el contador c9 7 ] o lo que es lo m ism o c [ 'a ']; tenem os entonces un
contador de V . A nlogam ente direm os para el resto de los caracteres.

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:

c[car ' a ']+ + :


1 7 4 JA V A: C U R SO DE PROGRAM A CIN

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.

El program a com pleto se m uestra a continuacin.

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

// V i s u a l i z a r l a f r e c u e n c i a con l a que han a p a r e c i d o l o s c a r a c t e r e s


f o r ( c a r = ' a ' : c a r <= z : c a r + + )
System.out.print" + c[car - ' a' ] ) :
S y s t e m . o u t . p r i n t n i ):
1
)

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 :

System.out.println"Fin del proceso."):

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:

cha r [ ] c a d e n a = l'a', 'b', c ' . *d * I :

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:

cha r [ ] c a d e n a = 197, 98. 99. 1001:

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

Si se crea una m atriz de caracteres y se le asigna un nm ero de caracteres m e


nor que su tam ao, el resto de los elem entos quedan con el valor \ 0 con el que
fueron iniciados. Por ejem plo:
1 7 6 JA V A: C U R SO DE PROGRAM A CIN

char[] cadena - new charflO];


c a d e n a C O ] - a : c a d e n a f l ] = b ; c a d e n a [ 2 ] = c : c a d e n a [ 3 ] = 'd':
S y s t e m . o u t . p r i n t l n ( c a d e n a );

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 om o ya se expuso al hablar de las m atrices num ricas, un intento de acceder


a un valor de un elem ento con un subndice fuera de los lm ites establecidos al
crear la m atriz, dara lugar a que Java lanzara una excepcin durante la ejecucin.

Leer y escribir una cadena de caracteres


En el captulo 5, cuando se expusieron los flujos de entrada, vim os que una form a
de leer un carcter del (lujo in era utilizando el m todo read. Entonces, leer una
cadena de caracteres supondr ejecutar repetidas veces la ejecucin de read y al
m acenar cada carcter ledo en la siguiente posicin libre de una m atriz de carac
teres. Por ejem plo:

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

w hile ( ( c a r = S y s t e m . i n . r e a d ( )) != \ r && i < cadena. length)


cadena[i++] = (ch arle ar:

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

// 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 lu j o S = System.out:

String cadena: // v a r i a b l e p a r a a l m a c e n a r un a linea de t e x t o


try
1
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 : ):
c a d e n a = f 1u j o E . r e a d L i n e ( ) ; // l e e r una l i n e a de t e x t o
flujoS.println(cadena): // e s c r i b i r l a l i n e a l e d a
I
catch (IOException ignorada) 1 I

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.

C om parando el m todo read con el m todo re a d L in e , se puede observar que


este ltim o proporciona una form a m s cm oda de leer cadenas de caracteres de
un flujo y adem s, devuelve un objeto S t r in g cuyos m todos, com o verem os a
continuacin, hacen m uy fcil la m anipulacin de cadenas.

U na m atriz de caracteres tam bin puede ser convertida en un objeto S trin g,


segn se m uestra a continuacin. P or ejem plo:

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

Trabajar con cadenas de caracteres


El siguiente ejem plo lee una cadena de caracteres y a continuacin visualiza el
sm bolo y el valor A SC II de cada uno de los caracteres de la cadena. La solucin
ser de la forma:

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

E l problem a consiste en definir una cadena de caracteres, cadena, y asignarle


datos desde el teclado utilizando el m todo re a d . U na vez leda la cadena, se ac
cede a cada uno de sus elem entos (no olvide que son elem entos de una m atriz) y
por cada uno de ellos se visualiza su contenido y el valor A S C II correspondiente.

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

C uando un usuario ejecute este program a, se le solicitar que introduzca una


cadena. Por ejem plo:

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:

M inusculasM ayuscu las(caden a):

C om o se puede observar en el cdigo m ostrado a continuacin, el m todo re


cib ir una referencia a la cadena que se desea pasar a m aysculas. A continua
cin, acceder al prim er elem ento de la m atriz y com probar si se trata de una
m inscula, en cuyo caso cam biar el valor A SC II alm acenado en dicho elem ento
por el valor A SC II correspondiente a la m ayscula. Esto es:

static void M in u sculasM ayuscu las(char[] str)


I
i n t i = 0 . desp = a ' - A ' ;
f o r ( i = 0 : i < s t r . l e n g t h && s t r [ i ] ! = , \ 0 ; i++)
i f ( s t r [ i ] > = ' a ' && s t r [ i 3 < = z ' )
s t r [ i ] = ( c h a r ) ( s t r [ i ] - desp):
180 JAVA: C U R SO DE PROGRAM A CIN

O bserve que cuando se llam a al m todo M inusculasM ayusculas, lo que en


realidad se pasa es una referencia al com ienzo de la m atriz. P or lo tanto, el m to
do llam ado y el m todo que llam a, trabajan sobre la m ism a m atriz, con lo que los
cam bios realizados p o r uno u otro son visibles para am bos.

El program a com pleto se m uestra a continuacin.

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

public s t a t ic void m a in (S trin g [] args)


I
c h a r [ ] c a d e n a = 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 m atriz

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

La solucin que se ha dado al problem a planteado n o contem pla los caracteres


tpicos de nuestra lengua com o la o las vocales acentuadas. E ste trabajo queda
com o ejercicio para el lector.

La utilizacin de m atrices de caracteres para la solucin de problem as puede


ser am pliam ente sustituida por objetos de la clase S trin g . La gran cantidad y va
riedad de m todos aportados p o r esta clase facilitarn enorm em ente el trabajo con
cadenas de caracteres, puesto que, com o ya sabem os, un objeto S trin g encapsula
una cadena de caracteres.
C A P T U L O 7: M A TRICES 181

Clase String

La clase S trin g , que pertenece al paquete ja v a .la n g, proporciona m todos para


exam inar caracteres individuales de una cadena de caracteres, com parar cadenas,
buscar y extraer subcadenas, copiar cadenas y convertir cadenas a m aysculas o a
m insculas. A continuacin verem os algunos de los m todos m s com unes de la
clase S tr in g . P ero antes sepa que un objeto S t r in g representa una cadena de ca
racteres no m odificable. Por lo tanto, una operacin com o convertir a m aysculas
no m odificar el objeto original sino que devolver un nuevo objeto con la cadena
resultante de esa operacin.

A s m ism o, el lenguaje Java proporciona el operador + para concatenar o bje


tos S trin g , as com o soporte para convertir otros objetos a objetos S trin g . Por
ejem plo, en la siguiente lnea d e cdigo. Java debe convertir las expresiones que
aparecen entre parntesis en objetos S trin g . antes de realizar la concatenacin.

S y s t e m . o u t . p r in t ln ( "Dim ensin de l a m a t r i z : " + cadena.length);

La concatenacin de objetos S t r in g est im plem entada a travs de la clase


S t r in g B u ff e r y la conversin, a travs del m todo to S tr in g heredado de la clase
O bject. T anto la clase com o el m todo citados sern estudiados a continuacin.

R ecuerde que para acceder desde un m todo de la clase aplicacin o de cual


quier otra clase a un m iem bro (atributo o m todo) de un objeto de otra clase dife
rente se utiliza la sintaxis objeto.m iem bro. La interpretacin que se hace en
program acin orientada a objetos es que el objeto ha recibido un m ensaje, el es
pecificado por el nom bre del m todo, y responde ejecutando ese m todo. Los
m todos static son una excepcin a la regla (puede obtener m s inform acin en el
apartado M iem bro de un objeto o de una clase" del captulo 4).

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 s t r l = "abe : // c r e a un S t r i n g " a b e "


String s t r 2 = new S t r i n g ( " d e f ); // c r e a un S t r i n g " d e f
String s t r 3 = new S t r i n g ( s t r l ) : II c r e a un n u e v o S t r i n g "abe"

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

La m ism a operacin puede ser realizada utilizando la expresin s t r l = s tr l lo


cual ya fue expuesto en el apartado R eferencias a objetos del captulo 4.

String concat(String str)

Este m todo devuelve com o resultado un nuevo objeto S t r in g resultado de con


catenar el S t r in g especificado a continuacin del objeto S t r in g q ue recibe el m en
saje concat. P or ejem plo, la prim era lnea de cdigo que se m uestra a
continuacin da com o resultado A yer llovi y la segunda A yer llovi m ucho .

System .out.println("Ayer".concat(" llovi")):


System.out.pri n t ln ( "A y e r ". c o n c a t ( " 11o v i " . c o n c a t ( " m u c h o ") ) ) :

Si alguno de los S t r in g tienen longitud 0, se concatena una cadena nula. Este


otro ejem plo que se m uestra a continuacin construye un objeto a b e d e f' resulta
do de concatenar s tr l y str2, y asigna a s tr l la referencia al nuevo objeto.

Strin g s t r l = "abe", str2 = "def";


strl = strl .concat(str2):

int com pareTo(String otroString)

Este m todo com para lexicogrficam ente el S t r in g especificado, con el objeto


S t r in g que recibe el m ensaje c o m p a r e T o (el m todo e q u a ls realiza la m ism a
operacin). El resultado devuelto es un entero:

< 0 si el S t r in g que recibe el m ensaje es m enor que el otroString,


= 0 si el S t r in g que recibe el m ensaje es igual que el otroString y
> 0 si el S t r in g que recibe el m ensaje es m ayor que el otroString.
C A PTU LO 7: M A TRICES 183

En otras palabras, el m todo c o m p a r e T o perm ite saber si una cadena est en


orden alfabtico antes (es m enor) o despus (es m ayor) que otra y el proceso que
sigue es el m ism o que nosotros ejercitam os cuando lo hacem os m entalm ente,
com parar las cadenas carcter a carcter. La com paracin se realiza sobre los va
lores U nicode de cada carcter. El siguiente ejem plo com para dos cadenas y es
cribe abcde" porque esta cadena est antes por orden alfabtico.

S tr in g s t r l - "abcde, str2 = "abcdefg":


i f ( s t r l . c o m p a r e T o ( s t r 2 ) < 0)
System .out.p rin tln (strl):

El m todo c o m p a r e T o diferencia las m aysculas de las m insculas. Las m a


ysculas estn antes por orden alfabtico. Esto es as porque en la tabla U nicode
las m aysculas tienen asociado un valor entero m enor que las m insculas. El si
guiente ejem plo no escribe nada porque abe no est antes por orden alfabtico
que A be.

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 ):

Si en vez de utilizar el m todo c o m p a r e T o se u tiliza el m todo com pare-


T o Ig n o r e C a s e no se hace diferencia entre m aysculas y m insculas. El resultado
de ejecutar el siguiente program a es que s tr l y str2 son iguales.

public class Test


I
public static void m a in (S trin g [] args)
I
String s t r l = " L a p r o v i n c i a d e S a n t a n d e r e s muy b o n i t a " :
String s t r 2 = La p r o v i n c i a de S ANTANDER e s muy b o n i t a " :

S t r i n g strtemp;
in t resultado:

resultado = s t r l . com pareToIgnoreCase(str2):

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

Este m todo devuelve la longitud o nm ero de caracteres U nicode (tipo c h a r) del


objeto S t r in g que recibe el m ensaje length.

El siguiente ejem plo escribe com o resultado: L o n g i t u d : 39

S t r i n g s t r l = " L a p r o v i n c i a de S a n t a n d e r e s muy b o n i t a " :


S y ste m .o u t .p rin t'In C 'L o n g itu d : " + s t r l . l e n g t h t )):

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.

El siguiente ejem plo alm acena en s tr l la cadena str2 en m aysculas.

S tr in g s t r l . s tr2 = "Santander, tu eres novia del m ar...":


s t r l = s t r 2 . t o U p p e r C a s e t ):

String trim()

Este m todo devuelve un objeto S t r in g resultado de elim inar los espacios en


blanco que pueda haber al principio y al final del objeto S t r in g que recibe el m en
saje trim .

boolean startsW ith(String prefijo)

Este m todo devuelve un valor true si el prefijo especificado coincide con el


principio del objeto S t r in g que recibe el m ensaje sta rtsW ith .

boolean endsW ith(String sufijo)

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

String substring(int Indicelnicial, int IndiceFinal)

Este m todo retorna un nuevo S t r in g que encapsula una subcadena de la cadena


alm acenada por el objeto S t r in g q ue recibe el m ensaje su b strin g . La subcadena
em pieza en In d icelnicial y se extiende hasta IndiceF inal - I, o hasta el final si In-
diceF inal no se especifica.

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

char charAt(int ndice)

Este m todo devuelve el carcter que est en la posicin especificada en el objeto


S t r in g que recibe el m ensaje c h a rA t. El ndice del prim er carcter es el 0. Por lo
tanto, el parm etro ndice tiene que estar entre los valores 0 y le n gth () - 1. de lo
contrario Jav a lanzar un excepcin.

int indexOf(int car)

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.

int indexOf(String str)

Este m todo devuelve el ndice de la prim era ocurrencia de la subcadena especifi


cada por str en el objeto S t r in g que recibe el m ensaje in d e x O f. Si s tr no existe
in d e x O f devuelve -1. Puede com enzar la bsqueda por el final en lugar de ha
cerlo por el principio utilizando el m todo la stln d e x O f.

String repiace(char car, char nuevoCar)

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

static String valueOf(tipo dato)

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.

A lgunos de los m todos m s interesantes que proporciona la clase S t r in g B u


ffer, perteneciente al paquete ja v a .la n g, son los siguientes:

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

S y s t e m . o u t . p r i n t l n ( s t r b 3 + " + s t r b 3 . 1 e n g t h ( )+ " " + s t r b 3 . c a p a c i t y ( )):


i
La ejecucin de las lneas de cdigo del ejem plo anterior, da lugar a los si
guientes resultados:

0 16
0 80
a b c d e 5 21

A la vista de los resultados podem os deducir que cuando S t r in g B u f f e r se in


voca sin argum entos construye un objeto vaco con una capacidad inicial para 16
caracteres; cuando se invoca con un argum ento entero, construye un objeto vaco
con la capacidad especificada; y cuando se invoca con un S t r in g com o argum ento
construye un objeto con la secuencia de caracteres proporcionada por el argu
m ento y una capacidad igual al nm ero de caracteres alm acenados m s 16.

int length()

Este m todo devuelve la longitud o nm ero de caracteres U nicode (tipo c h a r) del


objeto S t r in g B u f fe r que recibe el m ensaje length. E sta longitud puede ser m odi
ficada por el m todo se tL e n g th cuando sea necesario.

int capacity()

Este m todo devuelve la capacidad en caracteres U nicode (tipo c h a r) del objeto


S tr in g B u ffe r que recibe el m ensaje capacity.

StringBuffer append(tipo x)

E ste m todo perm ite aadir la cadena de caracteres resultante de convertir el ar


gum ento x en un objeto S trin g , al final del objeto S t r in g B u f f e r que recibe el
m ensaje append. El tipo del argum ento x puede ser boolean, char, char[], int,
long. float, double, S t r in g y O bject. La longitud del objeto S t r in g B u f f e r se in
crem enta en la longitud correspondiente al S t r in g aadido.

StringBuffer insert(int ndice, tipo x)

E ste m todo perm ite insertar la cadena de caracteres resultante de convertir el ar


gum ento x en un objeto S tr in g , en el objeto S t r in g B u f f e r que recibe el m ensaje
inser. Los caracteres sern aadidos a partir de la posicin especificada por el
argum ento ndice. El tipo del argum ento x puede ser boolean. char. char| 1. int.
long. float, double. S t r in g y O bject. La longitud del objeto S t r in g B u f f e r se in
crem enta en la longitud correspondiente al S t r in g insertado.
188 JA V A: C U R S O DE PROGRAM A CIN

El siguiente ejem plo crea un objeto S t r in g B u f f e r con la cadena M es de del


ao", a continuacin inserta la cadena Abril a partir de la posicin 7, y final
m ente aade al final, la cadena representativa del entero 2002. El resultado ser
M es de Abril 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 ( " M e s de " . l e n g t h O , " A b r i l " ) ; // " M e s de . l e n g t h ( ) = 7
strb.append(2002);

StringBuffer delete(int p1, int p2)

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 ):

StringBuffer replace(int p1, int p2, String str)

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:

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 d e d e l ao "):


s t r b . insert.( 7 . " A b r i l " ) ;
strb.append(2002);
s t r b . r e p l a c e ( 7 . 13. "Ma yo " ) :

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 substring(int Indicelnicial, int IndiceFinal)

E ste m todo retorna un nuevo S t r in g que encapsula una subcadena de la cadena


alm acenada por el objeto S t r in g B u f fe r que recibe el m ensaje su b strin g. La sub
cadena em pieza en Indicelnicial y se extiende hasta IndiceF inal - 1, o hasta el fi
nal si IndiceF inal no se especifica.

char charAt(int ndice)

Este m todo devuelve el carcter que est en la posicin especificada en el objeto


S tr in g B u ffe r que recibe el m ensaje c h a rA t. El ndice del p rim er carcter es el 0.
P o r lo tanto, el parm etro ndice tiene que estar entre los valores 0 y le n gth () - 1.

void setCharAt(int ndice, char ca)

Este m todo reem plaza el carcter que est en la posicin especificada en el ob


je to S t r in g B u ff e r que recibe el m ensaje s e tC h a rA t, por el nuevo carcter espe
cificado. El ndice del prim er carcter es el 0. P or lo tanto, el parm etro ndice
tiene que estar entre los valores 0 y le n gth O - 1.

String toString()

Este m todo devuelve com o resultado un nuevo S t r in g copia del objeto S t r in g


B u ffe r que recibe el m ensaje to Strin g.

El siguiente ejem plo copia la cadena alm acenada en strb en str.

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 ( " a b c d e " ):


S t r i n g s t r = s t r b . t o S t r i n g ( );

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

Un objeto S tr in g T o k e n iz e r se construye a partir de un objeto S trin g . Por


ejem plo:

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

C uando ejecutem os las cuatro lneas de cdigo correspondientes a los dos


ejem plos anteriores, el resultado que se m ostrar ser el siguiente:

un o,
dos.
tres
y
cuatro

Tam bin se pueden especificar los delim itadores en el instante de construir el


objeto S trin g T o k e n iz e r. Por ejem plo, la siguiente lnea de cdigo especifica co
m o delim itadores la com a y el espacio en blanco:

cadena - new S t r i n g T o k e n i z e r ( " u n o . d o s . tres y cuatro". ". "):

En este caso, el resultado que se obtendr a partir del objeto cadena es el si


guiente:

uno
dos
tres
y
cuatro

La diferencia con respecto a la versin anterior es que ahora no aparece la


com a com o parte integrante de los elem entos, ya que se ha especificado co m o de
lim itador y los delim itadores no aparecen. Si querem os que los delim itadores ap a
rezcan com o un elem ento m s, basta especificar tr u e com o tercer argum ento:

cadena - new S t r i n g T o k e n i z e r ( u n o . dos. tres y cuatro". true):

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

Conversin de cadenas de caracteres a datos numricos


C uando una cadena de caracteres representa un nm ero y se necesita realizar la
conversin al valor num rico correspondiente, p o r ejem plo, para realizar una ope
racin aritm tica con l, hay que u tilizar los m todos apropiados proporcionados
por las clases del paquete ja v a .la n g : Byte, C h a ra c te r, S h o rt, In te ge r, L o n g.
Flo at, D o u b le y Boo lean . Para m s detalles, recurra al captulo 5, donde fueron
expuestos los m todos aludidos. Por ejem plo:

String s trl - "1234":


i n t d a t o l = I n t e g e r . p a r s e l n t ( s t r l ): // c o n v e r t i r a entero

String str2 - "12.34";


f l o a t d a t o 2 = (new F l o a t ( s t r 2 ) ) . f 1o a t V a l u e ( ) : // c o n v e r t i r a float

MATRICES DE REFERENCIAS A OBJETOS


Segn lo estudiado a lo largo de este captulo podem os decir que cada elem ento
de una m atriz unidim ensional es de un tipo prim itivo, o bien una referencia a un
objeto. Entonces cm o procederam os si necesitram os alm acenar las tem peratu
ras m edias de cada da durante los 12 m eses de un ao?, o bien cm o procede
ram os si necesitram os alm acenar la lista de nom bres de los alum nos de una
determ inada clase? R azonando un poco, llegarem os a la conclusin de que utilizar
m atrices unidim ensionales para resolver los problem as planteados supondr pos
teriorm ente un difcil acceso a los datos alm acenados; esto es, responder a las
preguntas: cul es la tem peratura m edia del 10 de m ayo?, o bien cul es el
nom bre del alum no nm ero 25 de la lista? ser m ucho m s sencillo si los datos
los alm acenam os en form a de tabla; en el caso de las tem peraturas, una tabla de
12 filas (tantas com o m eses) por 31 colum nas (tantas com o los das del m es ms
largo); y en el caso de los nom bres, una tabla de tantas filas com o alum nos, y
tantas colum nas com o el nm ero de caracteres del nom bre m s largo. P or lo tanto,
una solucin fcil para los problem as planteados exige el uso de m atrices de dos
dim ensiones.

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.

Matrices numricas multidimensionales


La definicin de una m atriz num rica de varias dim ensiones se hace de la forma
siguiente:

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,

moo moi m 02 fila 0

mo mu m t2 fila 1

Evidentem ente, el tipo de los elem entos de la m atriz referenciada por m es


int[] y el tipo de los elem entos de las m atrices referenciadas por m /0 ] y m [ l ] es
int. A dem s, puede com probar la existencia y la longitud de las m atrices unidi
m ensionales referenciadas por m , m [0] y m [ I ] utilizando el cdigo siguiente:

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

C om o ejem plo de aplicacin de m atrices m ultidim ensionales, vam os a reali


zar un program a que asigne datos a una m atriz m de dos dim ensiones y a co n ti
nuacin escriba las sum as correspondientes a las filas de la m atriz. La ejecucin
del program a presentar el aspecto siguiente:

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.

int n f ila s . ncols; // f i l a s y c o l u m n a s de l a m a t r i z


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 negativo
194 JA V A: C U R SO D E PROGRAM A CIN

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

D espus, cream os la m atriz m con el nm ero de filas y colum nas especifica


do, definim os las variables fila y col que utilizarem os para m anipular los subndi
ces correspondientes a la fila y a la colum na, y la variable sum afila para
alm acenar la sum a de los elem entos de una fila:

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

El paso siguiente es asignar un valor desde el teclado a cada elem ento de la


matriz.

f o r ( f i l a = 0: f i l a < n fila s; fila++)


f o r ( co l = 0; col < ncols: col++)
I
S y ste m .o u t.p rin tt "m [" + f i l a + + col + "] = "):
m [ f i l a ] [ c o l ] = L e e r . d a t o F l o a t t ):
I

U na vez leda la m atriz, calculam os la sum a de cada fila y visualizam os los


resultados para com probar el trabajo realizado.

for (fila = 0; fila < nfilas; 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 l a ] [ c o l ];
S y s t e m . o u t . p r i n t l n ( Suma de 1 a f i 1 a " + f i 1 a + " : + sum afila):

El program a com pleto se m uestra a continuacin.

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

System .out.p rin tn(" Introd u cir los valores de l a m atriz.");


f o r ( f i l a = 0: f i l a < n f i l a s ; f i l a + + )
I
for (col - 0; col < ncols: col++)
I
System .out.print"m [" + f i l a + " ] [ " + col + "] = ");
m[f1l a ] [ c o l ] = L e e r.d a to F lo a t();

// 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 y s t e m . o u t . p r i n t l n t " S u m a de l a fila " + fila + ": " + sumafila):


I
System .out.p rin tn("\nFin del proceso."):

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.

for (fila = 0: fila < nfilas: fila++)


I
s u m a f i 1 a = 0;
f o r ( c o l = 0; col < ncols; col++)
I
System .out.printt"m [" + f i l a + "][" + col + ] = " ) ;
1 9 6 JA VA : C U R S O DE PROGRAM ACIN

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

No obstante, esta form a de proceder presenta una diferencia a la hora de vi


sualizar los resultados, y es que la sum a de cada fila se presenta a continuacin de
haber ledo los datos de la misma.

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.

Matrices de cadenas de caracteres


L as m atrices de cadenas de caracteres son m atrices m ultidim ensionales, general
m ente de dos dim ensiones, en las que cada fila se corresponde con una cadena de
caracteres. E ntonces segn lo estudiado, una fila puede ser un objeto m atriz uni
dim ensional, un objeto S trin g o un objeto S trin g B u ffe r.

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:

char[)[] nombre__matri z = new ch a r [ f i I a s ] [ 1ongi t u d _ f i 1a ] ;

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

trices unidim ensionales de C elem entos de tipo c h a r. G rficam ente podem os


im aginarlo as:

mo ------------------- * mo.o mo.i mo.2 m o.c-i fila 0


mt ------- m i.o m i.i m i .2 m t.c -i fila 1
m2 -------------------
m 2.o m 2.i m 2.2 m 2.c-i fila 2
------------------- *
... ...
*
itif -i niF-i.p m F- i.i niF-i.2 m p-i.c-i fila F-1

Evidentem ente, el tipo de los elem entos de la m atriz referenciada p o r m es


c h a r[] y el tipo de los elem entos de las m atrices referenciadas por m [0], m [ l] ......
es char. D esde nuestro punto de vista, es m s fcil im aginarse una m atriz de ca
denas de caracteres com o una lista. Por ejem plo, la m atriz m del ejem plo anterior
estar com puesta por las cadenas de caracteres rn[0], m [ l] , m [2], m i3 ], etc.

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.

P ara ilustrar la form a de trabajar con cadenas de caracteres, vam os a realizar


un program a que lea una lista de nom bres y los alm acene en una m atriz. Una vez
construida la m atriz, visualizarem os su contenido.

La solucin tendr el aspecto siguiente:

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

La solucin pasa p o r realizar los siguientes puntos:

1. D efinir una m atriz de cadenas, los ndices y dem s variables necesarias.

2. E stablecer un bucle para leer las cadenas de caracteres utilizando el m todo


re a d . La entrada de datos finalizar al introducir la m arca de fin de fichero.

3. P reguntar al usuario del program a si quiere visualizar el contenido de la ma


triz.

4. Si la respuesta anterior es afirm ativa, establecer un bucle para visualizar las


cadenas de caracteres alm acenadas en la m atriz.

El program a com pleto se m uestra a continuacin.

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

S y s t e m . o u t . p r i r j t l p " E s c r i b a l o s nombres que desea i n t r o d u c i r . " ) ;


S y s t e m . o u t . p r i n t l n ( " P u e d e f i n a l i z a r p u l s a ndo l a s t e c l a s [ C t r l ] [ Z ] . " ) :
f o r ( f i l a - (ti f i l a < n F i l a s : T i l a + + )
, u r.jlri o n n u -.* i.r.d-.b a.p vjr-ciia -
f l u j o S . p r i n t " N o m b r e [ + f i l a + ]: " ) ;
n C a r s L e i d o s = f l u j o E . r e a d n o m b r e [ f i 1a ] 0 . n C a r s P o r F i l a ) ;
// S i s e p u l s [ C t r l ] [ Z ] , s a l i r d e l b u c l e
i f (nCarsLeidos = e o f ) break;
// E l i m i n a r l o s c a r a c t e r e s CR LF
n o m b r e [ f i 1 a ] [ n C a r s L e i d o s - 1] = * \ 0 ;
n o m b r e [ f i l a ] [ n C a r s L e i d o s - 2 ] = * \ 0 *:
1
flu jo S.p rin t"\n \n ");
n F i l a s = f i l a : // n me r o d e f i l a s leidas
char respuesta:
do
fl.:-.
f l u j o S . p r i n t ( " D e s e a v i s u a l i z a r el conteni do de l a m a t r i z ? ( s /n ) : " ) ;
respuesta = ( ( f lu j o E . r e a d L in e ) ) .toLoW erCase) ) .ch a rA t(O );
I .fV j .*<>, , ;r,' -i, . . , '! ,,rr: ^ .
w h i l e ( r e s p u e s t a ! = ' s ' && r e s p u e s t a != 'n'),;
i f ( respuesta == s ' )
I
// V i s u a l i z a r l a l i s t a de n o m b r e s
f l u j o S . 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 : f i l a + + )
f l u j o S . p r i n t n n o m b r e t f i l a ] );

catch (IOException ignorada) 1 I

El identificador nom bre hace referencia a una m atriz de caracteres de dos di


m ensiones. U na fila de esta m atriz es una cadena de caracteres (una m atriz de ca
racteres unidim ensional) y la biblioteca de Java provee el m todo re a d para leer
m atrices unidim ensionales de caracteres. Por eso. para leer una fila (una cadena
de caracteres) utilizam os slo un ndice. Esto no es aplicable a las m atrices num
200 JA V A: C U R SO DE PROGRAM A CIN

ricas de dos dim ensiones, ya que la biblioteca de Java no proporciona m todos pa


ra leer filas com pletas, lo cual es lgico.

Siguiendo con el anlisis del program a anterior, la entrada de datos finalizar


cuando se haya introducido la m arca de fin de fichero, o bien cuando se hayan in
troducido la totalidad de los nom bres.

A s m ism o, una v ez finalizada la entrada de datos, se lanza una pregunta acer


ca d e si se desea visualizar el contenido de la m atriz. En este caso la respuesta te
cleada se obtiene con re a d L in e . C om o este m todo lee hasta el carcter \n
inclusive, utilizam os el m todo c h a r A t para obtener del S t r in g devuelto por rea
d L in e , el prim er carcter ledo, que deber ser una s o bien una n .

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

D e qu longitud son las cadenas de caracteres nom bre/0, n o m b re/1], etc.?


Independientem ente del nm ero de caracteres ledos para cada uno de los nom
b res solicitados, todas son de la m ism a longitud: nC arsP orF ila caracteres
(recuerde que las m atrices de caracteres son iniciadas con nulos); para verificarlo
puede recurrir al atributo length de las m atrices. E videntem ente, esta form a de
proceder supone un derroche de espacio de m em oria, que se puede evitar hacien
do que cadena fila de la m atriz nom bre tenga una longitud igual al nm ero de ca
racteres del nom bre que alm acena. A pliquem os esta teora al program a anterior.

El proceso que seguirem os para solucionar el problem a planteado es el si


guiente:

D efinim os la m atriz de referencias a las m atrices unidim ensionales que sern


las filas de una supuesta lista.

char[ ] [] nombre = new c h a r [ n F i 1 a s ] [ ] :

N o asignam os m em oria para cada una d e las cadenas porque no conocem os su


longitud {nombre( 0 / = nuil, n o m b re/1] = nuil, etc.). P or lo tanto, este proce
so lo desarrollarem os paralelam ente a la lectura de cada una de ellas.
C A P T U L O 7: M A TRICES 201

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.

char[] un Nombre = new c h a r [ 8 1 ]

U na vez leda la cadena, conocerem os cuntos caracteres se han ledo; enton


ces, reservam os m em oria (new ) para alm acenar ese nm ero de caracteres, a l
m acenam os la referencia al bloque de m em oria reservado en el siguiente
elem ento vaco de la m atriz de referencias nom bre y copiam os unN om bre en
el nuevo bloque asignado (fila de la m atriz nom bre). Este proceso lo repeti
rem os para cada uno de los nom bres que leam os.

for (fila = 0; fila < nFilas: fila++)


I
f l u j o S . p r i n t ( " N o m b r e t " + f i l a + ]: "):
nCarsLeidos = flujoE.read(unNombre. 0, n C a r s P o r F i 1 a ) :
// S i s e p u l s [ C t r l ] [ Z ] , s a l i r d e l bucle
i f ( n C a rs L e id o s == e o f) break:

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

G rficam ente puede im aginarse el proceso descrito de acuerdo a la siguiente


estructura de datos:

unNombre J \r \n

nombre nombrep c a r m e n filaO


nombret F r a n c i s e o fila 1
nombre? J e s s fila 2

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.

U na vez leda la m atriz la visualizam os si la respuesta a la peticin de realizar


este proceso es afirm ativa.

El program a com pleto se m uestra a continuacin.


202 JA V A: C U R SO DE PROGRAM A CIN

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 ] [ ] :

S y s t e m . o u t . p r i n t l n ( " E s c r i b a l o s nombres que desea i n t r o d u c i r . " ) ;


S y s t e m . o u t . p r i n t l n t " P u e d e f i n a l i z a r p u l s a ndo l a s t e c l a s [ C t r l ] C Z ] . " ) ;
f o r ( f i l a = 0; f i l a < n F i l a s : f i l a + + )
I
flujoS.printf"N om bre[" + f ila + "]: ");
n C a r s L e i d o s = f l u j o E . r e a d ( u n N o m b r e , 0. n C a r s P o r F i l a ) :
// S i s e p u l s [ C t r l 3 [ Z J . s a l i r d e l b u c l e
i f (n C a rsL e id o s == e of) break:
// A a d i r el nombre l e i d o a l a m a t r i z ; nombre

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

Matrices de objetos String


En el apartado anterior hem os aprendido a m anipular cadenas de caracteres a ni
vel de carcter. Pero Java proporciona las clases S t r in g y S t r in g B u f f e r para ha
cer de las cadenas de caracteres objetos con sus atributos particulares, los cuales
podrn ser accedidos por los m todos de sus clases. D esde este nivel de abstrac
cin m uchos de los problem as que se han presentado anteriorm ente y que hem os
tenido que resolver, ahora sim plem ente no aparecern con lo que la im plem enta-
cin del program a resultar m s sencilla.

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:

D efinim os la m atriz de objetos S trin g :

Strin gf] no mb r e = new S t r i n g [ n F i 1 a s ] ;

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.

for (fila = 0; fila < nFilas; fila++)


(
flujoS.print("Nom breC" + f ila + "]: "):
n o m b r e [ f i l a ] = f 1u j o E . r e a d L i n e ( );
// S i s e p u l s [ C t r l ] [ Z ] , s a l i r d e l bucle
i f ( n o m b r e f i 1a ] - - n u i l ) b r e a k :
1

G rficam ente puede im aginarse el proceso descrito de acuerdo a la siguiente


estructura de datos, aunque para trabajar resulte m s fcil pensar en una ma
triz unidim ensional cuyos elem entos nom bre[0], n o m b r e [l] , etc. son cadenas
de caracteres.
204 JA VA : C U R S O DE PROGRAM A CIN

nom breo o b je to Strinq


n o m b rei o b je to Strinq
n o m b re 2 o b je to String

Una vez ledos todos los nom bres deseados los visualizam os si la respuesta a
la peticin de realizar este proceso es afirm ativa.

El program a com pleto se m uestra a continuacin.

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 y s t e m . o u t . p r i n t l n C ' E s c r i b a l o s nombres que desea i n t r o d u c i r . " ) :


S y s t e m . o u t . p r i n t l n " P u e d e f i n a l i z a r p u l s a nd o l a s t e c l a s [ C t r l ] [ Z ] . );
f o r ( f i l a = 0: f i l a < n F i l a s : f i l a + + )
I
flujoS.print("N om bre[" + f ila + "]: "): ___________
n o m b r e [ f i l a ] - f 1u j o E . r e a d L i n e ( );
I I S i s e p u l s [ C t r l ] CZ ] . s a l i r d e l bucle
i f ( n o m b r e C f i 1a ] - - n u i l ) b r e a k :
I
f l u j o S . p r i n t \ n \ n " ) :
n F i l a s = f i l a : // n mero de f i l a s ledas
II ...
CA PTU LO 7: M A TRICES 2 0 5

// c o n t i n a igual q u e en l a versin anterior


1
catch (IOException ignorada) I )

Si en lugar de utilizar objetos S tr in g utilizam os objetos S trin g B u ffe r, las


m odificaciones son m nim as. P uede verlas en el cdigo m ostrado a continuacin:

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 ;

for (fila = 0: fila < nFilas; fila++)


I
flujoS.print("Nom breC" + f i l a + "]: "):
// S i s e p u l s [ C t r l ] C Z 3. s a l i r d e l b u c l e
i f ( ( s N o m b r e = f 1u j o E . r e a d L i n e ( ) ) n u i l ) break:
n o m b r e [ f i l a ] = new S t r i n g B u f f e r ( s N o m b 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.

La solucin de este problem a puede ser de la siguiente forma:

D efinim os la m atriz que va a co ntener la lista de valores y el resto de las va


riables necesarias en el program a.

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):

f 1 o a t [ ] d a t o - new f l o a t [ n E l e i n e n t o s ] ; // c r e a r l a m a triz dato


i n t i = 0; / / subndice
f l o a t max, m i n : // v a l o r mxi mo y v a l o r m n i m o

A continuacin leem os los valores que form an la lista. La entrada de datos fi


nalizar cuando se tecleen todos los valores, o bien cuando se teclee un valor
no num rico; por ejem plo, pulsar sim plem ente la tecla Entrar. Hagam os un
breve repaso de la clase L eer que im plem entam os en el captulo 5. Los mto-
206 JA V A"'CURSO D E PROGRAM A CIN

dos de esta clase devuelven el nm ero entero o decim al introducido a travs


del teclado. A hora bien, cuando el v alo r tecleado no se corresponde con un
nm ero, los m todos im plem entados para leer un entero devuelven el valor
M I N _ V A L U E (valor m nim o) y los im plem entados para leer un decim al, de
vuelven el v alo r N a N (no es un nm ero).

'for (i = 0; i < dato.length; i++)

System .out.printt"dato[" + i + "]= "):


d a t o [ i ] = L e r . d a t o F l o a t ( );
i f ( F l o a t . i s N a N ( d a t o [ i ] ) ) b r e a k ; // s a l i r del bucle
1

nEle mentos = i : // n mero de v a l o r e s ledos

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.

U na vez leda la lista d e valores, calculam os el m xim o y el m nim o. Para ello


suponem os inicialm ente que el p rim er valor es el m xim o y el m nim o (com o
si todos los valores fueran iguales). D espus com param os cada uno de estos
dos valores con los restantes de la lista. El v alo r de la lista com parado pasar
a ser el nuevo m ayor si es m s grande que el m ayor actual y pasar a ser el
nuevo m enor si es m s pequeo que el m enor actual.

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

Finalm ente, escribim os el resultado.

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

E l program a com pleto se m uestra a continuacin.


CA PITU LO 7: M A TRICES 2 0 7

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

Sy ste m .o u t.p rin tln (" In tro d u c ir los valores.\n" +


"Para f i n a l i z a r p u l s e [ E n t r a r ] " ),; .i,,.;,t , .
for (i = 0 ; i < dato, length: i++)
I
S y s t e m . o u t . p r i n t ( d a t o [ " + i + " ] = "):
d a t o [ 1 ] = L e e r . d a t o F l o a t ( );
i f ( F l o a t . i s N a N ( d a t o C i] ) ) break:
I
nElementos = i: // n me r o de v a l o r e s ledos > ...

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

Para realizar este problem a, en funcin de lo expuesto necesitam os una m atriz


de enteros de dos dim ensiones. C ada elem ento actuar com o contador de la pareja
de letras correspondiente. Por lo tanto, todos los elem entos de la m atriz deben
valer inicialm ente cero.

in t[][] t a b l a = new i n t [ ' z ' ' a + l ] [ z ' - ' a ' + 1]:

Para que la solucin sea fcil, aplicarem os el concepto de m atrices asociativas


visto anteriorm ente en este m ism o captulo; es decir, la pareja de letras a contabi
lizar sern los ndices del elem ento de la m atriz que acta com o contador de dicha
pareja. O bserve la tabla anterior y vea que el contador de la pareja aa es el ele
m ento (0.0) de la supuesta m atriz. Esto supone restar una constante de valor ' a
los valores de los ndices (carant, ca r) utilizados para acceder a un elem ento. La
variable carant contendr el prim er carcter de la pareja y ca r el otro carcter.

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 ' ] + + :

El problem a com pleto se m uestra a continuacin.


C A P T U L O 7: M A TRICES 2 0 9

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 nalizando el cdigo que m uestra la tabla de frecuencias, observam os un


prim er bucle fo r que visualiza la cabecera a b c esta prim era lnea especifica
el segundo carcter de la pareja de letras que se contabiliza; el prim er carcter
aparece a la izquierda de cada fila de la tabla. D espus observam os dos bucles fo r
anidados cuya funcin es escribir los valores de la m atriz tabla p o r filas; ntese
que antes de cada fila se escribe el carcter prim ero de las parejas d e letras que se
contabilizan en esa lnea.

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.

R ealizar un program a que lea los pesos e im prim a el histogram a correspondiente.


Suponer que los pesos estn com prendidos entre los valores 10 y 100 Kg. E n el
histogram a slo aparecern los pesos que se corresponden con 1 o m s alum nos.

2. R ealizar un program a que lea una cadena de n caracteres e im prim a el resultado


que se obtiene cada vez que se realice una rotacin de un carcter a la derecha so
bre dicha cadena. El proceso finalizar cuando se haya obtenido nuevam ente la
cadena de caracteres original. Por ejem plo,

HOLA AHOL LAHO OLAH HOLA


CA PTU LO 7: M A TRICES 2 1 1

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.

4. La m ediana de una lista de n nm eros se define com o el valor que es m enor o


igual que los valores correspondientes a la m itad de los nm eros, y m ayor o igual
que los valores correspondientes a la o tra m itad. P or ejem plo, la m ediana de:

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

R ealizar un program a que lea un nm ero im par de valores y d com o resultado la


m ediana. L a entrada de valores finalizar cuando se detecte la m arca de fin de fi
chero.

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.

6. A nalice el program a que se m uestra a continuacin e indique el significado que


tiene el resultado que se obtiene.

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

public static byte HaceAlgo(byte car)


I
r e t u r n ( b y t e ) ( ( ( c a r & 0x01) << 7) | ( ( c a r & 0x02) << 5) |
( ( c a r & 0x04) << 3) j ( ( c a r & 0x08) << 1) j
' ! ( ( c a r & 0x10) 10 j ( ( c a r 0x200: ' 3) \
:u-io/ ( ( c a r 0x40) .:5i>i I - ( ( . c a r 0x80>:>>,.7)):
212 JA VA : C U R S O DE PROGRAM A CIN

pu blic s t a t ic void main(S t r i n g [ ] args)


i
byte 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 e un c a r c t e r A S C I I : );
c a r = ( b y t e J S y s t e m . i n . r e a d ):
V i s u a 1 i z a r ( c a r );
S y s t e m . o u t . p r i n t l n ( \ n C a r c t e r r e s u l t a n t e : );
car = H aceA lgo(car);
V isu alizar(car):
I
catch (IOException ignorar)!I

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

se guardar en una m atriz unidim ensional as: valor

|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:

int C r e a r M a t r i ztlni ( i n t [ ] m. int f i , int co):

Los parm etros f i y co se corresponden con el nm ero de filas y de colum nas


de la supuesta m atriz bidim ensional.

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:

int V isu alizar(in t f. int c. i n t [ ] m);


CA PTU LO 7: M ATRICES 2 1 3

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.

PASAR UNA MATRIZ COMO ARGUMENTO A UN MTODO


En el captulo 4 se expuso cm o definir un m todo en una clase y se explic cm o
pasar argum entos a un m todo. R ecuerde que los objetos pasados a los parm etros
de un m todo son siem pre referencias a dichos objetos, lo cual significa que cual
q u ier m odificacin que se haga a esos objetos dentro del m todo afecta al objeto
original, y las m atrices son objetos. En cam bio, las variables de un tipo prim itivo
se pasan por valor, lo cual significa que se pasa una copia, por lo que cualquier
m odificacin que se haga a esas variables dentro del m todo no afecta a la varia
ble original.

En m s de una ocasin, trabajando con cadenas de caracteres hem os pasado


com o argum ento una m atriz. S irva de ejem plo el m todo M inusculasM ayusculas
expuesto en el apartado T rabajar con cadenas de caracteres del captulo ante-
216 JA V A: C U R SO D E PROGRAM A CIN

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.

public class Test


I
static void Mu t i p l i c a r P o r D o s M a t r i z 2 D ( d o u b l e [ ] [ ] x)
I
for (in t f = 0; f < x.length; f++)
I
f o r ( i n t c = 0: c < x [ 0 ] .1e n g t h : c++)
X [ f ] [ c ] * = 2:

public static void m a in (S trin g [] args)


!
double[][] m = 1110, 20. 30}. 14 0 , 50. 601);

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 ):

La aplicacin anterior se ejecuta de la form a siguiente: el m todo m a in crea e


inicia una m atriz m de dos dim ensiones de tipo d o u b le. D espus invoca al m todo
M ultiplicarP orD osM atriz2D pasando com o argum ento la m atriz m; esto im plica
que el m todo tenga un parm etro declarado as: d o u b lef / / / x. Por ser m un obje
to, el parm etro x recibe una referencia a la m atriz m; esto es, a- alm acenar la po
sicin de m em oria de dnde se encuentra la m atriz, no una copia de su contenido.
Por lo tanto, ahora el m todo M uItiplicarP or)osM atriz2D tiene acceso a la m is
ma m atriz q ue el m todo m ain . G rficam ente puede im aginrselo as:
C A PTU LO 8: M TO D O S 2 1 7

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

C ul es el resultado? Q ue cuando el m todo m a in visualice los elem entos de


la m atriz m , stos aparecern con los cam bios introducidos por el m todo M ulti-
plicarP orD osM atriz2D . Esto es, am bos m todos trabajan sobre la m ism a matriz.

MATRIZ COMO VALOR RETORNADO POR UN MTODO


Segn vim os en el captulo 4, un m todo puede retornar un valor de cualquier tipo
prim itivo, o bien una referencia a cualquier clase de objetos. Por lo tanto, en el
caso de que un m todo devuelva una m atriz, lo que realm ente devuelve es una
referencia a la m atriz. A clarem os esto con un ejem plo.

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.

public class Test


(
s t a t i c d o u b l e [ ] [ ] C o p i a r M a t r i z 2 D ( d o u b l e [ ] [ ] x)
i
d o u b l e [ ] [ ] z = new d o u b l e x . l e n g t h ] [ x [ 0 ] . l e n g t h ] ;

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

public static void m a in (S trin g [] args)


I
d o u b l eC ] C 3 mi = M IO . 20. 30). 14 0 . 50, 60ll;

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

La aplicacin anterior se ejecuta de la form a siguiente: el m todo m a in crea e


inicia una m atriz de dos dim ensiones de tipo d o u b le referenciada por m i , y decla
ra una referencia m 2 a una m atriz d e dos dim ensiones del m ism o tipo. Despus
invoca al m todo C opiarM atriz2D pasando com o argum ento la m atriz m i. Esto
im plica que ese m todo tenga un parm etro declarado as: double[/[ ] x , para que
pueda recibir una referencia a la m atriz m i. A continuacin, C opiarM atriz2D crea
una m atriz z de las m ism as caractersticas que x, copia los elem entos d e x en z y
devuelve com o resultado z. F inalm ente, la referencia devuelta p o r CopiarM a-
triz2D es alm acenada p o r el m todo m a in en m 2, que com o com probacin visua
liza esa matriz.

Evidentem ente, el m todo C opiarM atriz2D podra haberse diseado segn el


siguiente prototipo, trabajo que se deja com o ejercicio p ara el lector.

static void C o p ia rM a tfiz2 D (d o u b le [][] destin. double[][] origen)

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:

double[][] mi = 1 1 1 0 , 2 0 . 3 0 1 , 1 40, 5 0 . 6011:


double[][] m2 = ( d o u b l e [ ] [ ] ) m l . c l o n e t ) :
for (in t f - 0: f < m l . l e n g t h ; f + + )
m2[f] = tint[])m l[f].clone t):

O tra form a ms de realizar una copia de una m atriz es utilizando el mtodo


a rra y c o p y de la clase System . Se trata de un m todo pblico y esttico cuya sin
taxis es la siguiente:

void arraycopytObject origen, in t posicin_origen,


Object d e stin o , in t p o sic i n _ d e stin o .
int longitud)
C A PTU LO 8: M TODOS 2 1 9

donde origen es la m atriz origen de los datos, posicin.jorigen el ndice de inicio


en la m atriz origen, destino es la m atriz destino de los datos, posicin_destino el
ndice de inicio en la m atriz destino y longitud es el nm ero de elem entos que se
desean copiar.

P o r ejem plo, el cdigo m ostrado a continuacin, copia una m atriz de dos di


m ensiones referenciada por n tl en otra m atriz referenciada p o r 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 ) :

REFERENCIA A UN TIPO PRIMITIVO


C uando un m todo Java invoca a otro m todo y le pasa un argum ento de un tipo
prim itivo, pasa una copia de ese argum ento. P or ejem plo:

pu b lic s t a t ic void Increm entarlO (int param)


,1
p a r a m + = 10;

public s t a t ic void m a in (Striiig[] args)


I I"; f o 'j '

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.

Segn lo estudiado hasta ahora, cuando se pasa un argum ento que es un o b


jeto , Jav a no hace una copia del objeto sobre el parm etro correspondiente del
m todo, sino que inform a al m todo acerca del lugar de la m em oria donde est
ese o b jeto para que puede acceder al m ism o, lo que se denom ina pasar un argu
m ento p o r referencia. E sto es, lo qu se copia en el parm etro del m todo es una
referencia al objeto;
220 JA V A: C U R SO D E PROGRAM A CIN

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:

public static void Increm entarl0(Integer param)


I
i n t v a l o r = p a r a m . i n t V a l u e ( );
v a l o r + - 10:
pa r a m = new I n t e g e r ( v a l o r ) :
I

public static void m a in (S trin g [] args)


I
I n t e g e r a r g - new I n t e g e r ( 1 2 3 4 ) : _______________
Increm entarlO(arg):
S y ste m .o u t .p rin tln (a rg .in tV a lu e ()):
I

El m todo m a in del ejem plo anterior crea un objeto In te g e r con el valor


1 2 3 4 y alm acena una referencia a ese objeto en la variable arg. C uando m a in in
voca a In crem en ta rlo , le pasa una referencia que este m todo alm acena en su pa
rm etro param . El m todo In c rem en ta rlo obtiene el v alo r entero del objeto, lo
increm enta en 10 y crea un nuevo objeto In te g e r con el resultado, alm acenando la
referencia al m ism o en param . Esto sobreescribe la referencia anterior que alm a
cenaba param , pero lgicam ente no afecta a la variable arg, as que el m todo
m a in m ostrar el valor 1 2 3 4 original.

Q u ha sucedido? Q ue el m todo In c re m e n ta rlo no slo no m odific la es


tructura de datos del objeto referenciado por param (ya que valor es una variable
local que no pertenece al objeto), sino que asign a p a ra m un nuevo objeto. Para
poder m odificar el objeto pasado por referencia, la clase In te g e r debera propor
cionar, segn m uestra el ejem plo siguiente, un m todo anlogo a AsignarValor:

public static void I n c r e m e n t a r l o ! I n t e g e r param)


I
i n t v a l o r = p a r a m . i n t V a l u e ( );
v a l o r + = 10:
param .AsignarValor(valor):
I

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:

public static void Increm entarlO (int[] param)


1
param[0] + = 10:

public static void m a in (S trin g [] args)


1
i n t [ ] a r g = I 1234 I ;
Increm entarlO(arg);
S y s t e m . o u t . p r i n t l n ( a r g [ 0 ] ):

En el ejem plo anterior, el m todo m a in define un valor de tipo int m ediante


una m atriz de un solo elem ento. D espus invoca al m todo In c rem en ta rlo pasn
dole com o argum ento esa m atriz, lo que supone copiar la referencia arg en el pa
rm etro param . A hora param hace referencia a la m ism a m atriz que arg. Por lo
tanto, todos los cam bios realizados p o r el m todo afectarn a la m atriz original.
C om o consecuencia, el resultado m ostrado p o r m a in ser ahora 1244.

ARGUMENTOS EN LA LNEA DE RDENES


M uchas veces, cuando invocam os a un program a desde el sistem a operativo, ne
cesitam os escrib ir uno o m s argum entos a continuacin del nom bre del progra
ma, separados p o r un espacio en blanco. P or ejem plo, piense en la orden Is -l del
sistem a operativo UNI X o en la orden clir /p del sistem a operativo M S-DOS.
T anto Is com o d ir son program as; -/ y /p son opciones o argum entos en la lnea de
rdenes que pasam os al program a para que tenga un com portam iento diferente al
q ue tiene de form a predeterm inada; es decir, cuando no se pasan argum entos.

De la m ism a form a, nosotros podem os construir aplicaciones Java que adm i


tan argum entos a travs de la lnea de rdenes Q u m todo recibir esos argu
m entos? El m todo m ain. ya que este m todo es el punto de entrada a la
aplicacin y tam bin el punto de salida. Su definicin, una vez ms, es com o se
m uestra a continuacin:

public static void m a in ( S t r in g [ ] args)


i
// C u e r p o d e l m t o d o
222 JA VA : C U R SO D E PROGRAM A CIN

C om o se puede observar, el m todo m a in tiene un argum ento args q u e es una


m atriz unidim ensional d e tipo S tr in g . El nom bre args puede ser cualquier otro.
Esta m atriz alm acenar los argum entos pasados en la lnea de rdenes cuando se
invoque a la aplicacin para su ejecucin de la form a que se observa a continua
cin. O bserve q ue cada argum ento est separado p o r un espacio.

java M iA plicacin argumentol argumento2 ...

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

El cdigo de la aplicacin propuesta, se m uestra a continuacin.

public class Test


I
public static void m a in (S trin g [] args)
I
// C d i g o comn a t o d o s l o s c a s o s
System .out.println("Argum entos: "):
i f ( a r g s . 1 e n g t h = = 0)
I
// E s c r i b a a q u e l c d i g o q u e s l o se debe e j e c u t a r cuando
// no s e p a s a n a r g u m e n t o s
C A PTU LO 8: M TO D O S 2 2 3

System .out.println" nin g u n o"); 'ip c jc i^ y -to ss-r-*'r-r-rz-f


! v
el se
'! I.l UVI..I l: . u tn.il v - i r -u w n , v /!>- o . u
b o o l e a n a r g u m e n t o _ k ** f a l s e , argumento_l false,
i a r g u m e n t o _ n false:

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

if ( a r g s [ i ] . compareTf" - k " ) 0) argumento_kl - true:


if ( a r g s [ i ] . c o m p a r e T o ( " - l " ) = 0) argumento_l: true:
if ( a r g s [ i ] . c o m p a r e T o t H- n " ) = 0 ) argumento_n - true:
,, ; i., I : iiii v!> p v i u -i: :! ' <r

if (argumento_k) // s i se pas el argumento -k:


I
7 / E s c r i b a aq u el c d i g o que s l o se debe e j e c u t a r cuando
// s e p a s a e l a r g u m e n t o - k
System .out.println" -k");
I

if ( a r g u m e n t o _ l ) // s i se pas el argumento -1:


, .. ::.r . I
II E s c r i b a a q u e l c d i g o q u e s l o se debe e j e c u t a r cuando
// s e p a s a e l a r g u m e n t o -1
System .out.println - l n ):

if (argumento_n) // s i se pas el argumento -n:


I
// E s c r i b a a q u e l c d i g o q u e s l o se debe e j e c u t a r cuando
// s e p a s a e l a r g u m e n t o -n
System .out.p rintlnC -n "):
I
I
// C d i g o comn a t o d o s los casos

Al ejecutar este program a, invocndolo com o se ha indicado anteriorm ente, se


obtendr el siguiente resultado:

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.

C undo es eficaz escribir un m todo recursivo? La respuesta es sencilla,


cuando el proceso a program ar sea por definicin recursivo. P or ejem plo, el cl
culo del factorial de un nm ero, n ! = n (n -I)!, es p o r definicin un proceso recur
sivo que se enuncia as: fa cto ria l(n ) = n * fa c to ria l(n -l)

Por lo tanto, la form a idnea de program ar este problem a es im plem entando


un m todo recursivo. C om o ejem plo, a continuacin se m uestra un program a que
visualiza el factorial de un nm ero. Para ello, se ha escrito un m todo fa cto ria l
que recibe com o parm etro un nm ero entero positivo y devuelve com o resultado
el factorial de dicho nm ero.

public class Test


I
// C l c u l o d e l f a c t o r i a l de un nmero
p u b l i c s t a t i c l o n g f a c t o r i a l ( i n t n)
I
if ( n 0)
r e t u r n 1;
else
return n * f a c t o r i a l ( n - 1 );
1

public static void m a in ( S t r in g [ ] args)


I
i n t numer o :
long fa c:

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 ) :

fac = fa c to ria l(n u m e ro );


System .out.println"\nEl factorial de " + numero + " e s : " + fac):

En la tabla siguiente se ve el proceso seguido por el m todo fa cto ria l, durante


su ejecucin para n = 4.
C A PITU LO 8: M TO D O S 2 2 5

N ivel de recursin P roceso de ida P roceso de vuelta

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.

Los algoritm os recursivos son particularm ente apropiados cuando el problem a


a resolver o los datos a tratar se definen en form a recursiva. Sin em bargo, el uso
de la recursin debe evitarse cuando haya una solucin obvia por iteracin.

En aplicaciones prcticas es im perativo dem ostrar que el nivel m xim o de re


cursin es, no slo finito, sino realm ente pequeo. La razn es que, por cada eje
cucin recursiva del m todo, se necesita cierta cantidad de m em oria para
alm acenar las variables locales y el estado en curso del proceso de clculo con el
fin de recuperar dichos datos cuando se acabe una ejecucin y haya que reanudar
la anterior.

VISUALIZAR DATOS CON FORMATO


Los resultados producidos por las aplicaciones que hem os realizado hasta ahora
han sido m ostrados sin aplicar ningn tipo de form ato. Pero quizs en alguna o ca
sin necesitem os expresar una cantidad:

incluyendo la com a de los decim ales y el punto de los m iles,

con un nm ero determ inado de dgitos enteros com pletando con ceros por la
izquierda si fuera necesario,

con un nm ero determ inado de decim ales y ajustada a la derecha,

o bien una serie de cantidades decim ales, una debajo de otra, ajustadas por la
com a.

Si en lugar de cantidades hablam os de fechas, tam bin podram os requerir


diferentes m odos de presentacin.
226 JA VA : C U R SO D E PRO G R A M A CI N

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

La clase N u m b e r F o r m a t es la clase base abstracta para todos los form atos


num ricos. La clase D a te F o rm a t es tam bin una clase abstracta para los form atos
de fechas y horas. Pero las clases que son particularm ente tiles y que estudiam os
a continuacin son: D e c im a lF o rm a t. S im p le D a t e F o r m a t y M e s sa g e F o rm a t.

Dar formato a nmeros

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

% M ultiplicar p o r 100 y m ostrar el sm bolo %.


a R epresenta el sm bolo m onetario.
carcter C u alquier carcter puede ser utilizado com o prefijo o com o sufijo.
P o r ejem plo $ o \u 0 0 2 4 \

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

Si el nm ero de dgitos correspondiente a la parte entera excede el nm ero de


posiciones especificado para la m ism a, el form ato se extiende en lo necesario. Si
el nm ero de dgitos decim ales excede el nm ero de posiciones especificado para
los m ism os, la parte decim al se trunca redondeando el resultado.

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):

El m todo g e tC u rre n c y ln sta n c e devuelve el form ato m onetario de la locali


dad actual cuando no se especifica una, o el de la especificada. Por ejem plo:

L c a l e e n _ U S = new L o c a l e ( e n " . " U 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 l n s t a n c e ( e n _ U S ) ;

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

U na localidad no es un idiom a, ya que un m ism o idiom a se puede hablar en varios


pases. C uando escriba un program a internacional tendr que definir la localidad
228 JA VA: C U R SO D B PROGRAM A CIN

actual y el conjunto de localidades que soportar el program a. Las localidades son


definidas en Java por la clase L c a le incluida en el paquete java.u til. Un objeto
de la clase L c a le es sim plem ente un identificador para una localidad especfica.
P or ejem plo, el siguiente cdigo crea dos objetos. p a(s[0] y p a s[], uno para el
espaol de E spaa y otro para el ingls de Estados Unidos.

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;

U tilizando los m todos com entados en el apartado anterior, se puede obtener


el form ato predeterm inado para cualquiera de estos pases. Por ejem plo:

Deci mal Formal d f =


(Deci mal Fo r ma l ) De c i ma l Fo r ma t . g e t Nu mb e r I n s t a n c e ( p a i s [ 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);

Para utilizar el objeto F ie ld P o sitio n definido, el m todo fo rm a t invocado a


travs del objeto form ateador debe ten er tres parm etros: el valor num rico a for
m atear, un objeto S t r in g B u ff e r donde se alm acenar el nm ero form ateado y el
objeto F ie ldP ositio n . Para realizar la alineacin habr que aadir al principio del
objeto S t r in g B u ff e r un nm ero de espacios en blanco igual al espacio d e im pre
sin deseado m enos el valor devuelto por g e tE n d ln d e x .

Q u devuelve g e tE n d ln d e x ? Si el objeto F ie ld P o sitio n se cre basado en la


constante IN T E G E R _F IE L D , el m todo g e tE n d ln d e x devolver el nm ero de d
gitos enteros del dalo a form atear, y si se cre basado en la constante FRAC-
T IO N _F IE L D , el nm ero total de dgitos (enteros y decim ales). Para aclarar lo
expuesto observe el siguiente ejem plo, continuacin del anterior:
C A PTU LO 8: M TO D O S 2 2 9

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 . ' ') ;

Una vez estudiado cm o d ar form ato a un nm ero, el objetivo siguiente es es


cribir una clase O btener que proporcione varios m todos que perm itan obtener
cualquier nm ero en alguno de los form atos que considerem os m s com unes.
Posteriorm ente, podrem os utilizar esta clase com o soporte en otras aplicaciones.

Clase para formatos numricos

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:

F orm atoLocal. D evuelve la cadena resultante de form atear un nm ero utili


zando el form ato m onetario predefinido en el pas actual.

F orm atoPer. D evuelve la cadena resultante de form atear un nm ero con un


form ato personalizado. Los sm bolos de puntuacin utilizados son los corres
pondientes al pas actual.

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

static public String Form atoPertString patrn, double dato)


I
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 t p a t r n ) ;
S trin g salida = form ato.form at(dato):
return sa lid a:
I
2 3 0 JA V A: C U R SO D E PROGRAM A CIN

static public StringBuffer A linD er(String patrn, double dato)


I
F i e ld P o s i t i o n fp =
new F i e l d P o s i t i o n ( N u m b e r F o r m a t . F R A C T 1 0 N _ F I E L D ) ;
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 ( p a t r n ) ;
S t r i n g B u f f e r s a l i d a = new S t r i p g B u f f e r t );
form ato.form aUdato. sa lid a , fp);
f o r ( i n t i = 0; i < ( p a t r n .1e n g t h ( ) - f p . g e t E n d l n d e x ) ) ; i++)
sal i d a . i n s e r t ( 0 . ");
return sa lid a;
1

static public String Form atoPa1s(String patrn, double dato.


,... L c a l e , l u g a r )
i ;.. 'y'
Decim alFormat d f =
... . y . . : , , ; /.'V;Vr
( D e c i m a l F o r m a t ) D e c i m a l F o r m a t . g e t N u m b e r I n s t a n c e ( 1 u g a r );
d f . a p p l y P a t t e r n ( p a t r n );
S t r i n g s a l i d a = d f . format-(dato.-)';,
return sal id a ;

P u e d e , si lo desea, a a d ir esta c la se a la carp eta e sp e c ific a d a p o r la va ria b le


d e e n to rn o C L A S S P A T H . A c o n tin u a c i n e s c r ib im o s u n a a p lic a c i n q u e n o s per
m ita p ro b a r ca d a u n o d e lo s m t o d o s d e la c la s e anterior.

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

C om o ejercicio, ejecute esta aplicacin y analice los resultados.

Dar formato a fechas/horas


Para dar form ato a una fecha/hora dada, prim ero hay que crear un objeto forma-
teador de la clase S im p le D a t e F o r m a t basado en un form ato especfico, y luego
u tilizar su m todo fo rm a t para convertir la fecha/hora en una cadena construida a
p artir del form ato elegido. Los sm bolos que se pueden u tilizar para especificar un
determ inado form ato son:

Sm bolo Significado_____________ Presentacin____________Ejem plo__________


y ao num rica 2002
M m es del ao num rica y alfabtica 08 y agosto
d da del m es num rica 15
ii hora (1 a 12) num rica 10
H hora (0 a 23) num rica 13
m m inutos num rica 30
s segundos num rica 55
S m ilisegundos num rica 658
E da de la sem ana alfabtica jueves
D da del ao num rica 227
- da de la sem ana del m es num rica 3 (3o X de agosto)
w sem ana del ao num rica 24
W sem ana del m es num rica 2
3 m arca am /pm alfabtica PM
Z zona horaria alfabtica G M T+02:00

En las presentaciones alfabticas, 4 o m s sm bolos dan lugar a la forma


com pleta (por ejem plo, M M M M da lugar al nom bre del m es com pleto: agosto)-, y
232 JAVA: C U R S O DE PROGRAM A CIN

m enos de 4 da lugar a la form a abreviada o a la num rica (por ejem plo, M M M da


lugar a una abreviatura, ago, M M a un nm ero de dos dgitos, 08, y M a un nm e
ro de un dgito, 8).

En las presentaciones num ricas un sm bolo da lugar al m nim o nm ero de


dgitos. P o r ejem plo si yy yy d a lugar a 2002, y , yy, o y y y dan lugar a 02.

C ualquier otro carcter fuera de los rangos [A ..Z ] y [a \ . z ] ser tratado


com o un separador.

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 ):

Un objeto Date, construido sin argum entos, encapsula el tiem po en milise-


gundos transcurridos desde el 1 de enero de 1970.

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

o bien con el estilo y la localidad; por ejem plo:


CA PTU LO 8: M TODOS 2 3 3

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

donde p a s es un objeto L c a le segn se explic anteriorm ente en el apartado


L ocalidad .

Dar formato a mensajes


Para d ar form ato a un m ensaje que se desea construir durante la ejecucin, com o
p o r ejem plo "Fueron verificados 1234 ficheros de la unidad C: en 125 segundos ,
hay que crear un objeto form ateador de la clase M e s sa g e F o rm a t. Esta clase pro
porciona un m edio para construir m ensajes con partes variables que sern reem
plazados durante la ejecucin. P or ejem plo:

Object[] argumentos = (new L o n g ( 1 2 3 4 ) , " C : . new L o n g ( 1 2 5 ) 1 :

M e s s a g e F o r m a t m e n s a j e = new M e s s a g e F o r m a t ! " F u e r o n v e r i f i c a d o s " +


" 1 0 1 f i c h e r o s d e l a u n i d a d I I I en 12 I s e g u n d o s " ) :
Syste m .o u t.p rin tln (m e n sa je .fo rm a t(a rg u m e n to 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:

int b i n a r y S e a r c h ( tipo[] m, t ipo clave)

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.

El valor devuelto es un entero correspondiente al ndice del elem ento que


coincide con el valor buscado. Si el valor buscado no se encuentra, entonces el
valor devuelto es: -(p u n to de insercin) - 1. El valor de punto de insercin es el
234 JA VA : C U R S O DE PROGRAM A CIN

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.

C om o ejem plo, analice el siguiente cdigo:

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:

b o o l e a n e q u a l s tipo[] mi. t i p o ] m2)

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

void fiH (t?p o[] m, t i p o v a l o r )


void fill(tp o [] m, i n t d e s d e l n d . int hastalnd, tipo valor)

donde m es la m atriz y valor es el valor a asignar. C uando slo queram os asignar


el valor a un rango de elem entos, utilizarem os el segundo form ato de ll donde
d esd eln d y h a stalnd definen ese rango, tipo es cualquier tipo d e datos de los si
guientes: boolean. byte, char, short, int. long. float, d o u b le y O bject.

Un ejem plo de cm o utilizar este m todo es el siguiente:

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)

donde m es la m atriz a ordenar. C uando slo queram os ordenar un rango de ele


m entos, utilizarem os el segundo form ato de so rt donde d esd e ln d y hastalnd defi
nen los lm ites de ese rango, tipo es cualquier tipo de datos de los siguientes:
byte, ch ar, short, int, long, float, d o u b le y O bject.

C om o ejem plo, puede probar los resultados que produce el siguiente cdigo:

doub le[] a = 155.50.45.40.35.30.25.20.15.10):


A r r a y s . s o r t ( a ):

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

g e tC la ss y clone, los hem os utilizado en captulos anteriores; y otros, com o


equals, to S tr in g y finalize son expuestos a continuacin.

boolean equals(Object obj)


El m todo e q u a ls de la clase O b je c t retorna tru e si y slo si las dos referencias
com paradas sealan al m ism o objeto; esto es, proporciona el m ism o resultado que
el operador Esto es as porque la intencin es proporcionar un m todo que
pueda ser sobreescrito en cada una de las subclases de O b je c t que requieran una
funcionalidad m s especfica. Por ejem plo, considerem os el siguiente cdigo que
define dos referencias a otros dos objetos de la clase S trin g :

public class Test


I
public static void m a in (S trin g [] args)

S t r i n g s t r l - new S t r i n g ( " a b e " );


S t r i n g s t r ? = new S t r i n g t " a b e " ) :
/ / Comparar r e f e r e n c i a s
if (strl str2)
S y s t e m . o u t . p r i n t l n " L a s r e f e r e n c i a s s o n al mismo o b j e t o " ) ;
el se
S y s t e m . o u t . p r i n t l n t " L a s r e f e r e n c i a s s on a o b j e t o s d i f e r e n t e s " ) ;
/ / Comparar c o n t e n id o s
i f ( s t r l . e q u a 1s ( s t r 2 ))
S y s t e m . o u t . p r i n t n ( " M i s m o c o n t e n i d o " );
el se
S y s t e m . o u t . p r i n t l n ( " D i f e r e n t e c o n t e n i d o " ):
I
1

La expresin s tr l == str2 ser true si la referencia s tr l es igual a la referen


cia str2\ esto es, si am bas variables contienen idnticos valores, los cuales se c o
rrespondern con la posicin de m em oria donde se localice un objeto.

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.

C uando se ejecute la aplicacin anterior se obtendr el siguiente resultado:

Las r e f e r e n c i a s son a o b je to s diferentes


Mismo c o n t e n i d o
CA PTU LO 8: M TO D O S 2 3 7

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

El ejem plo siguiente perm ite verificar lo expuesto.

public class Test


I
public static void m a in (S trin g [] args)
I
T e s t o b j = new T e s t ( ):
S t r i n g s:
s - 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 )):
System .out.p rintln(s):
S y s t e m . o u t . p r i n t l n ( o b j . t o S t r i n g ( ) ) ; // mi s mo r e s u l t a d o que s
I
I

C uando se ejecute el ejem plo anterior la lnea som breada dar lugar al si
guiente resultado:

Test@73bf4fel

C on respecto al m todo t o S tr in g direm os lo m ism o que para equals; esto es,


todas las subclases de O b je c t deberan sobreescribir el m todo to S tr in g para que
proporcione una inform acin que sea til. P or ejem plo, la clase S t r in g sobrees-
cribe este m todo para que retom e el propio objeto S t r in g que recibe el m ensaje
to Strin g.

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.

El m todo finalize de la clase O b je c t no ejecuta ninguna accin en especial;


sim plem ente retorna norm alm ente. Las subclases de O b je c t debern sobreescribir
la definicin de este m todo slo cuando necesiten ejecutar alguna operacin de
finalizacin especial.
238 JA V A : C U R S O DE PRO G R A M A CI N

MS SOBRE REFERENCIAS Y OBJETOS String


En el captulo anterior hicim os una breve exposicin acerca d e cm o crear un
objeto S t r in g a partir de un literal o a partir d e o tro S trin g . Por ejem plo:

Strin g str = "abe";

Este ejem plo crea un objeto S t r in g con el contenido abe . D icho proceso
puede realizarse tam bin as:

String s t r = new S t r i n g ( " a b e " ):

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 .

C ada literal de caracteres es representado internam ente por un objeto Strin g .


A s m ism o. Java m antiene un rea de m em oria destinada a alm acenar tales objetos
S trin g . Entonces, cuando Java com pila un literal (en el ejem plo abe ) aade el
objeto S t r in g correspondiente, a dicho rea de m em oria; posteriorm ente, si apare
ce el m ism o literal en cualquier otra parte del cdigo de la clase, el com pilador no
aade un nuevo objeto, sino que utiliza el que hay. E sta form a de proceder ahorra
m em oria y no causa problem as porque los S t r in g son objetos no m odificables;
p o r lo tanto, no hay posibilidad de que una parte del cdigo pueda m odificar un
objeto S t r in g com partido por otra parte de cdigo.

A nteriorm ente en este captulo, vim os cm o utilizar el m todo e q u a ls para


verificar los contenidos de dos objetos S trin g . Tam bin vim os que, a diferencia
del m todo equals, el operador = = no com para los contenidos de los objetos refe-
renciados sino las referencias. E sto nos perm itir analizar m ediante algunos ejem
plos lo expuesto en el prrafo anterior:

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

En cam bio, el resultado de la expresin s tr l = = str2 es true porque am bos


identificadores se refieren al m ism o objeto. A nalicem os p o r qu.

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.

D urante la ejecucin, la prim era lnea alm acena en s t r l una referencia al ob


jeto que ya existe en el rea de m em oria destinada por el com pilador a objetos
S tr in g ; y la segunda lnea alm acena en str2 una referencia al m ism o objeto. La fi
gura siguiente m uestra esto grficam ente:

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.

D urante la ejecucin, la prim era lnea construye un nuevo objeto S t r in g du


plicando el existente en el rea de m em oria citada y alm acena una referencia al
mismo en s tr l. En cam bio, la segunda lnea sim plem ente alm acena en str2 una
referencia al objeto que ya existe en el rea de m em oria destinada por el com pila
dor a objetos S tr in g . La figura siguiente m uestra esto grficam ente:
240 JA V A: C U R SO D E PROGRAM A CIN

N o obstante, es posible colocar los objetos S t r in g creados dinm icam ente


(objetos creados durante la ejecucin m ediante el operador new ) en el espacio de
m em oria reservado por el com pilador Java para tales objetos utilizando su m todo
intern. Esto puede redundar en un ahorro de m em oria en program as que utilicen
una gran cantidad de objetos S trin g . P o r ejem plo, las lneas de cdigo siguiente:

S t r i n g s t r l = new S t r i n g t " a b e " ) : // c r e a r un n u e v o o b j e t o


s t r l = s t r l . i n t e r n ( ):
Strin g str2 = "abe :

son equivalentes a:

String s trl - "abe ;


S t r i ng s t r 2 - "abe":

El m todo in te rn coloca el objeto que recibe el m ensaje in te rn en el espacio


de m em oria reservado p o r el com pilador Java para los objetos S t r in g si an no
estaba, o si estaba lo reutiliza.

Finalm ente, es im portante recordar que cuando un m todo acta sobre un ob


je to S t r in g el resultado es un nuevo objeto lo que m antiene intacto el objeto ori
ginal. Por ejem plo:

strl = s t r l .re p la c e t'a ', x ):

Partiendo de que s tr l era el S t r in g abe, despus de ejecutarse la lnea de


cdigo anterior se genera un nuevo objeto xbc referenciado por s tr l. Esto hace
que el objeto referenciado por str2. que antes de la ejecucin era el m ism o que el
referenciado por s tr l, perm anezca inalterado. El nuevo objeto generado no se
aadir al espacio reservado para los objetos S t r in g a no ser que se invoque ex
plcitam ente al m todo intern.

EJERCICIOS RESUELTOS

1. Un algoritm o que genere una secuencia aleatoria o aparentem ente aleatoria de


nm eros, se llam a generador de nm eros aleatorios. M uchos program as requieren
C A PTU LO 8: M TODOS 2 4 1

de un algoritm o com o ste. El algoritm o m s com nm ente utilizado para generar


nm eros aleatorios es el de congruencia lineal que se enuncia de la form a si
guiente:

rk = (m ultiplicador * rk. + increm ento) % m dulo

donde se observa que cada nm ero en la secuencia rk, es calculado a partir de su


predecesor rk., (% es el operador m dulo o resto de una divisin entera). La se
cuencia, as generada, es llam ada m s correctam ente secuencia seudoaleatoria, ya
que cada nm ero generado, depende del anteriorm ente generado.

El m todo r a n d o m de la clase M a t h del paquete ja v a .la n g, o bien los m to


dos de la clase R a n d o m del paquete ja v a .u til estn basados en este algoritm o.

El siguiente m todo utiliza el algoritm o d e congruencia lineal para generar un


nm ero aleatorio entre 0 y 1, y no causar sobrepasam iento en un ordenador que
adm ita un rango de enteros de -2 31 a 2 3l- i .

public static double rnd(in t[] raridom)


I
randomO] = (25173 * randomO] + 13849) % 65536:
return ( (double)random [0] / 65535):
I

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.

El siguiente program a m uestra com o utilizar el m todo rnd para generar n


m eros seudoaleatorios entre 0 y 1:

import j a v a . u t i 1 . * :

public class CRandom


I
7/ N me r o s a l e a t o r i o s e n t r e 0 y 1
p u b l i c s t a t i c d o u b l e r n d ( i n t [ ] ran do m)
I
randomO] = (25173 * randomO] + 13849) X 65536:
r e t u r n ( ( d o u b l e ) randomO] / 6 5535):
242 JA V A: C U R SO DE PROGRAM A CIN

public static void m a in ( S t r in g [ ] args)


I
i n t i n i c i o = ( i n t ) ( ( n e w D a t e ( ) ) . g e t T i m e ( ) % 6 5 5 3 6 ): // s e m i l l a
i n t [ ] rando m = ( i n i c i o ) : II r a n d o m = nm ero e n t r e 0 y 65535

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

2. U tilizando el m todo ra n d o m de la clase M a t h del paquete ja v a .la n g, realizar un


program a que m uestre 6 nm eros aleatorios diferentes entre 1 y 4 9 ordenados as
cendentem ente.

Para producir enteros aleatorios en un intervalo dado puede u tilizar la frm u


la: P arte_entera_de((lm iteSup lm ite ln f + l ) * random + lm itelnf).

La solucin al problem a planteado puede ser de la siguiente forma:

D efinim os el rango de los nm eros que deseam os obtener, as com o una m a


triz para alm acenar los 6 nm eros aleatorios.

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;

O btenem os el siguiente nm ero aleatorio y verificam os si ya existe en la m a


triz, en cuyo caso lo desecham os y volvem os a obtener otro. E ste proceso lo
repetirem os hasta haber generado todos los nm eros solicitados.

for (i =0; i < n.length; i++)


I
CA PTU LO 8: M TODOS 2 4 3

n[i ] - ( i n t ) ( ( 1 1miteSup - l i m i t e l n f + 1) * M ath. random() +


1i m i t e l n f ) ;
f o r ( k = 0; k < i ; k + + )
i f <n [ k ] = = n [ i ] ) II ya e x i s t e
I
i - -:
break:

L a sentencia fo r externa define cuntos nm eros se van generar. C uando se


genera un nm ero se alm acena en la siguiente posicin de la m atriz. Despus,
la sentencia fo r interna com para el ltim o nm ero generado con todos los
anteriorm ente generados. Si ya existe, se decrem enta el ndice i de la matriz
para que cuando sea increm entado de nuevo por el fo r externo apunte al ele
m ento repetido y sea sobreescrito p o r el siguiente nm ero generado.

U na vez obtenidos todos los nm eros, ordenam os la m atriz y la visualizam os.

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] + "):

E l program a com pleto se m uestra a continuacin.

import j a v a .u t i 1 .*;

public class C Ra ndo mJ a v a


1
// O b t e n e r n m e r o s d e n t r o de un r a n g o
pu b lic s t a t ic void m a in (S trin g [] args)
I
in t llm ite Su p = 49, l i m i t e l n f = 1;
i n t n [ ] = new i n t [ 6 ] , i . k:

for (i - 0; i < n.length; 1++)


I
II O b t e n e r un nmero a l e a t o r i o
n [ i ] - ( i n t ) ( ( 1 1 m i t e S u p - l i m i t e l n f + 1) * M a t h . r a n d o m ) +
lim itelnf);
II V e r i f i c a r s i ya e x i s t e e l l t i m o n m ero o b t e n i d o
f o r ( k = 0; k < i ; k++)
i f ( n [ k ] = = n [ i D ) // y a e x i s t e
I
i--; II i s e r i n c r e m e n t a d a p o r e l for externo
break; II s a l i r de e s t e f o r
I
244 JA V A: C U R SO DE PRO G R A M A CI N

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

3. R ealizar un program a que partiendo de dos m atrices de cadenas de caracteres


clasificadas en orden ascendente, construya y visualice una tercera m atriz tambin
clasificada en orden ascendente. L a idea que se persigue es construir la tercera
lista clasificada; no construirla y despus clasificarla em pleando el m todo so rt.

Para ello, el m todo m a in proporcionar las dos m atrices e invocar a un


m todo cu y o prototipo ser el siguiente:

int Fusionar(String[] listal. Strin g[] 1 i s t a 2. Strin gf] lista3);

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.

El proceso de fusin consiste en:

a) Partiendo de que y a estn construidas las dos m atrices de partida, tom ar un


elem ento de cada una de las m atrices.

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

d) C uando no queden m s elem entos en una de las dos m atrices de partida, se


copian directam ente en la m atriz resultado, todos los elem entos que queden en
la otra m atriz.

El program a com pleto se m uestra a continuacin.

public class CFusionarListas


I
// F u s i o n a r d o s l i s t a s c l a s i f i c a d a s
public s t a t ic in t F u sio n a r(S trin g [] listaA, StringC ] listaB .
Strin g[] listaC)
C A P T U L O 8: M TODOS 2 4 5

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

fo r (ind = indB; i nd < 1 i s t a B . 1 e n g t h ; in d + + )


1istaC[indC++] - 1i staBC i n d ] :

return 1;

static p u b lic void m a in (S trin g [] args)


I
// I n i c i a m o s l a s l i s t a s a c l a s i f i c a r ( p u e d e s u s t i t u i r e s t e
// p r o c e s o , p o r o t r o de l e c t u r a c o n e l f i n de t o m a r l o s
// d a t o s de l a e n t r a d a e s t n d a r ) .
S t r i n g [ ] l i s t a l - I "A n a ". "Carmen". " D a v id " .
"Francisco". "Ja v ie r". "Jess",
"Jos", "Josefina". "L u is".
" M a r a . " P a t r i c i a . " S o n i a " I:

StringC ] lista2 - I "A g u stn ", "Beln". "D aniel".


"Fernando". "Manuel".
" P e d r o " . " R o s a " . " S u s a n a " I;

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

O bserve que el m todo F usionar copia referencias. C om o se expuso ante


riorm ente en este m ism o captulo, esta form a de proceder ahorra m em oria y no
causa problem as porque los S trin g son objetos no m odificables; por lo tanto, no
hay posibilidad de que una parte del cdigo pueda m odificar un objeto S trin g
com partido por o tra parte d e cdigo.

4. E scribir un program a que calcule la serie:

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:

a) E scribir un m todo que tenga el siguiente prototipo:

static double e x p o n e n c ia l( f l o a t x);

Este m todo devolver com o resultado el v alor aproxim ado de ex.

b) E scribir el m todo m a in para que invoque al m todo exponencial y com prue


be q ue para x igual a 1 el resultado es el nm ero e .

El program a com pleto se m uestra a continuacin.

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

public static void m a in (S trin g [] args)


I
d o u b l e ex p . x:
S y s t e m . o u t . p r i n t t " V a l o r de x : " ) ; x = L e e r . d a t o F l o a t t ):
exp = e x p o n e n c i a l ( x ) :
S y s t e m . o u t . p r i n t n ( " e x p t " + x + ") = " + exp):

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

U na vez finalizada la introduccin de las listas de palabras pasam os al m odo tra


duccin, de form a que si tecleam os g ree n , la respuesta ha de ser verde. Si la pala
bra no se encuentra se em itir un m ensaje que lo indique.

El program a constar al m enos de dos m todos:

a) crearD iccionario. Este m todo crear el diccionario.


b) traducir. E ste m todo realizar la labor de traduccin.

2. Un cuadrado m gico se com pone de nm eros enteros com prendidos entre 1 y n 2,


donde n es un nm ero im par que indica el orden de la m atriz cuadrada que con
tiene los nm eros que form an dicho cuadrado m gico. La m atriz que form a este
cuadrado m gico, cum ple que la sum a de los valores que com ponen cada fila, ca
da colum na y cada diagonal es la misma. Por ejem plo, un cuadrado m gico de or
den 3. im plica un valor de n = 3 lo que dar lugar a una m atriz de 3 por 3. Por lo
tanto, los valores de la m atriz estarn com prendidos entre 1 y 9 y dispuestos de la
form a siguiente:
248 JA V A: C U R SO DE PROGRAM A CIN

8 1 6
3 5 7
4 9 2

R ealizar un program a que visualice un cuadrado m gico de orden im par n. El


program a verificar que n es im par y que est com prendido entre 3 y 15.

U na form a de construirlo puede ser: situar el nm ero 1 en el centro de la primera


lnea, el nm ero siguiente en la casilla situada encim a y a la derecha, y a s sucesi
vam ente. E s preciso tener en cuenta que el cuadrado se cierra sobre s m ism o, esto
es, la lnea encim a de la prim era es la ltim a y la colum na a la derecha de la lti
ma es la prim era. S iguiendo esta regla, cuando el nm ero caiga en una casilla
ocupada, se elige la casilla situada debajo del ltim o nm ero situado.

Se debern realizar al m enos los m todos siguientes:

a) eslm par. E ste m todo verificar si n es im par.


b) cuadradoM gico. Este m todo construir el cuadrado m gico.

3. R ealizar un program a que:

a) Lea dos cadenas de caracteres denom inadas c a d e n a l y cadena2 y un nmero


entero n.

b) L lam e a un mtodo:

static int c o m p c a d s c a d e n a l. cadena2, n );

que com pare los n prim eros caracteres de c a d e n a l y de cadena2, y devuelva


com o resultado un valor entero:

0 si ca d e n a l y cadena2 son iguales


1 si ca d e n a l es m ayor q ue c a d e n a l (los n prim eros caracteres)
-1 si ca d e n a l es m enor q ue cadena2 (los n prim eros caracteres)

Si n es m enor que 1 o m ayor que la longitud de la m enor de las cadenas, la


com paracin se har sin tener en cuenta este parm etro.

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:

static void lee rM atriz2D (float[][] m):

El parm etro m del m todo leerM atrz2D es la m atriz cuyos elem entos deseam os
leer.

static float[] sum aColsM atriz2D(float[][] m);

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.

5. Escribir un program a para evaluar la expresin (ax + b y f . Para ello, tenga en


cuenta las siguientes expresiones:

[k) k\ (n k)\

/?! = /? * ( / ? - ! ) * ( - 2 )*...*2 * 1

a) E scribir un m todo cuyo prototipo sea:

static long f a c t o r ia l( int n);

El m todo fa cto ria l recibe com o parm etro un entero y devuelve el factorial
del m ism o,

b) Escribir un m todo con el prototipo:

static long com binaciones( int n. int k);

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

c) E scribir un m todo que tenga el prototipo:

static long potencia(int base, i n t exponente):


250 JA V A: C U R SO D E PROGRAM A CIN

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.

d) El m todo m a in leer los valores de a, b, n , x e y , y utilizando los m todos


anteriores escribir com o resultado el valor de (a x + b y )".
PARTE

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.

DEFINICIN DE UNA CLASE

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.

Segn hem os aprendido, la definicin de una clase consta de dos partes: el


nom bre de la clase precedido por la palabra reservada class. y el cuerpo de la cla
se encerrado entre llaves. Esto es:

class nom bre je ta s e


{
cuerpo de la clase
)
254 JA V A: C U R SO DE PRO G R A M A CI N

El cuerpo de la clase en general consta de m odificadores de acceso (public,


p ro te c te d y p rv a te ), atributos, m ensajes y m todos. Un m todo im plcitam ente
define un m ensaje (el nom bre del m todo es el m ensaje).

Por ejem plo, un crculo puede ser descrito p o r la posicin x , y de su centro y


por su radio. H ay varias cosas que nosotros podem os hacer con un crculo: cal
cular la longitud de la circunferencia, calcular el rea del crculo, etc. C ada cr
culo es diferente (por ejem plo, tienen el centro o el radio diferente); pero visto
com o una clase de objetos, el crculo tiene propiedades intrnsecas que nosotros
podem os agrupar en una definicin. El siguiente ejem plo define la clase Crculo.
O bservar cm o los atributos y los m todos form an el cuerpo 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 longCircunferencia()


I
return 2 * Math.PI * radio;

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.

Es posible asignar un valor inicial a un atributo de una clase. P or ejem plo, en


la clase C rculo podem os iniciar el radio con el valor 1, aunque generalm ente esto
no se hace, ya q ue com o expondrem os un poco m s adelante este tipo de opera
ciones son tpicas del constructor de la clase:

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:

Punto(double ex. double cy) I x = ex; y = cy; I


256 JA V A: C U R SO DE PROGRAM A CIN

class Circulo

p r i v a t e Punto cen tro: II 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 : // r a d i o d e l c i r c u l o
11...
I

El orden de las clases es indiferente. E sta form a de proceder ya ha sido utili


zada en captulos anteriores. Recuerde, por ejem plo, que en m s de una ocasin
hem os declarado un atributo de la clase S trin g .

Mtodos de una clase


Los m todos generalm ente form an lo que se denom ina interfaz o m edio de acceso
a la estructura interna de los objetos; ellos definen las operaciones que se pueden
realizar con sus atributos. D esde el punto de vista de la PO O , el conjunto de todos
estos m todos se corresponde con el conjunto de m ensajes a los que los objetos de
una clase pueden responder.

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

public double IongC ircunferencia()


I
return 2 * Math.PI * radio:
I
11...
C A P T U L O 9: CL A SES Y PAQUETES 2 5 7

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.

Control de acceso a los miembros de la clase

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:

1. Q ue el usuario no tenga acceso directo a la estructura de datos interna de la


clase, para que no pueda generar cdigo basado en esa estructura.

2. Que si en un m om ento determ inado alteram os la definicin de la clase, ex


cepto el prototipo de los m todos, todo el cdigo escrito por el usuario basado
en estos m todos no tendr que ser retocado.

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

En m uchos de los ejem plos realizados en los captulos anteriores, no se ha espe


cificado ningn tipo de control de acceso. Esto es, los atributos y los m todos se
declararon de form a anloga a com o puede observar en el ejem plo siguiente:

class CRacional
I
i n t Numerador:
i n t Denominador:

v o i d A s i g n a r D a t o s f i n t num, int den)


I
258 JA V A: C U R SO D E PROGRAM A CIN

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.

C om o se puede observar este tipo de control de acceso no tiene m ucho dom i


nio sobre el m ism o. Si lo que se pretende es tener un control preciso sobre cm o
va a ser utilizada nuestra clase por otras, deberem os utilizar los m odificadores
p rv a te , p ro te c te d o p u b lic en vez de aceptar el tipo de control predeterm inado.

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

IMPLEMENTACIN DE UNA CLASE


L a program acin orientada a objetos sugiere separar la im plem entacin de cada
clase en un fichero .class, fundam entalm ente para posteriorm ente reutilizar y
m antener dicha clase. C om o ejem plo, disearem os una clase que alm acene una
fecha, verificando que es correcta; esto es, que el da est entre ios lm ites 1 y das
del m es, que el m es est entre los lm ites 1 y 12 y que el ao sea m ayor o igual
que 1582.

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:

public class C Fech a


I
// A t r i b u t o s
p r i v a t e i n t d 1 a . mes . ao:

// 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:

public void a sig n a rF e c h a d n t dd , i n t mm, int aaaa)


I
d i a = dd ; mes = mm: a o = a a a a :
)

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 .

S iguiendo las reglas enunciadas, finalizarem os el diseo de la clase escribien


do el resto de los m todos. El resultado que se obtendr ser la clase C Fecha que
se observa a continuacin:

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

public void a s i g n a r F e c h a ( i n t dd . i n t mm. int aaaa)


I
dia = dd : mes = mm: a o - aaaa:
I

public void obte nerFecha (int[] fecha)


I
fe c h a [0] = di a :
f e c h a [ l ] = mes ;
f e c h a [ 2 ] = ao:

public boolean fe c h a C o rre c ta )


I
boolean d ia C o r re c t o . mesCorrecto. aoCorrecto:
// a o c o r r e c t o ?
a o C o rre c to = (ao >- 1582):
// m e s c o r r e c t o ?
m e s C o r r e c t o = (m es >= 1) && (mes < = 1 2 ) :
s w i t c h (mes)
// d i a c o r r e c t o ?
I
c a s e 2:
if (bisiestoO )
diaCorrecto - (dia >= 1 && d a <= 2 9 ) :
el s e
diaCorrecto = (dia >= 1 && d i a <= 2 8 ) :
break:
c a s e 4 : c a s e 6: c a s e 9: c a s e 11:
diaCorrecto = ( d a > - 1 && d a <= 30 ):
break:
default:
diaCorrecto = (da > = 1 && d i a <= 31):
I
return d i a C o r r e c t o && m e s C o r r e c t o && a o C o r r e c t o ;
1
I

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

El m todo pblico fech a C o rrecta verifica si la fecha que se desea asignar al


objeto que recibe este m ensaje es correcta. E ste m todo devuelve true si la fecha
es correcta y false en caso contrario.

El m todo protegido bisiesto verifica si el ao de la fecha que se desea asig


n ar al objeto que recibe este m ensaje es bisiesto. E ste m todo retorna true si el
ao es bisiesto y false en caso contrario.

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:

public int read()


public int read(byte[] b)
public int read(byte[] b, i n t off. int len)

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:

public void p r i n t ( i n t ;')


public void p r i n t ( d o u b l e d)
public void p r i n t ( c h a r [ ] s)

En qu se diferencian los m todos r e a d ? E n su nm ero d e parm etros. Y,


en qu se diferencian los m todos p rin t expuestos? En el tipo de su parm etro.

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.

La sobrecarga de m todos elim ina la necesidad de definir m todos diferentes


que en esencia hacen lo m ism o, com o es el caso del m todo p rin t, o tam bin hace
posible que un m todo se com porte de una u otra form a segn el nm ero de ar
gum entos con el que sea invocado, com o es el caso del m todo read.
CA PTU LO 9: CL A SES Y PAQUETES 2 6 3

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.

L a fecha actual del sistem a se puede obtener a partir de un objeto de la clase


G r e g o r ia n C a le n d a r , q ue es una subclase de C a le n d a r , del paquete java.u til. La
clase C a le n d a r es una clase abstracta que proporciona una serie de constantes ta
les com o D A Y_O F _M O N TH , M O N T H o YEAR que podem os u tilizar com o argu
m ento en el m todo get para obtener el dato al que alude.

public void asignarFecha)


I
// A s i g n a r , p o r o m i s i n , l a f e c h a a c t u a l .
G r e g o r i a n C a l e n d a r f e c h a A c t u a l = new G r e g o r i a n C a l e n d a r ( ):
di a = f e c h a A c t u a l , g e t ( C a l e n d a r . D A Y _ O F _ M O N T H ) :
mes = f e c h a A c t u a l . g e t C C a l e n d a r . H 0 N T H 1 + 1 :
ao = f e c h a A c t u a l . g e t t C a l e n d a r . Y E A R ) ;
I

public void a s i g n a r F e c h a t i n t dd)


1
a s i g n a r F e c h a ( );
d 1 a = dd:
I

public void a sig n a rF e c h a in t dd. i n t mm)


I
a s i g n a r F e c h a ( );
d i a = d d : mes = mm;
I

public void asignarFechaint dd. i n t mm, int aaaa)


I
d 1 a = dd : mes = mm: a o = a a a a ;
I

C om o se puede observar, el que una definicin del m todo invoque a otra es


una tcnica de m todo abreviado que da com o resultado m todos m s cortos.

P o r cada llam ada al m todo asignarF echa que escribam os en un program a, el


com pilador Jav a debe resolver cul de los m todos con el nom bre asignarFecha
es invocado. Esto lo hace com parando el nm ero y tipos de los argum entos espe
cificados en la llam ada, con los parm etros especificados en las distintas defini
ciones del m todo. El siguiente ejem plo m uestra las posibles form as de invocar al
m todo a signarF echa:
264 JA V A: CU R SO DE PROGRAM A CIN

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.

IMPLEMENTACIN DE UNA APLICACIN


Recordando lo expuesto en captulos anteriores, las aplicaciones son program as
Java que se ejecutan por s m ism os, a diferencia de los applets que requieren de
un explorador. U na aplicacin consiste en una o m s clases, de las cuales una de
ellas tiene que ser una clase aplicacin: clase que incluya el m todo m a in . C uan
do com pile el fichero que contiene su aplicacin, el com pilador Java generar un
fichero .class por cada una de las clases que la com ponen; cada fichero generado
tendr el m ism o nom bre que la clase que contiene.

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

S y s t e m . o u t . p r i n t " a o , IHHHt : "): ao = Leer.datolnt):


f e c h a . a s i g n a r F e c h a d l a . mes . a o ) ;
I
w h i 1e ( ! f e c h a . f e c h a C o r r e c t a ( ) ) :

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:

public static void m a i n i S t r i n g ] args)


I
CFecha f e c h a = new C F e c h a ( ) :
II...
i n t dd = f e c h a . d a : // e r r o r : d 1 a e s un m i e m b r o p r i v a d o
f e c h a . m e s = 1: II e r r o r : mes e s un m i e m b r o p r i v a d o
b o o l e a n e s B i s i e s t o = f e c h a . b i s i e s t o ); // c o r r e c t o
I

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.

CONTROL DE ACCESO A UNA CLASE


El control de acceso a una clase determ ina la relacin que tiene esa clase con otras
clases de otros paquetes. D istinguim os dos niveles de acceso: de paquete y p bli
co. Una clase con nivel de acceso de paquete slo puede ser utilizada por las cla
ses de su paquete (no est disponible para otros paquetes, ni siquiera para los
subpaquetes). En cam bio, una clase pblica puede ser utilizada p o r cualquier otra
clase de otro paquete.

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

R ecuerde, en el captulo 4 aprendi que cada objeto m antiene su propia copia de


los atributos pero no de los m todos de su clase, de los cuales slo existe una co
pia para todos los objetos de esa clase. Esto es, cada objeto alm acena sus propios
datos, pero para acceder y operar con ellos, todos com parten los m ism os m todos
definidos en su clase. Por lo tanto, para que un m todo conozca la identidad del
objeto particular para el que ha sido invocado, Java proporciona una referencia al
objeto denom inada this. As, por ejem plo, si cream os un objeto fe c h a ] y a conti
nuacin le enviam os el m ensaje asignarF echa,

f e c h a l . a s i g n a r F e c h a t d a . mes . ao):

Jav a define la referencia th is para perm itir referirse al objeto fe c h a 1 en el cuerpo


de el m todo que se ejecuta com o respuesta al m ensaje. E sa definicin es as:

final C F ec h a this = fechal:

Y cuando realizam os la m ism a operacin con otro objeto fech a 2 ,

fecha2.asignarFecha(d1a, mes . ao):

Jav a define la referencia th is, para referirse al objeto fe c h a l, de la forma:

final CFecha this - fecha2:

S egn lo expuesto, el m todo asignarF echa podra ser definido tam bin com o
se m uestra a continuacin:

public void asignarFechatint dd. i n t mm. int aa)


I
this.da = dd : t h i s . m e s = mm: t h i s . a o - aa:
CA PTU LO 9: C L A SES Y PA Q U ETES 2 6 7

Q u representa th is en este m todo? Segn lo explicado, th is es una referen


cia al objeto q ue recibi el m ensaje asignarF echa; esto es, al objeto sobre el que
se est realizando el proceso llevado a cabo p o r el m todo asigncirFecha.

O bserve ahora el m todo m a in de la clase Test presentada anteriorm ente. En


l hem os declarado un objeto fe c h a de la clase C Fecha y posteriorm ente le hem os
enviado un m ensaje fechaC orrecta:

do

System.out pri n t ( 'di a . ## : "): di a Leer d a t o l n t ):


System.out pri n t ( 'm es, U : "): mes Leer d a t o l n t ):
S ystem .o ut p r i nt( 'ao. # # # : "): ao Leer d a t o l n t ( );
fe c h a . a s i gnarFech a (d i a mes . a o ) :

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 ?

p u b lic boolean fechaCorrecta)


I
II...
if ( b i s i e s t o ! ))
// ...

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:

if (th is.b isie sto O )

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.

VARIABLES, MTODOS Y CLASES FINALES


En el captulo 3 ya fueron expuestas las variables finales, generalm ente denom i
nadas constantes porque nunca cam bian su valor. Tam bin vim os su uso ju n to con
268 JA VA : C U R SO D E PROGRAM A CIN

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

D eclarar un m todo fin al supone que la clase se ejecute con m s eficiencia,


porque el com pilador puede colocar el cdigo de bytes del m todo directam ente
en el lugar del program a donde se invoque a dicho m todo, ya que se garantiza
que el m todo no va a cam biar. P or ejem plo:

public fin a l void asigriarFecha in t dd . i n t mm. int aa)


I
d i a = dd : mes = mm: a o = a a :
I

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:

public final class CFecha


!
II...
I

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 :

C on objetos, el com pilador proporciona un constructor pblico por om isin


para cada clase definida. Este constructor ser ejecutado despus que el operador
new, secuencial y recursivam ente (un m iem bro de una clase puede ser iniciado
con un objeto de otra clase) reserve m em oria para cada uno de los m iem bros y los
inicie. Igualm ente, el com pilador proporciona para cada clase de objetos un des
tructor protegido por om isin, que ser invocado ju sto antes de que se destruya
un objeto con el fin de perm itir realizar tareas de lim pieza y liberar recursos.

No obstante, com o verem os a continuacin, cuando el constructor proporcio


nado por om isin p o r Java no satisfaga las necesidades de nuestra clase de obje
tos, podem os d efinir uno. Idem para el destructor.

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

A signa m em oria para el objeto p o r m edio del operador new.


Inicia los atributos de ese objeto, ya sea a sus valores iniciales (si los atributos
fueron iniciados en su propia declararon) o a los valores predeterm inados por
el sistem a: los atributos num ricos a ceros, los alfanum ricos a nulos, y las
referencias a objetos a nuil.
L lam a al constructor de la clase que puede ser uno entre varios, segn se ex
pone a continuacin.

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 p o r om isin de una ciase C es un constructor sin parm etros


que no hace nada. Sin em bargo, es necesario porque segn lo que acabam os de
exponer, ser invocado cada vez que se construya un objeto sin especificar ningn
argum ento, en cuyo caso el objeto ser iniciado con los valores especificados
cuando se declararon los atributos en su clase, o en su defecto, con los valores
predeterm inados por el sistem a.

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

C om o ejem plo, vam os a aadir un constructor a la clase C Fecha con el fin de


poder iniciar los atributos de cada nuevo objeto con unos valores determ inados:

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

O bserve q ue el constructor, salvo en casos excepcionales, debe declararse


siem pre pblico para que pueda ser invocado desde cualquier parte, aunque la cla
se, que se supone pblica, pertenezca a otro paquete.

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:

public class Test

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

public static void m a in (S trin g [] args)


I
// La s i g u i e n t e l i n e a i n v o c a al c o n s t r u c t o r de l a c l a s e C F ech a
CF e c h a f e c h a - new C F e c h a d . 3. 2 0 0 2 ) : // o b j e t o de t i p o C F ec h a
v i s u a l i z a r F e c h a ( f e c h a ):

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

A adam os ahora al m todo m a in de la clase Test del ejem plo anterior, la l


nea de cdigo que se indica a continuacin. Q u ocurrir?
272 JA V A: C U R SO DE PROGRAM A CIN

CF e c h a o t r a F e c h a = new C F e c h a O ;

Q uizs se sorprenda cuando el com pilador Java le indique que la clase C F e


cha no tiene ningn constructor sin parm etros, cuando anteriorm ente habam os
dicho que Java proporciona para toda clase uno. L o que sucede es que siem pre
que en una clase se define explcitam ente un constructor, el constructor im plcito
(constructor por om isin) es reem plazado p o r ste.

Segn lo expuesto, la definicin explcita del constructor con parm etros


C Fecha)int dd, int m m, int aaaa), ha sustituido al constructor p o r om isin que Ja
va a ad i a esa clase. Para solucionar este problem a, hay que aadir a la clase un
constructor sin parm etros. Por ejem plo, el siguiente:

public CFechaO { /* Sin cdigo */ )

El constructor anterior, realiza la m ism a funcin que el constructor p o r om i


sin. N o obstante, en el caso de la clase CFecha, quizs sea m s conveniente,
aadir un constructor sin parm etros que inicie cada objeto creado con los valores
correspondientes a la fecha actual:

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

Sobrecarga del constructor


Segn lo expuesto, es evidente que podem os d efinir m ltiples constructores con el
m ism o nom bre y diferentes parm etros con el fin de poder iniciar un objeto de
una clase de diferentes form as. Esto no es nuevo, sim plem ente es aplicar la tcni
ca de sobrecargar un m todo, expuesta anteriorm ente, al constructor de una clase.

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:

public CFechaO // c o n s t r u c t o r sin parmetros


(
a s i g n a r F e c h a O : // a s i g n a r f e c h a actual
1
CA PTU LO 9: CL A SES Y PA Q U ETES 2 7 3

public CFecha(int dd) // c o n s t r u c t o r c o n un p a r m e t r o


I
a s i g n a r F e c h a ! ) : // a s i g n a r fecha actual
dia = d d :
i f ( ! f e c h a C o r r e c t a ( ))
I
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 ! ):

public C F e c h a i n t dd . i n t mm) // c o n s t r u c t o r con d o s p a r m e t r o s


I
a s i g n a r F e c h a ! ) ; // a s i g n a r fecha actual
d i a = dd : mes = mm:
i f ( ! f e c h a C o r r e c t a ! ))
I
System .out.printn("Fecha incorrecta. Se a s i g n a la actual."):
a s i g n a r F e c h a ! );

public CFechatint dd . i n t mm. int aaaa) // c o n s t r u c . con t r e s pars.


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 ! ))
I
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 ! ):

A hora, podem os invocar al constructor C Fecha con O, 1, 2 3 argum entos,


segn se puede observar en las lneas de cdigo siguientes:

CF e c h a fechal = new CFecha!):


CF e c h a fecha2 = new CFechaO):
CF e c h a fecha3 = new CFecha(15, 3):
C F ec h a fecha4 = new C F e c h a . 3. 2 0 0 2 ) :

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:

public void CFechaint a. int b, int c)


I
// ...
274 JA V A : C U R SO D E PROGRAM A CIN

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:

t h i s ( [ [ [ [ a r g j ] , arg?], arg3]. ...]);

La llam ada a un constructor slo puede realizarse desde dentro de otro co n s


tructor de su m ism a clase y debe ser siem pre la prim era sentencia. Por ejem plo, el
constructor con un parm etro podra escribirse tam bin as:

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 :

Este ejem plo crea tres objetos: f e c h a l , f e c h a l y fe c h a 3 . D espus declara una


nueva referencia fe c h a d y le asigna fe c h a l, pero tanto fe c h a l com o fe c h a d son
referencias a objetos CFecha, que ahora apuntan al m ism o objeto (al referencian-
do por fe c h a l) . Finalm ente, asigna fe c h a 2 a fech a d , con lo que am bas referencias
apuntarn al objeto referenciado p o r fech a 2 .

Lo anteriorm ente expuesto dem uestra que el operador de asignacin no sirve


para co piar un objeto en otro. C ul es la solucin para resolver el problem a
planteado? Pues, aadir a la clase C Fecha un m todo com o el siguiente:
C A P T U L O 9: CL A SES Y PA Q U ETES 2 7 5

public void copiar(CFecha obj)


I
d a = o b j .d1a :
mes = o b j . m e s :
ao = o b j .a o ;
I

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

Si ahora quisiram os copiar el objeto fe c h a 3 en el objeto fe c h a ! y en el objeto


fe c h a 1, podram os proceder, por ejem plo, as:

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 ) ):

T endram os que m odificar el m todo copiar com o se observa a continuacin:

public CFecha c o p i a r ( C F e c h a obj)


I
di a = o b j . d i a :
mes = o b j . m e s :
ao = o b j . a o ;
return th is;

El m todo co piar devuelve ahora una referencia al objeto resultado de la co


pia, con lo cual podem os u tilizar esta referencia para copiar este objeto en otro;
esto es, el hecho de que el m todo copiar retom e una referencia al objeto resul
tante perm ite realizar copias m ltiples encadenadas.

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

nom bre_clase(nom bre_clase referencia jo b je t )

Se puede observar que un constructor de las caractersticas especificadas tiene


un solo parm etro, que es una referencia a un objeto de su m ism a clase. Por tra
tarse de un constructor no hay un valor retornado. Pues bien, un constructor que
se invoca para iniciar un nuevo objeto creado a partir de otro existente es denom i
nado constructor copia.

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

V em os que el constructor copia acepta com o argum ento una referencia al ob


je to a copiar y despus, asigna m iem bro a m iem bro ese objeto al nuevo objeto
construido. Para probar cm o trabaja, puede aadir a la funcin m a in de la clase
Test que escribim os anteriorm ente, las siguientes lneas de cdigo:

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.

C uando un objeto es destruido ocurren varias cosas: se llam a al m todo fin a


lize y despus, el recolector de basura se encarga de elim inar el objeto, lo que
conlleva liberar los recursos que dicho objeto tenga adjudicados, com o por ejem
plo, la m em oria que ocupa.
C A PTU LO 9: CLA SES Y PAQUETES 2 7 7

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:

protected void fin alize O th rows Throwable I /* s in cdigo */ I

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.

C om o ejem plo vam os a aadir a la clase C Fecha del program a anterior, un


destructor para q ue sim plem ente nos m uestre un m ensaje cada vez q ue se destruya
un objeto de esa clase. Esto es:

public c la ss CFecha
I
// ...

protected void fina lizeO t h r o w s T h r o w a b l e // d e s t r u c t o r


1
S y s t e m . o u t . p r i n t l n " O b j e t o d e s t r u i d o " );
I
II...
I

Ejecute ahora la aplicacin Test cuyo cdigo se m uestra a continuacin y ob


serve los resultados.

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

public static void v i s u a l i z a r F e c h a ( CFecha fecha)


I
i n t [ ] f = new i n t [ 3 ] :
fecha.obtenerFecha(f);
System .out.p rintn(f[0] + "/" + f [ 1 ] + "/" + f [ 2 ] ) :

public static void m a in (S trin g [] args)


I
C F e c h a f e c h a l = new C F e c h a C l , 3. 2002):
// E mp i e z a un b l o q u e de c d i g o
I
C F e c h a f e c h a 2 = new C F e c h a < f e c h a l ):
v is u a liz a r F e c h a fe c h a 2);
I // f i n d e l b l o q u e
v i s u a l i z a r F e c h a C f e c h a l );

A nalizando este ejem plo, observam os que en el m todo m a in se crean dos


objetos: uno al nivel del bloque de m a in , y otro local a un bloque interno a m ain.
Por lo tanto, cada objeto quedar desreferenciado cuando el flujo de ejecucin
salga fuera del bloque en el que est definido, instante a partir del cual el reco
lector de basura puede recolectar esos objetos.

O bservar que cuando finalice la ejecucin del m todo m a in no se visualiza


el m ensaje O bjeto destruido tantas veces com o objetos hay. Esto significa que
el recolector de basura, ju sto en este instante, no est en ejecucin (slo p o r una
pequea cantidad de tiem po); un poco m s larde, posiblem ente cuando el sistem a
est libre, el recolector de basura identificar los objetos que no tienen referencias
y los elim inar liberando la m em oria q ue ocupan.

N o obstante, la aplicacin Java puede finalizar sin que el recolector haya


identificado todos los objetos que d eb a e n v iar a la basura y p o r lo tanto, los d es
tructores correspondientes no se ejecutarn. En este caso, ser el sistem a operati
vo el que se encargue de liberar los recursos que fueron ocupados.

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

Ejecutar el recolector de basura


El recolector d e basura se ejecuta en un subproceso paralelam ente a su aplicacin
lim piando la basura (objetos desreferenciados) en form a silenciosa y en segundo
plano y nunca se detiene por m s de una pequea cantidad de tiem po.

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:

public class Test


I
// Vi s u a l i z a r una f e c h a
p u b l i c s t a t i c v o i d v i s u a l i z a r F e c h a ( CFecha fecha)
I
i n t [ ] f = new i n t [ 3 ] ;

fecha.obtenerFecha(f);
S y stem .o ut.p r i n t n < f [0] + "/" + f[l] + "/" + f[2]);
1

public static void m a in ( S t r in g [ ] args)


I
C F e c h a f e c h a l = new C F e c h a d , 3. 2002):
// E mp i e z a un b l o q u e de c d i g o
I
C F e c h a f e c h a 2 = new C F e c h a ( f e c h a 1 ) ;
vi su a li zarFecha( fecha2):
fecha2 = n u i l :
Runtime runtim e = R u n t i m e . g e t R u n t i m e ( );
r u n t i m e . g c ( ):
r u n t i m e . r u n F i n a l i z a t i o n ( ):
I // f i n d e l b l o q u e
v i s u a l i z a r F e c h a ( f e c h a l ):

El ejem plo anterior fuerza la recoleccin de basura en el bloque de cdigo


interno a m a in . Si em bargo, esto rara vez ser necesario; a lo m ejor, si acaba de
liberar m uchos objetos ya inservibles y quiere que se lleven pronto la basura.

REFERENCIAS COMO MIEMBROS DE UNA CLASE


Un m iem bro de una clase que sea una referencia requiere, generalm ente, de una
asignacin de m em oria, proceso que norm alm ente realizar el constructor. Sucede
entonces que el espacio de m em oria asignado es referenciado desde el objeto pe-
280 JA V A : C U R SO DF. PROGRAM A CIN

ro, lgicam ente, no pertenece al objeto, lo que puede d ar lugar a problem as si no


se im plem entan adecuadam ente los m todos que generan un objeto copia de otro
de su m ism a clase. Un ejem plo de este tipo de clases es la clase C rculo expuesta
al principio de este captulo; recuerde que tena un m iem bro centro de la clase
Punto.

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

Segn lo expuesto, la funcionalidad de la clase C V ector estar soportada por


los atributos:

vector: una referencia a una m atriz de valores de tipo do u b le.


nE lem entos: nm ero de elem entos de dicha m atriz.

public class CVector


I
private double[] vector:
prvate i n t nElementos:
II ...

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.

El trabajo que tienen que realizar los constructores de la clase C Vector. de


pendiendo de los casos, es asignar la m em oria necesaria para la m atriz de da
tos e iniciar dicha m atriz con ceros (iniciacin por om isin), con otra m atriz o
con otro vector, com o podem os ver a continuacin:
C A PTU LO 9: CL A SES Y PAQUETES 2 8 1

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

public C VectorO nt ne) // ne e l e m e n t o s


I
if ( ne < 1 )
I
System .out.p rin tln ("N de e l e m e n t o s no v l i d o : " + ne):
System .out.println("Se a s i g n a n 10 e l e m e n t o s " ) :
ne = 10;
I
n E l e m e n t o s ne:
v e c t o r = new d o u b l e [ n E l e m e n t o s ] :
I

public CVector(double[] 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


I
nEle mentos = m .le n g th ;
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 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 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 u b lic CVector co piar(C V ector v) // c o p i a un C V e c t o r en o t r o


I
nEle mentos = v . n E le m e n t o s :
v e c t o r = new d o u b l e f 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
282 JA V A: C U R SO D E PROGRAM A CIN

f o r ( i n t i = 0; i < nE lem entos; i++ )


vectorfi] = v.vector[1];
return this;
)

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.

public double v a lo r E n int i ) I return vectord]; I

longitud-, m todo que devuelve el nm ero de elem entos de un objeto CVector.

public int longitud!) I return nElementos; I

El resultado de encapsular los m todos anteriorm ente expuestos es la clase


C V ector que se m uestra a continuacin:

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

p u b l i c C V e c t o r ) // n m ero de e l e m e n t o s por om isin


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

public CVectorint ne) // ne e l e m e n t o s


I
if ( ne < 1 )
I
S y s t e m . o u t . p r i n t l n " N s de e l e m e n t o s no v l i d o : + ne);
S y s t e m . o u t . p r i n t l n i " S e a s i g n a n 10 e l e m e n t o s );
ne = 10;
I
n E l e m e n t o s = ne;
v e c t o r = new d o u b l e [ n E 1e m e n t o s ] :
CA PTU LO 9: C L A SES Y PAQUETES 2 8 3

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

public CVectorCVector v) // c o n s t r u c t o r copia


I
nEle mentos = v . n E le m e n t o s :
v e c t o r = new d o u b l e [ n E 1 e m e n t o s ] ;
// C o p i a r el o b j e t o v
f o r ( i n t i = 0: i < nElem entos; i + + )
vector[i] = v.vector[1]:

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;

public void ponerValorEn int i, double v a l o r )


I
if ( i >= 0 && i < n E l e m e n t o s )
vector[i ] = valor;
else
System .out.p r i n t l n ( n d ic e fuera de l i m i t e s " ) :

p u b lic double va lo rE n int i )


I
if ( i > = 0 && i < n E l e m e n t o s )
return v e c to rti];
else
I
S y ste m .o u t.p rin tn (" ndice fuera de l i m i t e s " ) :
r e t u r n Double.NaN;

public int longitudO I return nElementos: I


284 JA VA: C U R S O DE PROGRAM A CIN

El resultado es que cada objeto C V ector consta de dos bloques de m em oria,


uno de tam ao fijo que alm acena su estructura interna (vector y nE lem entos) y
o tro de longitud variable que alm acena los datos (la m atriz de tipo do u b le).

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

public static v o i d ma i n ( S t r i rig[ ] a r g s )


I
C V e c t o r v e c t o r l = new C V e c t o r ( 5 ) :
vi s u a 1 i z a r V e c t o r ( v e c t o r l );

CVect or v e c t o r 2 = new CVe c t o r ) );


f o r ( i n t 1 = 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 En( i . ( i + l ) * 1 0 ) :
vi s u a l i zar Vect or ( vector2) ;

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

System .out.p rintln"Fin de la a p l i c a c i n " ) :

A nalizando a grandes rasgos el cdigo presentado anteriorm ente, podem os


v er que la lnea:
CVector v e c to rl = new C V e c t o r ( 5 ) :

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

for (in t i = 0 : i < ve cto r2 .lo n g itu d (): i+ + )


v e c t o r ? .ponerValo rE n ( i . (1+1) * 1 0 ) :

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

la prim era define la m atriz x y la ltim a llam a al constructor C V ectorfdouble[ / m )


y crea un objeto vector4 iniciado con los datos d e la m atriz 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;

Suponga tam bin que en la aplicacin anterior el m todo m a in fuera com o


sigue:

public static void m a in (S trin g [] args)

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

// El siguiente bloque d e f in e vector2


I
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 ):
286 JA V A: C U R SO DE PROGRAM A CIN

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

System .out.p rintlnC Fin de l a aplicacin"):

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

ser dos objetos, ve cto rl y v e c to r l, referenciando la m ism a m atriz. La figura si


guiente m uestra esto con claridad:

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

E sto significa que cualquier m odificacin en uno de los objetos afectar a


am bos, ju sto lo que sucede cuando se ejecuta el cdigo siguiente. Las m odifica
ciones realizadas en el objeto ve c to rl afectan de la m ism a form a a v e c to r l:

// El siguiente bloque d e f in e vector2


1
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 );
f o r ( i n t i - 0: i < v e c t o r 2 . 1 o n g i t u d ( ) ; i + + J
v e c t o r 2 . p o n e r V a lo r E n ( i. v e c t o r 2 . v a l o r E n ( i )*10>:
vi s u a li z a r V e c t o r ( v e c t o r 2 ) ;
1

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

ciado p o r el atributo vector de v e c to r il N o, porque dicho objeto m atriz tiene an


una referencia: vector de vector].

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

C om o ejem plo, aada la definicin del m todo e q u a ls a la clase CVector. Para


poder escrib ir este m todo, prim ero debe responder a la siguiente pregunta:
cundo dos objetos C Vector son iguales? La respuesta es, cuando contengan los
m ism os valores; esto es, cuando las m atrices que representan sean idnticas. Basta
entonces con el m todo e q u a ls de la clase C V ector com pare las m atrices de los
dos objetos a com parar:

p u b lic boolean eq u a ls(C V e cto r v)


I
r e t u r n A r r a y s .e q u a l s ( v e c t o r . v . v e c t o r ) ;
I

El cdigo anterior im plica im portar la clase A r r a y s del paquete java.util. Pa


ra probar los resultados que podem os obtener a p artir de este m todo a diferencia
de los obtenidos por el operador = = escriba la siguiente aplicacin:

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

public static void m a in (S trin g [] args)


1
d o u b l e x [ ] = 1 1 . 2 . 3. 4. S . 6. 7 1: // 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

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 " ):

Si ejecuta la aplicacin Test anterior, obtendr los siguientes resultados:

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

MIEMBROS STATIC DE UNA CLASE


Este tem a y a fue introducido en el captulo 4. Por lo tanto, el propsito ahora que
ya tiene un m ayor conocim iento de la PO O es abundar en detalles con el fin de
dejar suficientem ente claro cul es la utilidad de estos m iem bros.
CA PITU LO 9: CL A SES Y PA Q U ETES 2 8 9

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.

Un atributo static no es un atributo especfico de un objeto (el radio si es un


atributo especfico de un crculo; cada crculo tiene su radio), sino m s bien es un
atributo de la clase; esto es, un atributo del que slo hay una copia que com parten
todos los objetos d e la clase. Por esta razn, un atributo static existe y puede ser
utilizado aunque no exista ningn objeto de la clase.

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;

P u n t o d o u b le ex. double cy)


I
x = ex: y - cy:

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;

p r i v a t e Punto cen tro: // 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 : // r a d i o d e l c i r c u l o

// Mtodos
290 JA V A: C U R SO DE PRO G R A M A CI N

protected void m sgEsN egativo()


I
System .out.println"El r a d i o es n e g a t i v o . Se c o n v i e r t e a p o s i t i v o " ) :
I

public C ircu lo !) // c o n s t r u c t o r sin parmetros

t h is ( 100.0, 1 0 0 . C 1 0 0 . 0 ) :
I

p u b l i c C i 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
c e n t r o = new P u n t o c x . cy);
i f ( r < 0)
1
m s g E s N e g a t i v o ( );
r = -r :
I
r a d i o = r;
numCi r c u l o s + + ;
I

public double 1o n g C i r c u n f e r e n c i a < )


I
return 2 * pi * radio:
I

p u b lic double r e a C I r c u l o ( )
I
return pi * radio * radio:
i
i

Un atributo static puede ser calificado com o p riv a te (privado), protected


(protegido), p u b lic (pblico), o no calificado (acceso predeterm inado). Asimismo,
podem os calificarlo fin a l para que sea una constante en lugar de una variable.

Acceder a los atributos static


En el apartado anterior podem os ver cm o los m todos de la clase C rculo pueden
acceder directam ente a los atributos num C rculos y p i de la m ism a, igual que ac
ceden al resto de los atributos. Pero, desde otra clase cm o podem os acceder a
esa inform acin? Puesto que num C rculos es una variable static declarada public
podem os acceder a ella directam ente a travs del nom bre de la clase (utilizar el
nom bre de un objeto, aunque es vlido, puede dar lugar a m alas interpretaciones
del cdigo). Por ejem plo:
C A P T U L O 9: CL A SES Y PAQUETES 2 9 1

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

O bserve que para acceder a la inform acin proporcionada por el atributo


num C rculos se utiliza el nom bre de su clase y no el de un objeto de la misma. En
cam bio, desde la clase Test no se puede acceder al atributo p i porque es privado.

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.

C om o ejem plo, vam os a aadir a la clase C rculo un m todo cam biarPreci-


sinP iA que perm ite cam biar la precisin de p i siem pre que su valor se m antenga
entre 3.14 y 3.1416.

public static void ca m b iarP recisinP iA (d ou b le nuevoValor)


I
if (nuevoValor < 3.14 || n u e v o V a l o r > 3 . 1 4 1 6 ) return:
pi = nuevoValor:
292 JA V A: C U R SO D E PROGRAM A CIN

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:

public class Test


I
public static void m a in (S trin g [] args)
I
C i r c u l o o b j l - new C r c u l o O :
S y s t e m . o u t . p r in t l n t o b j l .1o n g C ir c u n f e r e n c ia ( ));
S y s t e m . o u t . p r i n t l n t o b j l . r e a C i r c u l o t ) >:

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 ):

Se puede observar que el com portam iento de C rculo.cam biarPrecisinPiA es


igual que el de cualquier otro m todo de un lenguaje no orientado a objetos. Esto
hace posible escribir program as Java utilizando solam ente esta clase de mtodos,
pero entonces se frustrara el propsito m s im portante de este lenguaje: la POO.
No piense por ello que utilizar este tipo de m todos es una tram pa. Hay m uchas y
buenas razones para utilizarlos y sino observe la utilidad de las clases M a th y
S y stem en las que todos sus m todos son estticos.

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

En m s de una ocasin necesitarem os iniciaciones m s com plejas que esas


que podem os hacer en la propia declaracin. Para esto podem os utilizar alguno de
los constructores de la clase. Pero en el caso de que la clase tenga atributos estti
cos, los constructores slo seran adecuados cuando la iniciacin de esos atributos
no sea requerida antes de que se cree un prim er objeto. Si no es as, ser necesario
aadir a la clase un iniciador esttico cuya sintaxis es la siguiente:

stati c
I
// i n i c i a c i n ele l o s atributos de l a clase
1

Un iniciador esttico es un m todo annim o que no tiene parm etros, no re


tom a ningn valor, y es invocado autom ticam ente por el sistem a cuando se carga
la clase.

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:

CPersona[] listaTelfonos = new C P e r s o n a f l O O ] :

listaTelfonos es una m atriz de referencias a objetos de la clase C Persona. Cada


elem ento de esta m atriz ser iniciado p o r Java con el valor nuil, indicando as que
la m atriz inicialm enle no referencia a ningn objeto C P ersona; esto es, la matriz
est vaca.

U na vez creada la m atriz, para asignar un objeto al elem ento i de la m ism a se


puede u tilizar una lnea de cdigo com o la 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 ] ) :

C om o ejem plo, supongam os que deseam os m antener una lista de telfonos.


La lista ser un objeto que encapsule la m atriz de objetos persona, y m uestre una
interfaz que perm ita aadir, elim inar y buscar una en la lista.

En un prim er anlisis sobre el enunciado identificam os dos clases de objetos:


personas y lista de telfonos.

La clase de objetos persona (que denom inarem os C Persona) encapsular el


nom bre, la direccin y el telfono de cada una de las personas de la lista; asimis
m o proporcionar la funcionalidad necesaria para establecer u obtener los datos
de cada persona individual.

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:

C onstructores, con y sin argum entos, para iniciar un objeto persona.

M todos de acceso (asignar... y obtener...) para cada uno de los atributos.


CA PTU LO 9: CL A SES Y PA Q U ETES 2 9 5

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

public void a s i g n a r N o m b r e ( S t r i n g nom)

nombre = nom;

public String obtenerNombre()

r e t u r n n o mbr e ;

public void a s ig n a r D ir e c c i n ( S t r in g dir)


I
d i r e c c i n = d i r ;

public S trin g obtenerDireccin()


I
return direccin:

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 ;

public long obtenerTelfono()


I
return telfono;
296 JA V A : C U R SO DE PROGRAM A CIN

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

private void unElementoMs( C P e rso n a [] l i s t a A c t u a l ) I ... 1


private void unElementoMenos( C P e rso n a [] l i s t a A c t u a l ) I ... 1
public C L i s t a T f n o s ) I . . . 1 // c o n s t r u c t o r
public void p one rValorEnt i n t i. CPersona ob je to ) I ... 1
public CPersona va lo rE n ( in t i ) I . .. 1
public i n t 1o n g i t u d ( ) I . . . I
public void aadr(CPersona obj) I ... I
public v o i d el i m i n a r d o n g tel ) I . . . 1
public in t b u s c a r ( S t r in g s t r . in t pos) i ... )
)

Para crear un objeto lista de telfonos escribirem os una lnea de cdigo como
la siguiente:

CListaTfnos listatfnos = new C L i s t a T f n o s ( ):

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:

public C L ista T fn o s()


I
II C r e a r una l i s t a v a c i a
n E l e m e n t o s = 0:
l i s t a T e i f o n o s = new C P e r s o n a C n E l e m e n t o s ] :
CA PTU LO 9: C L A SES Y PAQUETES 2 9 7

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

El cdigo que escribirem os para aadir un telfono (objeto C P ersona) a la


lista de telfonos (objeto C ListaTfnos) ser anlogo al siguiente:

1i s t a t f n o s .aadir(new CPersona(nombre, direccin, telfono));

C uando el objeto listatfnos de la clase C ListaTfnos recibe el m ensaje aadir,


responde ejecutando su m todo aadir que increm entar en uno el tam ao del
atributo m atriz listaTelfonos y asignar a este nuevo elem ento el objeto C P erso
na pasado com o argum ento. Para realizar estas dos tareas aadirem os a la clase
C ListaTfnos los m todos unE lem entoM s y p onerV alorE n.

public void aadir(CPersona obj )


I
un E l e m e n t o M s ( 1 i s t a T e l f o n o s ):
p o n e r V a l o r E n t n E l e m e n t o s - 1. o b j );
1

O bservam os q ue cuando se invoca al m todo unE lem entoM s se pasa com o


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
listaTelfonos un nuevo espacio de m em oria que perm ita albergar un elem ento
ms de los que tiene actualm ente, copiar uno a uno los elem entos que tena hasta
ahora la m atriz y que estn referenciados por listaActual, e increm entar el atributo
nE lem entos. O bserve que el bloque de m em oria viejo quedar desreferenciado
cuando el flujo de control salga fuera del m todo unE lem entoM s, p o r ser el pa
rm etro listaA ctual local Q uin liberar ese bloque de m em oria y los bloques de
m em oria de los objetos referenciados p o r l? De esta tarea se encarga el recolec
tor de basura de Java.

private void unElementoMs(CPersona[] listaActual)


I
nEle mentos = 1 i s t a A c t u a l .1e n g t h ;
l i s t a T e l f o n o s - new C P e r s o n a n E l e m e n t o s + 1 ] ;
// C o p i a r l a l i s t a a c t u a l
f o r ( i n t i = 0: i < nElem entos: i + + )
1i s t a T e l f o n o s i ] = 1 i s t a A c t u a l [ i ]:
n E 1e m e n t o s + + ;
I

El m todo p o n erV alorE n tiene com o m isin asignar la referencia a un nuevo


objeto C Persona, al elem ento / de la m atriz listaTelfonos. A m bos datos, objeto y
posicin, son pasados com o argum entos.
298 JA V A: C U R S O D E PROGRAM A CIN

public void ponerValorEn( int i. CPersona objeto )


I
if ( i > = 0 && i < n E l e m e n t o s )
1i s t a T e l f o n o s f i ] = objeto:
el se
S y s t e m . o u t . p r i n t l n ( " n d i ce f u e r a de l i m i t e s " ) :
I

El cdigo que escribirem os p ara elim inar un telfono (objeto CPersona) de la


lista de telfonos (objeto C ListaTfnos) ser anlogo al siguiente:

elim inado = 1i s t a t f n o s . e lim i n a r ( t e l f o n o ) ;

C uando el objeto listatfnos de la clase C ListaTfnos recibe el m ensaje elimi


n a r, responde ejecutando su m todo elim inar que quitar de la lista el elemento
correspondiente al telfono pasado com o argum ento y decrem entar en uno el ta
m ao de la lista. Para realizar estas dos tareas, prim ero buscar en la m atriz lista-
Telfonos el elem ento que referencia al objeto C Persona que tiene el nm ero de
telfono pasado com o argum ento y asignar a este elem ento el valor n u il (de esta
form a, el objeto C Persona ser enviado a la basura y recolectado p o r el recolector
de basura); despus, invocar al m todo unElem enloM enos para q u itar ese ele
m ento de la lista. El m todo elim inar devuelve tr u e si se encontr y elim in el
elem ento especificado y false en caso contrario.

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

prvate void unElementoMenos(CPersona[] l i s t a A c t u a l )


I
i f ( 1 i s t a A c t u a l .1ength == 0) return:
i n t k = 0:
nEle mentos - 1 i s t a A c t u a l . 1 e n g t h :
1 i s t a T e l f o n o s - new C P e r s o n a [ n E l e m e n t o s - 1 ] ;
II C o p i a r l a l i s t a a c t u a l
f o r ( i n t i - 0: i < nE le m e ntos: i + + )
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 1e m e n t o s - -:
I

El cdigo que escribirem os para buscar un telfono (objeto C Persona) en la


lista de telfonos (objeto C ListaTfnos) ser anlogo al siguiente:

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 ):

C uando el objeto listatfnos de la clase C ListaT fnos recibe el m ensaje buscar,


responde ejecutando su m todo buscar q ue recorrer la lista de telfonos en busca
de un elem ento (objeto C Persona referenciado) que contenga en su cam po n om
bre la subeadena pasada com o argum ento. La bsqueda se iniciar en la posicin
pasada com o argum ento. El m todo buscar devolver la posicin del elem ento
buscado, si se encuentra, o -1 en caso contrario.

public int buscar(String str, int pos)


I
S t r i n g nom;
i f ( s t r = - n u i l ) re tu rn -1;
i f ( p o s < 0 ) p o s - 0:
for ( i n t i - pos: i < nElementos: i++ )
I
nom = 1 i s t a T e l f o n o s C i ] . o b t e n e r N o m b r e ( ):
i f (nom n u il) continu:
// s t r e s t c o n t e n i d a en nom?
i f ( n o m . in d e x O f( s tr) > -1)
return i ;
I
return -1:
I

O tros m todos de inters son valorEn y longitud. El m todo valorEn devuel


ve el objeto C Persona referenciado por el elem ento i de la m atriz UstaTelfonos.

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.

public int 1o n g i t u d ( ) 1 return nElementos; 1

H asta aqu, el diseo de la clase C Persona y C U staTfnos. El siguiente paso


ser escribir una aplicacin que se ejecute as:

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:

A la vista del resultado anterior, esta aplicacin m ostrar un m en que pre


sentar las operaciones que se pueden realizar sobre la lista de telfonos. Poste
riorm ente, la operacin elegida ser identificada p o r una sentencia sw itch y
procesada de acuerdo al esquem a presentado a continuacin:

public class Test


I
public static in t menO I ... I

public static void m a in ( S t r in g [ ] args)


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 y o t r o de s a l i d a
C A P T U L O 9: CL A SES Y PAQUETES 3 0 1

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

El listado com pleto d e la aplicacin Test se m uestra a continuacin:

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

Syste m .o u t.p ri n t l n ( "2. Buscar 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 i r " );
S y s t e m . o u t . p r i n t n ( " 4 . El i mi 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.printt" Opcin: " ) ;
i n t op:
do
o p - L e e r . d a t o l n t );
w h i l e ( o p < 1 || op > 5 ) :
r e t u r n op:

public static void m a in (Strin g [] args)


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 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 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 l u j o S - System.out:

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

catch (IOException ignorada) II


I
w h i 1 e ( o p c i n != 5);

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

2. C rear una estructura jer rq u ica d e carpetas en el disco duro. H em os dicho


que la biblioteca de clases de Java est organizada en paquetes dispuestos j e
rrquicam ente. Pues bien, esta estructura jerrquica se hace corresponder en
el disco duro con una estructura jerrq u ica de carpetas, de form a que los
nom bres de las carpetas coincidan con los de los elem entos del paquete. La
ruta de la carpeta raz de esta estructura jerrq u ica tiene que estar especificada
por la variable C LASSPATH .

P ara el ejem plo propuesto en el punto 1, la variable C LA SSP A TH debe indi


car, entre otras, la ruta de la carpeta m isClases:

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

3. E specificar el paquete a l que pertenece la clase. C uando defina una clase


puede especificar a qu paquete pertenece utilizando la sentencia:
p a c k a g e nom bre_j)aquete\
Esta sentencia debe ser la prim era lnea de cdigo del fichero fuente.

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

A continuacin coloque las clases C Persona y C ListaTfnos im plem entadas


anteriorm ente, en la carpeta utilidades. Edtelas y aada a cada una de ellas la
sentencia p a c k a g e para especificar el paquete al que pertenecen:

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

UN EJEMPLO DE DISEO DE UNA CLASE


El siguiente ejem plo m uestra cm o construir una clase para o p erar con nm eros
racionales. Un nm ero racional es un nm ero representado por el cociente de dos
nm eros enteros (lo que norm alm ente llam am os quebrado), com o 5/7. El nm ero
de la izquierda se denom ina num erador y el de la derecha denom inador.

U na clase que envuelva un nm ero racional es til porque m uchos de estos


nm eros no pueden ser representados exactam ente utilizando el tipo float. Por
ejem plo, 1/3 + 1/3 + 1/3, que es 1, utilizando el tipo float sera 0,333333 +
0,333333 + 0,333333, que es 0,999999. Para evitar este tipo de errores debem os
considerar a un nm ero racional com o un objeto con entidad propia. Esto se con
sigue diseando una clase, denom inada p o r ejem plo C R acional, con los atributos
num erador y denom inador, y con una interfaz que perm ita realizar cualquier ope
racin en la que pueda intervenir un nm ero racional.

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:

Pensem os ahora en el conjunto de operaciones que deseam os realizar con los


nm eros racionales (a m odo de ejem plo, slo expondrem os algunas de las varias
posibles):

C onstruir un nm ero racional. El constructor im plcito (sin argum entos) no es


adecuado puesto que 0/0 es una indeterm inacin. P or ello definirem os expl
citam ente varios constructores.

O peraciones aritm ticas. Sum a, resta, m ultiplicacin y divisin.

C om paracin de dos nm eros racionales. Igual, m enor y m ayor.

O peraciones para facilitar la entrada y salida.

C opiar un racional en otro y verificar si un racional es cero.

Increm ento, decrem ento y cam bio de signo.

E m pecem os con el constructor. La construccin de un nm ero racional cuan


do se om iten los argum entos parece lgico que resulte ser el racional 0 /1 . Partien
do de este supuesto, el constructor C R acional puede ser:

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:

public CRacional l o n g num, l o n g den ) // c o n s t r u c t o r


I
n u m e r a d o r = num;
d e n o m in ad o r = den:

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.

protected CRacional Sim p lificare)


1
// 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 );
w h i l e ( temp > 0 )
I
r e s t o = mcd % temp:
mcd = temp;
temp = r e s t o :
I
II S i m p l i f i c a r
i f ( mcd > 1 )
1
n u m e r a d o r /= mcd:
d en om in ad or /= mcd :
)
return this;

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

Pensem os ahora en las operaciones aritm ticas; p o r ejem plo, en la operacin


de sum ar. S upongam os las siguientes declaraciones:

CRacional r l = new CRacional(1):


CRacional r2 - new C R a c i o n a ld . 4):
CRacional r3;

C om o el operador + no est definido para los nm eros racionales y tam poco


podem os definirlo, la solucin puede ser utilizar una sintaxis com o la siguiente:

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:

p u b lic CRacional sumar( CRacional r )


I
C R a c i o n a l temp;
temp - 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.d e n o m in a d o r ):
r e t u r n temp:
I

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.

Supongam os ahora que uno de los operandos que intervienen en la sum a es un


entero. En este caso podram os proceder as:

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 Ra cio nal r3:


r 3 = new C R a c i o n a l ( n ) . s u m a r ( r 2 );

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.

La im plem entacin de los m todos restar, m ultiplicar y dividir, sabiendo c


m o se obtiene el num erador y el denom inador del resultado, siguen un desarrollo
anlogo al explicado para sumar.

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

L a expresin r3.equals(r2) sugiere redefinir el m todo e q u a ls con un par


m etro que haga referencia a un objeto CRacional-, el otro objeto im plicado en la
com paracin, el de la izquierda, es aquel que recibe el m ensaje eq u a ls. El mtodo
debe devolver un valor tr u e o false. Segn lo expuesto, la definicin del mtodo
puede ser as:

public boolean e q u a ls( CRacional r )


I
return ( nu merador * r . d e n o m i n a d o r ==
d e n o m i n a d o r * r . n u m e r a d o r ):
I

El resto de las operaciones de relacin se desarrollan de form a sim ilar a la ex


puesta.

A continuacin pasam os a resolver la entrada salida de nm eros racionales.


L os m todos que im plem entem os com o parte de la interfaz que los usuarios de
esta clase utilizarn, deben tratar el nm ero racional com o un objeto indivisible;
CA PTU LO 9: C L A SES Y PAQUETES 3 1 1

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

La expresin r l.to S trin g )) debe devolver un objeto S trin g con el contenido


correspondiente al objeto C R acional que recibe el m ensaje toString expresado de
la form a num erador/denom inador :

public String toStringO


I
return new S t r i n g ( n u m e r a d o r + / " + d e n o m i n a d o r ) :
I

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:

public static CRacional lee rO


I
l o n g num. d e n :
int i. barras;
boolean c a r c t e r V lid o :
S t r i n g r a c i o n a 1:
312 JA V A : C U R SO DE PRO G R A M A CI N

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

Pensem os ahora en copiar un objeto C R acional en otro. S upongam os las si


guientes declaraciones:

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

Para poder copiar un objeto C R acional en otro, p o r ejem plo r2 en r l , pode


m os proceder as:

rl.copiar(r2);

La expresin rl.c o p ia r(r2 ) requiere redefinir el m todo copiar con un par


m etro que haga referencia al objeto C R acional a copiar; el objeto sobre el que se
realiza la copia, el de la izquierda, es aquel que recibe el m ensaje copiar. El m
todo deber devolver el objeto copiado con el fin de poder encadenar esta opera
cin cuando se solicite. Segn lo expuesto, este m todo puede ser as:

public CRacional copiart CRacional r )


I
numerador = r.num erador;
denominador = r . d e n o m i n a d o r ;
return th is;
I

En ocasiones, puede ser necesario saber si un nm ero racional es cero. Por


ejem plo, para saber si el racional r es cero podram os escribir:

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

Y , cm o realizar una operacin de la form a a = -b\ tenga en cuenta que b no


cam bia. E sta operacin podram os requerirla as:

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

w hile ( temp > 0 )


I
r e s t o - mcd % temp:
mcd = temp:
temp = r e s t o :
I
// S i m p l i f i c a r
i f ( mcd > 1 )
I
numerador /= mcd:
denomi n a d o r / = m c d :
I
return this;

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:

p u b lic C R a cio n a l( long num ) // c o n s t r u c t o r


(
n u m e r a d o r = num;
denomi n a d o r = 1;

public CRacional( l o n g num. l o n g den ) // 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 = d e n ;
i f ( denominador = 0 )
1
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.");
denomi n a d o r = 1;
I
if ( denominador < 0 )
I
numerador = -numerador:
denominador = -denominador;
I
S i m p l i f i c a r ( );

public CRacionaK CRacional r ) // c o n s t r u c t o r copia


I
numerador = r . numerador:
denominador = r . denominador:
I
316 JA V A: C U R SO D E PROGRAM A CIN

// 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:

public class CMatriz

private d oub le[] 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 [] d im sM a triz ; II v a l o r de c a d a d i m e n s i n
// . . .

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.

Un ejem plo de m anipulacin de un objeto C M atriz es el siguiente:

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.

La representacin grfica de la estructura de datos construida es la siguiente:

M a triz m u ltid im en sio nal

_______________________________________ M a triz d e u n a d im ensi n

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 )

y por los m todos pblicos,

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 )

Suponiendo que querem os m anipular m atrices de 1, 2 3 dim ensiones, res


ponda a las siguientes preguntas:
CA PTU LO 9: CL A SES Y PA Q U ETES 3 2 1

1. E scriba el esqueleto de la definicin de la clase CM atriz.

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.

3. Escriba el m todo construir. Este m todo es invocado p o r los constructores


de la clase y com prueba si todas las dim ensiones son positivas. D espus esta
blece los atributos de CM atriz. T enga presente que m atriz referencia a una
m atriz unidim ensional que representa a la m atriz de 1, 2 3 dim ensiones.

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.

int total Elem entos*)

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.

int desplazamiento* int[] subind )

El m todo desplazam iento retorna la posicin en la m atriz unidim ensional del


elem ento especificado p o r subind o -1 si algn subndice es invlido.

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.

void asignarDato* int dato, int il )


void asignarDato* int dato, int i l . int i2 )
322 JA V A: C U R S O DE PRO G R A M A CI N

void asignarDato( int dato, int il, int i 2, int i3 )

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.

double obtenerDato( int il )


double obtenerDato( int i l . int i2 )
double obtenerDato int il, int i2, in t i3 )

El m todo obtenerD ato retom a el valor alm acenado en el elem ento especifi
cado de la m atriz.

9. U tilizando la clase C M atriz que acaba de construir, escriba un program a que


utilice com o cuerpo del m todo m a in , el expuesto en el enunciado. El resul
tado que tiene que obtener con este m todo es:

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

10. P or qu es necesario sobrecargar los m todos asignarD ato y obtenerD ato?

11. Es necesario un destructor para esta clase? P or qu?

12. Q u m todos se invocan y en qu orden, cuando se ejecuta la sentencia?

C M a t r i z m( A . B ):

13. Q u m todos se invocan y en qu orden, cuando se ejecuta la sentencia?

m.obtenerDato! i . j );

La solucin a las preguntas 1 a 8 puede obtenerlas del cdigo presentado a


continuacin. D icho cdigo corresponde a la definicin de la clase CM atriz.

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

private void c o n s t r u ir int[] dim )


I
int i ;
for ( i = 0: i < dim .length: i++ )
i f ( d i m[ i ] < 1 )
I
System .out.pri ntln("D im ensin nula o negativa"):
S y ste m .e x it-1):
1
// E s t a b l e c e r l o s a t r i b u t o s
d i m s M a t r i z = new i n t [ d i m . 1 e n g t h ] ;
f o r ( i = 0: i < d i m . l e n g t h : i + + ) d i m s M a t r i z [ i ] = d i m [ i ] :
nDims = d i m . l e n g t h :
m a t r i z = new d o u b l e [ t o t a l E l e m e n t o s ( ) ] ;

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

public CMatriz int di ) // c o n s t r u c t o r


I
i n t di mC] = I d i ); // una d i m e n s i n
c o n s t r u i r { d i m );

public CMatriz int di, i n t d2 ) // c o n s t r u c t o r


I
in t dim[] = I d i, d2 I; // d o s d i m e n s i o n e s
c o n s t r u i r ( d i m );

public CMatriz( int di, i n t d2, int d3 ) // c o n s t r u c t o r


I
in t dim[] = I d i. d2, d3 I: // t r e s dimensiones
c o n s t r u i r di m ):

public int total Elem entos)


I
int i ;
i n t n T E l e m e n t o s = 1;
// C a l c u l a r e l n m e r o t o t a l de e l e m e n t o s de l a matriz
f o r ( i = 0: i < nDims: i+ + )
nTElementos * = d i m s M a t r i z [ i ]:
r e t u r n nTElementos;
324 JA V A: C U R SO DE PROGRAM A CIN

public int desplazamiento! in t [] subind )


I
int i :
i n t d e s p l a z a m i e n t o = 0;

for ( i - 0: i < nDims; i++ )


I
// V e r i f i c a r s i l o s s u b n d i c e s e s t n d e n t r o d e l r a n g o
i f ( s u b i n d f i ] < 0 || s u b i n d f i ] > d i m s M a t r i z f i ] )
I
System .out.p rintlnt"Subndice fuera de r a n g o " ) :
r e t u r n -1;
1
// D e s p l a z a m i e n t o e q u i v a l e n t e en l a m a t r i z unidim ensional
desp lazam ien to += s u b i n d f i ] :
i f ( i+ 1 < nDims )
desplazamiento *= d i m s M a t r i z [ i + l ] ;
I
return desplazamiento:

public void asignarDatot int dato, int il )


f
asignarDatotdato. il. 0. 0):

p u b lic void asignarD atot int dato, int il. int i2 )


I
a s i g n a r D a t o t d a t o . i l . i 2. 0 ) ;
I

public void asignarDatot int dato, int il. int i 2. int i3 )


I
// A s i g n a r un v a l o r a l e l e m e n t o e s p e c i f i c a d o de l a matriz
i n t s u b i n d f ] = I i l . i 2. i 3 I :
i n t i = d e s p l a z a m i e n t o t s u b i n d ):
i f ( i - 1 ) S y s t e m . e x i t ( - 1 ) : // s u b n d i c e fuera de r a n g o
m a t r i z f i ] = dato:

p u b lic double obtenerOatot int il )


I
return obtenerDatot il. 0. 0);

p u b lic double obtenerDatot int il. int i2 )


I
return obtenerDatot il. i2. 0);
CA PTU LO 9: CLASES Y PAQUETES 3 2 5

public double obtenerDato int 11. int i2, int i3 )


{
II O b t e n e r e l v a l o r al e l e m e n t o e s p e c i f i c a d o d e l a m a t r i z
i n t s u b i n d [ ] = I i 1. i 2 . i 3 I :
i n t i - d e s p l a z a m i e n t o s u b i n d ):
i f ( i - 1 ) S y s t e m . e x i t ( - 1 ) ; // s u b n d i c e f u e r a d e r a n g o
r e t u r n m a t r i z [ i ];

//////////////////////////////////////////////////////////////////

A continuacin se m uestra la respuesta a la pregunta 9.

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

R espuesta a la pregunta 11. N o es necesario escribir el m todo fin alize por


que de liberar la m em oria asignada dinm icam ente (operador new ) se encarga el
recolector de basura.
326 JA V A : C U R SO DE PROGRAM A CIN

R espuesta a la pregunta 12. Los m todos invocados cuando se ejecuta la sen


tencia C M a t r i z m( A, B ) son:

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!)

R espuesta a la pregunta 13. Los m todos invocados cuando se ejecuta la sen


tencia m . o b t e n e r D a t o ! i . j ) son:

p u b lic double obtenerDato( in t i l , int i2 )


p u b lic double obtenerDato( i n t i l . i n t i 2. i n t i3 )
p u b lic in t desplazamiento( i n t [] subind )

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

A su vez, la m atriz, q u e ir creciendo a m edida que se vayan aadiendo palabras,


ser un atributo d e la clase C F recuenciasP alabras. L a interfaz de esta clase in
cluir al m enos los m todos: BuscarPcilabra, InsertarP alabra y ObtenerObjPala-
bra.

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

de expresiones se defini la unidad im aginaria V -T , que se representa por De


este m odo podem os escribir que:

2 + V -9 = 2 + 3 -7 -1 = 2 + 3 /, que se representa com o (2, 3).

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.

El nm ero positivo m = -Ja~ + b~ se denom ina m dulo o valor absoluto y el n


g ulo a = a re Ig(b/a) recibe el nom bre de argum ento.

O peraciones aritm ticas:

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.

public class Complejo


I
p r i vate double real; // p a r t e real
p r i v a t e double i ma g: // p a r t e im aginaria
II...
I

La interfaz de esta clase proporcionar varios conjuntos de m todos que se pue


den clasificar de la form a siguiente:

U no o m s constructores. El com plejo construido por om isin ser el (0, 0).


P aso de form a p o lar a binm ica.
O peraciones aritm ticas sum ar, restar, m ultiplicar y dividir.
328 JA VA : C U R SO DE PROGRAM A CIN

C om paracin de com plejos. La igualdad y la desigualdad la realizarem os en


m dulo y argum ento. El resto de las com paraciones tienen sentido cuando
slo se com paran los m dulos.
O peraciones trigonom tricas.
O peraciones logaritm o natural, exponencial, potencia y raz cuadrada.
O peraciones de entrada/salida.
C om plejo conjugado, negativo y opuesto.
O peraciones de asignacin.

3. Se quiere escribir un program a para m anipular ecuaciones algebraicas o poli-


nm icas dependientes de una variable. Por ejem plo:

2x3 - x + 8.25 m s 5x5 - 2 x3 + 7x2 - 3 igual a 5x5 + 7x2 - x + 5.25

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:

C onstruir un trm ino, iniciado a cero por om isin.


A cceder al coeficiente de un trm ino para obtener su valor.
A cceder al exponente de un trm ino para obtener su valor.
O btener la cadena de caracteres equivalente a un trm ino con el form ato si
guiente: {+1-} 7x*4.

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:

C onstruir un polinom io, inicialm ente con 0 trm inos.


O btener el nm ero de trm inos que tiene actualm ente el polinom io.
A signar un trm ino a un polinom io colocndolo en orden ascendente del ex
ponente. Si el coeficiente es nulo, no se realizar ninguna operacin. Cada
vez que se inserte un nuevo trm ino, se increm entar autom ticam ente el ta
m ao del polinom io en uno. El m todo encargado de esta operacin tendr un
parm etro de la clase CTermino.
S um ar dos polinom ios. El polinom io resultante quedar tam bin ordenado en
orden ascendente del exponente.
O btener la cadena de caracteres correspondiente a la representacin de un po
linom io con el form ato siguiente: + 5xA5 - 1x^1 + 5.25.
C A PTU LO 10
F.J.Cebalox/RA-MA

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 on la herencia todas las clases estn clasificadas en una jerarq u a estricta.


C ada clase tiene su superclase (la clase superior en la jerarqua), y cada clase pue
de tener una o m s subclases (las clases inferiores en la jerarqua). Las clases que
estn en la parte inferior en la jerarq u a se dice que heredan de las clases que es
tn en la parte superior en la jerarqua. P or ejem plo, la figura siguiente indica que
las clases C C uentaC orriente y C C uentaAhorro heredan de la clase CCuenta.

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

CLASES Y MTODOS ABSTRACTOS


En una jerarqua de clases, una clase es tanto m s especializada cuanto m s aleja
da est de la raz, entendiendo por clase raz aquella de la cual heredan directa o
indirectam ente el resto de las clases de la jerarqua; y al contrario, es tanto ms
genrica cuanto m s cerca est de la raz. S irva de ejem plo la clase O b je c t, clase
raz de la jerarq u a de clases de Java; es una clase que slo define los atributos y
el com portam iento com unes a todas las clases. L o m ism o suceder con la clase
C Cuenta de la figura anterior, ser m s bien una clase genrica, correspondiendo
los atributos y com portam iento ms especficos a las clases C C uentaAhorro y
C C uentaC orriente.

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:

public abstract class CCuenta


I
// C u e r p o de l a clase
)

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.

Q u es un m todo abstracto? Es un m todo calificado a b s tr a c t con la parti


cularidad de que no tiene cuerpo. Por ejem plo, el siguiente cdigo declara comi
siones com o un m todo abstracto:

public abstract c la ss CCuenta


I
// . ..
public abstract void com isiones!):
/ / ...
I

P or qu no tiene cuerpo? Porque la idea es proporcionar m todos que deban


ser redefinidos en las subclases de la clase abstracta, con la intencin de adaptar
los a las necesidades particulares de stas.

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:

1. C uando en un principio se abord el diseo de una aplicacin para adm inis


trar las cuentas de una entidad bancaria, fue suficiente con las capacidades
proporcionadas por la clase C Cuenta. Posteriorm ente, la evolucin de los
m ercados bancarios, sugiri nuevas m odalidades de cuentas. L a m ejor solu
cin para adaptar la aplicacin a esas nuevas exigencias fue definir una sub
clase para cada nueva m odalidad, puesto que el m ecanism o de herencia pona
a disposicin de las subclases todo el cdigo de su superclase, al que slo era
necesario a ad ir las nuevas especificaciones. E videntem ente, la herencia es
una form a sencilla de reutilizar e l cdigo proporcionado p o r otras clases.

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.

En los dos casos planteados, la herencia es la solucin para reutilizar cdigo


perteneciente a otras clases. Para ilustrar el m ecanism o de herencia vam os a im-
plem entar la jerarq u a de clases de la figura anterior. La idea es disear una apli
cacin para adm inistrar las cuentas corrientes y de ahorro de los clientes de una
entidad bancaria. C om o am bas cuentas tienen bastantes cosas en com n, hemos
decidido ag rupar stas en una clase C C uenta de la cual posteriorm ente derivare
m os las cuentas especficas que vayan surgiendo. Segn este planteam iento, no
parece que tengam os intencin de crear objetos de C C uenta; m s bien la intencin
es que agrupe el cdigo com n que heredarn sus subclases, razn por la cual la
declararem os abstracta.

Pensem os entonces inicialm ente en el diseo de la clase C Cuenta. Despus de


un anlisis acerca de los factores que intervienen en una cuenta en general, llega
mos a la conclusin de que los atributos y m todos com unes a cualquier tipo de
cuenta son los siguientes:

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.

El cdigo correspondiente a esta clase se expone a continuacin:

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

public void a s i g n a r N o m b r e S t r i n g nom)


I
if ( n o m . 1e n g t h ) = 0)
I
S y s t e m . o u t . p r i n t l n ( E r r o r : cadena v a c i a " ) :
return;
I
no mb r e = nom:
I

public String obtenerNombre!)


I
return n o mbr e :
I

public void a sig n a rC u e n ta S trin g cue)


(
if ( c u e . l e n g t h ( ) = = 0)
I
S y s t e m . o u t . p r i n t l n ( " E r r o r : c u e n t a no v l i d a " ) :
return:
I
c u e n t a = cue:
1

public String o b te nerC u enta ()


I
return cuenta:
)

p u b lic double e s t a d o ! )
I
return saldo:
)

public abstract void com isiones!):

public a b s t r a c t double intereses!):

public void ingreso(double cantidad)


I
if (cantidad < 0)
I
System .out.p r i n t l n ( " E r r o r : cantidad negativa"):
return:
I
sa ldo += cantidad:
334 JA V A: C U R SO D E PROGRAM A CIN

public void rein tegro(dou ble cantidad)


I
if (saldo - cantidad < 0)
I
System .out.p rintln !"Error: no d i s p o n e de s a l d o );
return:
I
saldo -= cantidad:
I

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

public void asignarTipoDeInters(double tipo)


I
if ( t i po < 0)
I
S y ste m .o u t.p rin tln ("E rro r: tipo no v l i d o ):
return;
I
tipoDelnters = tipo;
I
I
//////////////////////////////////////////////////////////////////

Si ahora, utilizando la definicin de la clase anterior intenta ejecutar una lnea


de cdigo com o la siguiente, obtendr un error indicndole que la clase es abs
tracta.

CCuenta clienteOl = new C C u e n t a O :

DEFINIR UNA SUBCLASE


Pensem os ahora en un tipo de cuenta especfico, com o es una cuenta de ahorro.
U na cuenta de ahorro tiene las caractersticas aportadas p o r un objeto CCuenta, y
adem s algunas otras; por ejem plo, un atributo que especifique el im porte que hay
que pagar m ensualm ente p o r el m antenim iento de la m ism a. Esto significa que
necesitam os disear una nueva clase, C C uentaA horro, que tenga las m ism as ca
pacidades de C Cuenta, pero a las que hay que aadir otras que den solucin a las
nuevas necesidades.

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

public class CCuentaAhorro


I
II A t r i b u t o s y m t o d o s d e C C u e n t a
// N u e v o s a t r i b u t o s y m t o d o s de C C u e n t a A h o r r o
I

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.

U na subclase es un nuevo tipo de objetos definido por el usuario que tiene la


propiedad de heredar los atributos y m todos de o tra clase definida previam ente,
denom inada superclase. La sintaxis para definir una subclase es la siguiente:

class nom bre_subclase e x te n d s nom bre_superclase


{
II C uerpo de la subclase
}

L a palabra clave e x te n d s significa que se est definiendo una clase denom i


nada nom bre_subclase que es una extensin de otra denom inada nom bre_super-
clase\ tam bin se puede decir que n o m b rejsu b c la se es una clase derivada de
nom bre_supe rease.

El ejem plo m ostrado a continuacin define la clase C C uentaA horro com o una
extensin de CCuenta.

public class CCuentaAhorro extends CCuenta


I
II C C u e n t a A h o r r o ha h e r e d a d o l o s m i e m b r o s de C C u e n t a
II E s c r i b a a q u l o s n u e v o s a t r i b u t o s y m t o d o s de C C u e n t a A h o r r o
1

Si no se especifica la clusula e x te n d s con el nom bre d e la superclase, se en


tiende que la superclase es la clase O b je c t. Por lo tanto, la clase C C uenta est d e
rivada de la clase O b jec t.

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.

Control de acceso a los miembros de las clases


En el captulo dedicado a clases se expuso que para controlar el acceso a los
m iem bros de una clase, Java provee las palabras clave p riv a te (privado), protec-
ted (protegido) y p u b lic (pblico), o bien pueden om itirse (acceso predeterm ina
do). Lo all estudiado se am pla ahora para las subclases. Para evitar confusiones,
la tabla siguiente resum e de una form a clara qu clases, o subclases, pueden acce
d er a los m iem bros de otra clase, dependiendo del control de acceso especificado:

Un m iem bro declarado en una clase com o


Puede ser accedido desde: p rivado predeterm inado pro teg id o pblico
Su m ism a c l a s e ................... s s s s
C u alquier clase o subclase
del m ism o p a q u e te ............. no s s s
C u alquier clase de otro
p a q u e te ................................... no no no s
C ualquier subclase de otro
p a q u e te ................................... no no s s

Qu miembros hereda una subclase


Los siguientes puntos resum en las reglas a tener en cuenta cuando se define una
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 no tiene acceso directo a los m iem bros privados (p rivate) de su


superclase.
C A PTU LO 10: SUBC LA SES E IN TERFACES 3 3 7

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.

2. U na subclase puede aadir sus propios atributos y m todos. Si el nom bre de


alguno de estos m iem bros coincide con el de un m iem bro heredado, este lti
m o queda oculto para la subclase, que se traduce en que la subclase ya no
puede acceder directam ente a ese m iem bro. L gicam ente, lo expuesto tiene
sentido siem pre que nos refiram os a los m iem bros de la superclase a los que
la subclase poda acceder, segn el control de acceso aplicado.

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.

L a definicin correspondiente a esta clase se expone a continuacin:

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

public void asignarCuotaMantentdouble cantidad)


I
if (cantidad < 0)
I
S y s t e m . o u t .p r in t ln ( "E r r o r : cantidad negativa"):
return;
I
cuotaMantenimiento = cantidad:

public double obtenerCuotaM antent)


I
return cuotaMantenimiento;

public void com isiones!)


(
// 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 de l a c u e n t a
G r e g o r i a n C a l e n d a r f e c h a A c t u a l = new G r e g o r i a n C a l e n d a r t );
in t dia = fechaActual.get(Calendar.DA Y_0F_M0NTH):

if (dia = = 1) reintegro(cuotaM antenim iento):

p u b lic double intereses))


I
G r e g o r i a n C a l e n d a r f e c h a A c t u a l = new G r e g o r i a n C a 1e n d a r ( );
in t da = fechaActual.get(Calendar.DAY_OF_MONTH):

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):

// D e v o l v e r e l i n t e r s m e n s u a l por si fuera necesario


return in te re se sP ro d u cid o s;
I
//////////////////////////////////////////////////////////////////

CCuentciAhorro es una subclase de la superclase C Cuenta. O bserve que para


definir una subclase se aade a continuacin del nom bre de la m ism a la palabra
reservada e x ten d s y el nom bre de la superclase. En la definicin de la subclase se
describen las caractersticas adicionales que la distinguen de la superclase.

La capacidad de la clase C Cuenta est soportada por:


CA PTU LO 10: SUBCLASES E INTERFACES 3 3 9

A tributos M todos

nom bre constructores C C uenta


cuenta asignarN om bre
saldo obtenerN om bre
tipoD elnters asignarC uenta
obtenerC uenta
estado
com isiones
intereses
ingreso
reintegro
asignarT ipoD elnters
obtenerT ipoD elnters

La capacidad de la clase C C uentaA horro, derivada de C Cuenta, est soporta


da p o r los m iem bros heredados de C Cuenta (en cursiva y no tachados) m s los
suyos:

A tributos M todos

nom bre constructores C Cuenta


cuenta asignarN om bre
saldo obtenerN om bre
tipoD elnters asignarC uenta
obtenerC uenta
estado

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

O bserve que los constructores de la clase CCuenta no se heredan, puesto que


cada clase define el suyo por om isin, y que los m todos com isiones e intereses
quedan ocultos por los m todos del m ism o nom bre de la clase C Cuenta Ahorro.
Un poco m s adelante verem os que es posible referirse a un m iem bro oculto utili
zando la palabra reservada s u p e r de Java: s u p e r .m iem bro_oculto.
340 JA V A: C U R S O D E PROGRAM A CIN

Segn el anlisis anterior, m ientras un posible objeto C Cuenta contendra los


datos nom bre, cuenta, saldo y tipoD elnters, un objeto C C uentaAhorro contiene
los datos nom bre, cuenta, saldo, tipoD elnters y cuotaM antenim iento.

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 .

Partim os del hecho de que las clases C Cuenta y C C uentaAhorro pertenecen al


m ism o paquete que la clase Test. Entonces, un objeto , com o clienteO l, de la
clase C C uentaAhorro puede invocar a cualquiera de los m todos pblicos, prote
gidos y predeterm inados de C C uentaAhorro y de C Cuenta, pero no tiene acceso a
sus m iem bros privados. Si las clases C C uentaA horro y C C uenta pertenecieran a
o tro paquete, la clase Test slo tendra acceso a los m iem bros pblicos.

L os m todos de una subclase no tienen acceso a los m iem bros privados de


su superclase, pero s lo tienen a sus m iem bros protegidos y pblicos; y si la sub
clase pertenece al m ism o paquete que la superclase, tam bin tiene acceso a sus
m iem bros predeterm inados. Por ejem plo, el m todo com isiones de la clase
C C uentaA horro no puede acceder al atributo saldo de la clase C C uenta porque es
privado, pero s puede acceder a su m todo pblico reintegro.

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 de l a c u e n t a
G r e g o r i a n C a l e n d a r f e c h a A c t u a l = new G r e g o r i a n C a l e n d a r ( ):
int da = fechaActual,get(Calendar.DAY_0F_MONTH);

if ( d i a == 1) reintegro(cuotaM antenim iento);


CA PTU LO 10: SUBC LA SES E IN TERFACES 3 4 1

E sta restriccin puede sorprender, pero es as para im poner la encapsulacin.


Si una subclase tuviera acceso a los m iem bros privados de su superclase, entonces
cualquiera podra acceder a los m iem bros privados de una clase, sim plem ente d e
rivando una clase de ella. C onsecuentem ente, si una subclase quiere acceder a los
m iem bros privados de su superclase, debe hacerlo a travs de la interfaz pblica,
protegida, o predeterm inada en su caso, de dicha superclase.

ATRIBUTOS CON EL MISMO NOMBRE


C om o sabem os, una subclase puede acceder directam ente a un atributo pblico,
protegido, o predeterm inado en su caso, de su superclase. Q u sucede si defini
m os en la subclase uno de estos atributos, con el m ism o nom bre que tiene en la
superclase. P o r ejem plo, supongam os que una clase C laseA define un atributo
identificado por atributo_x, que despus redefinim os en una subclase ClaseB:

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 :

class ClaseB extends ClaseA


I
protected int a t r i b u t o _ x = 2:

public int mtodo_x()


I
return atributo_x * -10:

A hora, la definicin del atributo atributo_x en la subclase oculta la definicin


del atributo con el m ism o nom bre en la superclase. Por lo tanto, la ltim a lnea de
cdigo del ejem plo siguiente devolver el valor de atributo_x de ClaseB. Si este
atributo no hubiera sido definido en la subclase, entonces el valor devuelto sera el
valor de atributo_x de la superclase. Se puede observar que el tipo de control de
acceso puede m odificarse en cualquier sentido.
342 JA V A : C U R SO DE PROGRAM A CIN

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

A h o ra bien cm o procederam os si el m todo referenciado por el m todo j e


de la clase C laseB tuviera que acceder obligatoriam ente al dato atributo_jc de la
superclase? La solucin es sencilla: utilizar para ese atributo nom bres diferentes
en la superclase y en la subclase. N o obstante, aun habiendo utilizado el mismo
nom bre, tenem os una alternativa de acceso: utilizar la palabra reservada super.
Por ejem plo:

public in t mtodo_x()
I
return su p e r.atribu to_x * -10;
I

C om o se puede ver, podem os referirnos al dato atributo_x de la superclase


con la expresin:

super.atributo_x

A sim ism o, podram os referirnos al d ato atributo_x de la subclase con la ex


presin:

th is.atribu to_x

En cam bio, la expresin siguiente hace referencia al dato atributo_x de la


C lase A:

( ( C1a s e A ) t h i s ) . a t r i buto_x

La tcnica de realizar una conversin explcita u obligada es la que tendremos


que utilizar si necesitam os referim os a un m iem bro oculto perteneciente a una
clase p o r encim a de la superclase (una clase base indirecta).
C A P T U L O 10: SUBC LA SES E IN TERFA CES 3 4 3

REDEFINIR MTODOS DE LA SUPERCLASE

C uando se invoca a un m todo en respuesta a un m ensaje recibido por un objeto.


Java busca su definicin en la clase del objeto. La definicin del m todo que all
se encuentra puede pertenecer a la propia clase o puede haber sido heredada de
alguna de sus superclases (esto ltim o equivale a decir que si no la encuentra. Ja
va sigue buscando hacia arriba en la jerarqua de clases hasta que la localice).

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.

R edefinir un m todo heredado significa volverlo a escribir en la subclase con


el m ism o nom bre, la m ism a lista de parm etros y el m ism o tipo del valor retom a
do que tena en la superclase; su cuerpo ser adaptado a las necesidades de la sub
clase. Esto es lo que se ha hecho con el m to d o _ x del ejem plo expuesto en el
apartado anterior.

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.

En el m todo m a in de la clase Test del ejem plo anterior, se cre un objeto


objC laseB y se invoc a su m todo_y. C om o la clase del objeto, C laseB , no define
este m todo. Java ejecuta el heredado. A sim ism o, se invoc a su m todo_x\ en
este caso, existe una definicin para este m todo, que es la que se ejecuta.

C uando en una subclase se redefine un m todo de una superclase, se oculta el


m todo de la superclase, pero no las sobrecargas que existan del m ism o en dicha
superclase. Si el m todo se redefine en la subclase con distinto tipo o nm ero de
parm etros, el m todo de la superclase no se oculta, sino que se com porta com o
una sobrecarga de ese m todo. P or ejem plo, el m todo_x tal cual lo hem os redefi
nido en la subclase oculta al m todo del m ism o nom bre de la superclase. Pero si
lo hubiram os definido con distinto nm ero de parm etros, por ejem plo con uno,
segn se m uestra a continuacin, sera una sobrecarga.

public int m todo_x(int a) // m t od o de C l a s e B


I
return atributo_x * - a;
I

En el caso de que el m todo heredado por la subclase sea abstracto, com o su


cede en nuestro ejem plo acerca de las cuentas bancarias, es obligatorio redefinir-
lo, de lo contrario la subclase debera ser declarada tam bin abstracta.
344 JA V A : C U R SO DE PRO G R A M A CI N

A diferencia de lo que ocurra con los atributos redefinidos, el control de ac


ceso de un m todo que se redefine no puede m odificarse en cualquier sentido.
C om o regla, no se puede redefinir un m todo en una subclase y hacer que su con
trol de acceso sea m s restrictivo que el original. El orden de los tipos de control
de acceso de m s a m enos restrictivo es as: private, predeterm inado, protected y
public. A plicando esta regla, un m todo que en la superclase sea protected, en la
subclase podr ser redefnido com o protected o pub lic: si es p u b lic slo podr
ser redefnido com o public. Si es p riv a te no tiene sentido hablar de redefinicin,
porque no puede ser accedido nada m s que desde su propia clase.

Para acceder a un m todo de la superclase que ha sido redefnido en la sub


clase, igual que se expuso para los atributos, tendrem os que utilizar la palabra re
servada super. Por ejem plo, suponga que aadim os el siguiente m todo a la
C laseB :

public int mtodo_z()


I
a t r i b u t o _ x - s u p e r . a t r i b u t o _ x + 3;
return super.mtodo_x() + atributo_x;

C om o se puede observar, podem os referim os al m todo_x de la superclase


con la expresin:

super,mtodo_x()

Es im portante resaltar que su p e r puede ser utilizado slo desde dentro de la


clase que proporciona los m iem bros redefinidos.

A sim ism o, com o ya vim os cuando se expuso this. podram os referim os al


m todo_x de la subclase as:

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

En el ejem plo anterior, th is lgicam ente es una referencia a un objeto de la


C laseB ; esta referencia es convertida explcitam ente a un objeto de la C lase A ; pe
ro, independientem ente de esto, en Java, el m todo invocado, cuando se trate de
un m todo redefinido, siem pre pertenece a la clase del objeto no de la referencia;
por lo tanto, el m todo_x invocado ser el de la ClaseB.

CONSTRUCTORES DE LAS SUBCLASES


Sabem os q ue cuando se crea un objeto de una clase se invoca a su constructor.
T am bin sabem os que los constructores de la superclase no son heredados por sus
subclases. En cam bio, cuando se crea un objeto de una subclase, se invoca a su
constructor, que a su vez invoca al constructor sin parm etros de la superclase,
que a su vez invoca al constructor de su superclase, y a s sucesivam ente.

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:

nom bre_subclase( lista d e parm etros )


{
s u p e r( lista d e p a r m e tro s);
// cuerpo del constructor de la subclase
}

En la definicin genrica anterior correspondiente a un constructor con par


m etros de una subclase, se observa, por una parte, la utilizacin de la palabra re
servada s u p e r para invocar al constructor de la superclase, y p o r otra, el cuerpo
del constructor de la subclase. C uando desde un constructor de una subclase se
invoque al constructor de su superclase, esta lnea tiene que ser la prim era.

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

Si la superclase no tiene un constructor de form a explcita o tiene uno que no


requiere parm etros, no se necesita invocarlo explcitam ente, ya que Java lo invo
car autom ticam ente m ediante su p e r() sin argum entos. Por el contrario, s es ne
cesario invocarlo cuando se trate de un constructor con parm etros, para poder as
pasar los argum entos necesarios en la llam ada.

P o r ejem plo, aplicando la teora expuesta, vam os a aadir a la clase CCuen-


taA horro un constructor con parm etros. C untos parm etros debe tener este
constructor para iniciar todos los atributos del un objeto CCuentaAhorro^. Pues
tantos com o atributos heredados y propios tenga la clase; en nuestro caso un ob
je to C C uentaAhorro contiene los atributos nom bre, cuenta, sa ld o , tipoD elnters y
cuotaM antenim iento. Segn esto el constructor podra ser as:

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

La prim era lnea del m todo constructor anterior llam a al constructor de


C Cuenta. superclase de C CuentaAhorro. Lgicam ente, la clase C C uenta debe te
ner un constructor con cuatro parm etros del tipo de los argum entos especifica
dos. L a segunda lnea invoca al m todo asignarC uotaM anten para iniciar el
atributo cuotaM antenim iento de CCuentaAhorro.

E videntem ente, si slo se desea iniciar algunos de los atributos de un objeto,


hay que escribir los constructores adecuados tanto en la subclase com o en la su
perclase.

De acuerdo con los m todos constructores definidos en la clase CCuentaAho


rro, son declaraciones vlidas las siguientes:

public class Test


I
public static void m a in (S trin g [] args)
I
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 C u e n t a A h o r r o c l i e n t e 0 2 - new C C u e n t a A h o r r o ! " U n n o m b r e " ,
"Una c u e n t a " . 1 0 00 000 , 3 . 5 , 300);
// . . .

En este ejem plo, la sentencia prim era requiere en C C uentaAhorro un cons


tructor sin parm etros y en C C uenta otro. E n cam bio, la segunda sentencia re-
CA PTU LO 10: SUBC LA SES E IN TERFA CES 3 4 7

quiere en C C uentaAhorro un constructor con parm etros y en C C uenta otro que


se pueda invocar com o se indica a continuacin, con el fin de iniciar los atributos
definidos en la superclase, con los valores pasados com o argum entos.

superlnombre, cuenta, saldo, tipoln ters);

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.

DESTRUCTORES DE LAS SUBCLASES


A cabam os de ver que en Java, el constructor de una subclase invoca autom tica
m ente al constructor sin parm etros de su superclase. En cam bio, con los des
tructores (m todos finalize) no ocurre los mismo.

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

protected void fin alize O throw s Throwable // d e s t r u c t o r


1
System .out.println!"Recursos de C l a s e A liberados"):

class ClaseB extends ClaseA


I
protected int a t r i b u t o _ x = 2;

publ i c int mtodo_x()


I
return atributo_x * -10:
1

public int mtodo_z()


1
a t r i b u t o _ x = s u p e r . a t r i b u t o _ x + 3:
return super.mtodo_x() + atribu to_x:
I

protected void finalize!) t h r o w s T h r o w a b l e // d e s t r u c t o r


t
S y s t e m , o u t . p r i n t ri( " R e c u r s o s de C l a s e B liberados");
s u p e r . f i n a l i z e ( );
I
I

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 ):

Para ver cm o son invocados los destructores, el m todo m a in de la clase


T est crea un objeto de la C laseB referenciado p o r objC laseB y cuando finaliza el
trabajo con el m ism o asigna a la variable objC laseB el valor nuil con la intencin
de enviar el objeto referenciado p o r ella a la basura. Finalm ente fuerza al reco
lector de basura a que recoja la basura, lo que provocar la ejecucin de los des
tructores: prim ero el de la C laseB y despus el de la ClaseA.

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.

protected void f i n a l i z e ( ) throws T h r o w a b l e // d e s t r u c t o r


I
// N i n g u n a o p e r a c i n
s u p e r . f i n a l i z e ( ) ; // i n v o c a r a l m t o d o f i n a l i z e de l a superclase
I

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

_________ I ~ _______________ I____________


^ la s e ^ C C u e n t a C o r r ie ^ ^ ^ ^ ^ la s ^ C u e n ta A h o r r 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

El conjunto de clases as definido da lugar a una jera rq u a de clases. Cuando


cada subclase lo es de una sola superclase, com o ocurre en Java, la estructura je
rrquica recibe el nom bre de rbol de clases.

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.

L as reglas que podem os aplicar para m anipular la subclase CCuentaCorriente


de la superclase CCuenta o la subclase C C uentaC orrienteC onln de la superclase
C C uentaC orriente son las m ism as que hem os aplicado anteriorm ente para la sub
clase C C uentaAhorro de la superclase C C uenta, y lo m ism o direm os para cual
quier otra subclase que deseem os aadir. Esto quiere decir que para im plem entar
una subclase com o C C uentaC orrienteC onln, nos es suficiente con conocer a fon
do su superclase C C uentaC orriente sin im portarnos CCuenta.

O bserve que la clase C C uenta acta com o superclase de m s de una clase,


concretam ente de las clases C C uentaA horro y C C uentaC orriente.

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

reintegro R esta la cantidad especificada del saldo actual de la


cuenta e increm enta el nm ero de transacciones.
com isiones Se ejecuta los das uno de cada m es para cobrar el
im porte de las transacciones efectuadas que no estn
exentas y pone el nm ero de transacciones a cero.
intereses Se ejecuta los das uno de cada m es para calcular el
im porte correspondiente a los intereses/m es produci
dos y aadirlo al saldo. H asta 3000 euros al 0.5% . El
resto al inters establecido.

A plicando la teora expuesta hasta ahora y procediendo de form a sim ilar a


com o lo hicim os para construir la subclase C C uentaA horro, la definicin de la
clase C C uentaC orriente es la siguiente:

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

public void asignarlm portePorTransdouble imptrans)


I
if (im ptrans < 0)
I
S y s t e m . o u t .p r in t n ( "E r r o r : cantidad negativa");
352 JA V A: C U R SO DE PROGRAM A CIN

return:
1
importePorTrans = imptrans;

public double o b te n e r Im p o r t e P o r T r a n s()


(
return importePorTrans:

public void a sig n a rT ra n sE x e n ta sin t transex)


I
if (transex < 0)
(
System .out.p rintln("Error: cantidad negativa"):
return;
)
transExentas = transex;

public int obtenerTransExentas()


I
return tra n sE xe n ta s:

public void in gre sod o u b le cantidad)


I
supe r.ingreso(cantid ad):
transacciones++;

public void reintegrotdouble cantidad)


I
super.reintegro(cantidad);
tr a n s a c c i ones++;

public void c o m isio n e sO


I
// Se 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 de l a c u e n t a
G r e g o r i a n C a l e n d a r f e c h a A c t u a l = new G r e g o r i a n C a l e n d a r f );
i n t d a = f e c h a A c t u a l . g e t ( C a l e n d a r . D A Y _ 0 F _ M 0 N T H );
i f (da 1 )
1
int n = transacciones - transExentas:
i f (n > 0) r e i n t e g r o t n * im p o r t e P o r T r a n s ) ;
t r a n s a c c i o n e s = 0:
C A PTU LO 10: SUBC LA SES E IN TERFACES 3 5 3

p u b lic double intereses!)


I
G r e g o r i a n C a l e n d a r f e c h a A c t u a l - new G r e g o r i a n C a l e n d a r ! );
i n t d i a - f e c h a A c t u a l . g e t ( C a l e n d a r . D A Y _ 0 F _M 0 N T H ):

if (da !- 1) return 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 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.

La definicin correspondiente a esta clase se expone a continuacin:

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

p u b l i c C C u e n t a C o r r i e n t e C o n I n ( S t r i n g nom. S t r i n g c u e , double sal,


double t ip o , double im ptrans, i n t transex)
I
II I n v o c a r al c o n s t r u c t o r d e l a s u p e r c l a s e
supernom , cue. s a l . t i p o , im p tra n s. t r a n s e x ) ;

p u b lic double intereses!)


1
G r e g o r i a n C a l e n d a r f e c h a A c t u a l = new G r e g o r i a n C a l e n d a r ! );
in t da = fechaActual.get(Calendar.DAY_OF_MONTH):

if (da ! = 1 || e s t a d o ! ) < 3000) return 0.0:

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

// D e v o l v e r e l i n t e r s m e n s u a l por s i fuera necesario


return interesesProducidos:

//////////////////////////////////////////////////////////////////

La clase C C uenta es la superclase directa (o sim plem ente superclase) de


C C uentaA horro y de C C uentaC orriente, y es una superclase indirecta para
C C uentaC orrienteC onln. M ientras que una subclase tiene una nica superclase
C A PTU LO 10: SU B C LA SE S E INTERFACES 3 5 5

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.

U na subclase que redefina un m todo heredado slo tiene acceso a su propia


versin y a la publicada por su superclase directa. Por ejem plo, las clases C C uen
ta y C C uentaC orriente incluyen cada una su versin del m todo ingreso', y la
subclase C C uentaC orrienteC onln hereda el m todo ingreso de C C uentaC orrien
te. Entonces, C C uentaC orrienteC onln, adem s de a su propia versin, slo puede
acceder a la versin de su superclase directa por m edio de la palabra s u p e r (en
este caso am bas versiones son la m ism a), pero no puede acceder a la versin de su
superclase indirecta C C uenta (s u p e r.s u p e r no es una expresin adm itida por el
com pilador Java).

Segn lo expuesto las lneas de cdigo:

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

del m todo intereses de la clase C C uentaC orriente podran ser sustituidas p o r la


indicada a continuacin, puesto que el m todo ingreso de C Cuenta no acta sobre
las transacciones:

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

En cam bio, en el m todo intereses de la clase C C uentaC orrienteC onln no


podem os proceder de la m ism a form a porque desde esta clase no se puede acceder
a la versin de ingreso de CCuenta.

A continuacin se presenta una aplicacin con algunos ejem plos de operacio


nes con objetos de las clases pertenecientes a la jerarqua construida:

public class Test


I
public static void main( S t r i n g [] args)
I
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 !
" Un n o m b r e " , " U n a c u e n t a " , 1 0 0 0 0 , 3.5, 30);

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

En la aplicacin anterior se puede observar cm o el m todo m a in construye


dos objetos: clienteO l de la clase C C uentaAhorro y clienle02 de la clase C C uen
taC orrienteC onln.

Para co n struir clienteO l se ha utilizado el constructor C C uentaAhorro con ar


gum entos. U na vez construido, observe que responde a una serie de m ensajes eje
cutando los m todos del m ism o nom bre, unos heredados de su superclase, com o
obtenerN om bre, y otros propios, com o intereses.

En cam bio, para construir cliente02 se ha utilizado el constructor C C uentaC o


rrienteC onln sin argum entos. U na vez construido, puede tam bin observar que
responde a una serie de m ensajes ejecutando los m todos del m ism o nom bre, unos
heredados de su superclase directa, com o reintegro, otros heredados de su super
clase indirecta, com o asignarN om bre, y otros propios, com o intereses.

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.

REFERENCIAS A OBJETOS DE UNA SUBCLASE


Las referencias a objetos de una subclase pueden ser declaradas y m anipuladas de
la m ism a form a que las referencias a objetos de una clase cualquiera, tal y como
C A PTU LO 10: SUBC LA SES E IN TERFA CES 3 5 7

ya expusim os en el captulo 4. V eam os algunos ejem plos basados en la jerarqua


de clases que acabam os de construir:

public class Test


1
public static void m a in (S trin g [] args)
I
CCuentaCorriente c lie n te O I:
c l i e n t e O I = 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 0 .
10000. 3 .5 , 30);
/ / ...

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:

public class Test


(
public static v o i d ma i n S t r i n g [ ] a r g s )
1
CCuentaCorriente c lie n te O I:
c l i e n t e O I = new C C u e n t a C o r r i e n t e C o n I n ( " c l i e n t e O l " . " 1 2 3 4 5 6 7 8 9 0 ,
10000, 3 .5 . 1.0. 6);
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 ):
II...

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.

C uando accedem os a un objeto p o r m edio de una variable no del tipo del ob


jeto, sino del tipo de alguna de sus superclases (directa o indirectas) segn m ues
tra el ejem plo anterior, es el tipo de la variable el que determ ina qu m ensajes
puede recibir el objeto referenciado; dicho de otra form a, es este tipo el que de
term ina qu m todos pueden ser invocados por el objeto referenciado. C ules
son esos m todos? Pues los correspondientes al tipo de la variable que utilizam os
para hacer referencia al objeto, no los de la clase del objeto.

R esum iendo: cuando accedem os a un objeto de una subclase p o r m edio de


una referencia a su superclase, ese objeto slo puede ser m anipulado p o r ios m
todos de su superclase. P or ejem plo:

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.

En cam bio, cuando se invoca a un m todo que est definido en la superclase y


redefinido en sus subclases, la versin que se ejecuta depende de la clase del ob
jeto referenciado, no del tipo de la variable que lo referencia. P or ejem plo:

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

cliente - clie n te 02;


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 C o n l n . 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.

R ecuerde que cuando se invoca a un m todo que est definido en la supercla


se y redefinido en sus subclases, la versin que se ejecuta depende de la clase del
objeto referenciado, no del tipo de la variable que lo referencia.

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.

S egn lo expuesto, y en un intento de buscar una codificacin m s genrica,


pensem os en una m atriz de referencias en la que cada elem ento seale a un objeto
de alguna de las subclases d e la jerarq u a construida anteriorm ente. D e qu tipo
deben ser los elem entos de la m atriz? Segn el prrafo anterior deben de ser de la
clase C C uenta; de esta form a ellos podrn alm acenar indistintam ente referencias a
objetos de cualquiera de las subclases. Por ejem plo:

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.

La definicin correspondiente a esta clase se expone a continuacin:

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

private void unElementoMs(CCuenta[] clientesActuales)


I
nElementos - e l i e n t e s A c t u a l e s . l e n g t h ;
// C r e a r una m a t r i z c o n un e l e m e n t o ms
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 + 1 ] ;
// C o p i a r l o s c l i e n t e s q u e ha y a c t u a l m e n t e
f o r ( i n t i = 0; i < nE le m e ntos: i + + )
c l i e n t e s f i ] = e l i e n t e s A c t u a l e s [ i ];
nEle mentos++:

private void unElementoMenos(CCuenta[] clientesActuales)


I
i f ( el i e n t e s A c t u a l e s .1ength == 0) r e t u r n :
i n t k = 0:
nElem entos = el i e n t e s A c t u a l e s .1e n g t h :
// C r e a r una m a t r i z c o n un e l e m e n t o menos
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 - 1 ] ;
// C o p i a r l o s c l i e n t e s no n u l o s que h a y a c t u a l m e n t e
f o r ( i n t i = 0: i < nE le m e ntos: i + + )
i f ( e l i e n t e s A c t u a l e s C i ] != n u i l )
el i e n t e s [ k + + ] = e l i e n t e s A c t u a l e s [ i ];
n E l e m e n t o s - -:

public void insertarC lientet int i, CCuenta o b j e t o )


l
// A s i g n a r al e l e m e n t o i de l a m a t r i z , un n u e v o o b j e t o
i f ( i > = 0 && i < n E l e m e n t o s )
e l i e n t e s i ] = objeto:
else
S y s t e m . o u t . p r i n t l n " n d i c e f u e r a de l i m i t e s " ) ;
I

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

public int longitud*) I re tu r n nElementos: )

public void aadirtCCuenta obj)


I
// A a d i r un o b j e t o a l a m a t r i z
unElementoMscl i e n t e s ) ;
i n s e r t a r C l i e n t e * n E l e m e n t o s - 1. obj ):

p u b lic boolean e l i m i n a r ( S t r i n g cuenta)


I
II B u s c a r l a c u e n t a y e l i m i n a r e l o b j e t o
f o r ( i n t i = 0: i < n E l e m e n t o s : i + + )
i f ( c u e nta .co m p a re T o cliente s[i] . obtenerCuenta()) = = 0)
I
c l i e n t e s f i ] = n u i l ; // e n v i a r el objeto a la basura
unElem entoMenostclientes):
return true;
I
return false:

public int buscar*String str. int pos)


I
// B u s c a r un o b j e t o y d e v o l v e r s u p o s i c i n
S t r i n g nom. c u e n ;
i f ( s t r = = n u i l ) r e t u r n -1;
i f ( p o s < 0 ) p o s = 0:
f o r ( in t i = pos: i < nElementos: i++ )
I
// B u s c a r p o r e l nombre
nom = e l i e n t e s [ i ] . o b t e n e r N o m b r e * ):
i f (nom = n u il ) continu;
// s t r e s t c o n t e n i d a en nom?
i f (n o m . in d e x O f( s tr) > -1)
return i :
// B u s c a r p o r l a c u e n t a
cuen = el i e n t e s t i ] . o b t e n e r C u e n t a * );
i f (cuen == n u i l ) c o n t in u :
// s t r e s t c o n t e n i d a en c u e n ?
i f ( c u e n . i n d e x O f ( s t r ) > -1)
return i :
I
return - 1;

//////////////////////////////////////////////////////////////////
CA PTU LO 10: SUBC LA SES E IN TERFACES 3 6 5

A nalizando la clase C B anco, observam os que su constructor inicia la m atriz


clientes con 0 elem entos; que aadir un objeto (un cliente) a la m atriz se hace en
dos pasos: uno, increm entar la m atriz en un elem ento, y dos, asignar la referencia
al objeto al nuevo elem ento de la m atriz; que elim inar un objeto de la m atriz tam
bin se hace en dos pasos: uno, poner a nuil el elem ento de la m atriz que referen
cia al objeto q ue se desea elim inar (el objeto se enva a la basura para que sea
recogido por el recolector de basura), y dos, quitar ese elem ento de la m atriz de-
crem entando su tam ao en 1.

N o tar que la operacin de increm entar o decrem entar en un elem ento la m a


triz de referencias clientes, asigna un nuevo espacio de m em oria; el necesario para
el nuevo nm ero de elem entos. E ntonces q u sucede con el espacio que antes
estaba referenciado p o r clientes? Pues que queda sin referenciar, condicin sufi
ciente para que sea enviado a la basura y recogido p o r el recolector de basura.

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:

La operacin elegida ser identificada p o r una sentencia sw itch y procesada


de acuerdo al esquem a presentado a continuacin:

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

public static i n t menO I ... 1

public static void m a in (S trin g [] args)


I
// C r e a r un o b j e t o b a n c o v a c i o (con c e r o ele m entos)
C B a n c o b a n c o = new C B a n c o ) :

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

El listado com pleto de la aplicacin Test se m uestra a continuacin. Se puede


observar que la clase aplicacin utiliza tres m todos estticos: leerD atos, m en y
el m todo m ain .

El m todo leerD atos recibe com o parm etro un valor 1, 2 3 dependiendo


del tipo de objeto que se desee crear: C C uentaA horro, C C uentaC orriente, o
C C uentaC orrienteC onln. Lee los atributos correspondientes al tipo de cuenta ele
gido e invoca al constructor adecuado. El m todo devuelve una referencia al nue
vo objeto construido. Este m todo ser invocado cada vez que se elija la opcin
a adir una nueva cuenta.

El m todo m en visualiza el m en anteriorm ente m ostrado, y devuelve el en


tero correspondiente a la opcin elegida.

El m todo m a in crea el objeto banco e invoca repetidam ente al m todo m en


para perm itir elegir la operacin program ada que se desee realizar en ese instante
sobre el cliente correspondiente a la cuenta o nom bre especificado.

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 ;

public static i n t men!)


I
System .out.print("\n\n");
Sy ste m .o u t.p rin tln ("l. Saldo ) :
S y s t e m . o u t .p r in t ln ! "2. Buscar s ig u i e n t e " )
S y s t e m . o u t . p r i n t l n ! " 3 . I n g r e s o " ):
S y s t e m . o u t . p r i n t l n ! 4. R e i n t e g r o " ) :
S y s t e m . o u t . p r i n t l n ( " 5 . A a d i r " );
S y s t e m . o u t . p r i n t n ( " 6 . El i m i n a r " );
S y s t e m . o u t . p r i n t l n ( 7 . M a n t e n i m i e n t o " ) :
S y s t e m . o u t . p r i n t l n ( " 8 . S a l i r ):
S y s t e m . o u t . p r i n t l n ! ):
System .out.print!" Opcin: "):
i n t op:
do
op = L e e r . d a t o l n t ! );
w h i l e ( o p < 1 || op > 8 ) ;
r e t u r n op:

public static void m a in (S trin g [] args)


I
// 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:

// C r e a r un o b j e t o b a n c o v a c i o (con cero elementos)


C Ba n c o b a n c o = new C B a n c o ! ) :

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.

C undo un m todo no podr pasar a ser un m todo en lnea? C uando el


com pilador no sepa con exactitud a qu versin del m todo tiene que invocar.
V eam os; si com o en el ejem plo anterior, tenem os una m atriz de referencias a ob
jeto s de las subclases C C uentaAhorro, C C uentaC orriente o C C uentaC orriente
C onln, cm o sabe el com pilador a qu m todo inters, p o r ejem plo, tiene que
llam ar? El com pilador no puede saber esto. C uando esto sucede, el com pilador
produce cdigo que perm itir al intrprete Java consultar durante la ejecucin qu
m todo tiene que invocar. C om o el intrprete Java s sabe a qu objeto, C C uenta
A horro, C C uentaC orriente o C C uentaC orrienteC onln, se refiere cada uno de los
elem entos de la m atriz, el cdigo aadido por el com pilador ser suficiente para
determ inar qu m todo invocar para cada uno de los objetos.

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.

Definir una interfaz


U na interfaz consta de dos partes: el nom bre de la interfaz precedido por la pala
bra reservada in te rfa c e , y el cuerpo de la interfaz encerrado entre llaves. Esto es:
372 JA V A: C U R SO DE PROGRAM A CIN

[p u blic] in te rfa c e nom bre J n te r fa z e x te n d s superinterfaces


{
cuerpo de la interfaz
}

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 cuerpo de la interfaz puede incluir declaraciones de constantes y declara


ciones de m todos (no sus definiciones).

La palabra clave e x te n d s significa que se est definiendo una interfaz que es


una extensin de otras; tam bin se puede decir que es una interfaz derivada de
otras; estas otras se especifican a continuacin de e x ten d s separadas p o r com as.
C om o habr observado, a diferencia de las clases, una interfaz puede derivarse de
m s de u na superinterfaz. U na interfaz as definida hereda todas las constantes y
m todos de sus superinterfaces, excepto las constantes y m todos que queden
ocultos porque se redefinan.

El nom bre de una interfaz se puede utilizar en cualquier lugar donde se pueda
utilizar el nom bre de una clase.

Un ejemplo: la interfaz IFecha


En la jerarq u a de clases im plem entada anteriorm ente en este m ism o captulo, no
sotros declaram os las clases C C uentaA horro, C C uentaC orriente y C C uentaC o
rrienteC onln com o parte de un conjunto de clases para adm inistrar distintos tipos
de cuentas bancarias. T odas estas clases tienen varios m todos en com n; as que
para facilitar, no slo el diseo, sino el trabajo con m atrices de objetos de dichas
clases, nosotros im plem entam os una superclase genrica, C C uenta, que encapsula
los atributos y los m todos com unes a todas esas clases; incluso, alguno de esos
m todos, com o com isiones e intereses, no tena sentido definirlos en la superclase
porque deban ser despus particularizados para cada una de las subclases. Esto
nos condujo a definir esos m todos com o abstractos, lo que im plic definir la su
perclase tam bin abstracta.

L as interfaces, al igual que las clases y m todos abstractos, proporcionan


plantillas de com portam iento que se espera sean im plem entadas p o r otras clases.
Esto es, una interfaz Java declara un conjunto de m todos, pero no los define
(slo aporta los prototipos de los m todos). Tam bin puede incluir definiciones de
constantes.
C A PTU LO 10: SUBC LA SES E INTERFACES 3 7 3

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.

La clase G r e g o r ia n C a le n d a r es un proveedor de servicios; en nuestro ejem


plo. notificar el da a los objetos derivados de C C uenta cuando intenten ejecutar
sus m todos com isiones o intereses. Para ello, com o se m uestra a continuacin,
proporciona el m todo get que devuelve el tipo de dato (da, m es, etc.) solicitado:

public class GregorianCalendar extends Calendar


I
// . . .
public final int get(int tipo_de_dato) I ... 1
II...
I

Segn hem os planteando el problem a, cualquier objeto derivado de CCuenta


que quiera utilizar un objeto G r e g o r ia n C a le n d a r debe im plem entar el m todo
da proporcionado por la interfaz Fecha. Este m todo es el m edio utilizado por el
objeto G r e g o r ia n C a le n d a r para notificar al objeto derivado de CCuenta el da
actual. Segn lo expuesto la interfaz / Fecha puede tener el aspecto siguiente:

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 ;

public abstract int dfa():


public abstract i n t mes!);
public abstract i n t a o ( );
)
//////////////////////////////////////////////////////////////////

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.

Utilizar una interfaz


Para utilizar una interfaz hay que aadir el nom bre de la m ism a precedido p o r la
palabra clave im p le m e n ts a la definicin de la clase. La palabra clave im ple-
m ents sigue a la palabra clave extends, si existe.

S iguiendo con el ejem plo iniciado en el apartado anterior, una subclase de


C Cuenta com o C C uentaA horro que utilice la interfaz Fecha debe definirse as:

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

p u b lic double intereses!)


I
i f ( d i 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 ca 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 i p o D 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 );
// D e v o l v e r e l i n t e r s m e n s u a l p o r s i f u e r a n e c e s a r i o
return interesesProducidos:
C A PTU LO 10: SUBC LA SES E INTERFACES 3 7 5

/ / I m p l e m e n t a c i n de l o s m t odo s de l a interfaz IFecha


public int d a()
I
G r e g o r i a n C a l e n d a r f e c h a A c t u a l = new G r e g o r i a n C a l e n d a r ( );
return fechaActual.get(DIA_DEL_M ES);
I
public i n t mes() I r e t u r n 0: II no s e n e c e s i t a
public in t afloO I r e t u r n 0; I // no s e n e c e s i t a
I
//////////////////////////////////////////////////////////////////

C om o una interfaz slo aporta declaraciones de m todos abstractos, es nuestra


obligacin definir todos los m todos en cada una de las clases que utilice la in
terfaz. N o podem os elegir y definir slo aquellos m todos que necesitem os. De no
hacerlo, Java obligara a que la clase fuera abstracta. Se puede observar tam bin
cm o el acceso a las constantes definidas en la interfaz es directo.

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

p u b lic double inte resesO


I
if ( d 1a ( ) != 1) return 0.0;

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 om o la clase C C uentaC orriente im plem enta la interfaz Fecha, su subclase


C C uentaC orrienteC onln heredar los nuevos m todos y constantes. P or lo tanto,
no es necesario agregar a la definicin de esta clase la palabra clave im p lem en ts
m s el nom bre de la interfaz.

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

///////////////////////// 1 I I I I I I 1 1 ///////////////////// I I I I ///////

U na vez realizadas en nuestra jerarq u a de clases las m odificaciones pro


puestas com o consecuencia d e hab er aadido la interfaz Fecha, el resultado ob
tenido desde un punto de vista grfico es el siguiente:

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.

Clase abstracta frente a interfaz


Llegado a este punto, se preguntar en qu difiere una interfaz de una clase abs
tracta? Puesto que una interfaz es sim plem ente una lista de constantes y m todos
abstractos, sera equivalente la clase Fecha siguiente, a la interfaz F echal

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

La respuesta a la pregunta anterior es no. Si Fecha es una clase abstracta,


entonces todas las subclases de C Cuenta, com o C C uentaA horro, que quisieran
u tilizar su funcionalidad para interactuar con G r e g o ria n C a le n d a r tendran que
derivarse de ella. Pero sucede que las subclases a las que nos referim os ya tienen
una superclase y no pueden tener otra, ya que Java no perm ite la herencia m ltiple
de clases: s perm ite que una interfaz se derive de m ltiples interfaces. Por lo
tanto, en casos com o el presentado hay que utilizar una interfaz.

L o anterior es una explicacin prctica. U na explicacin conceptual puede ser


que G re g o ria n C a le n d a r no debe forzar a sus usuarios a establecer una relacin
entre clases. Esto es, no im porta la clase; lo nico que im porta es im plem entar
uno o m s m todos especficos. Al fin y al cabo, una interfaz no es m s que un
protocolo que una clase im plem enta cuando necesita utilizarlo.

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

Utilizar una interfaz como un tipo


U na interfaz es un nuevo tipo de datos; un tipo referenciado. P or lo tanto, el nom
bre de u na interfaz se puede utilizar en cualquier lugar donde pueda aparecer el
nom bre de cualquier otro tipo de datos.

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.

El siguiente ejem plo m uestra cm o tres clases no relacionadas, C la se l, Ca-


se2 y C lase3, p o r el hecho de im plem entar la m ism a interfaz Ixxx, perm ite definir
una m atriz de objetos de esas clases y aplicar la definicin de polim orfism o.

In te rfa z Ixxx

c C la s e l
J C la s e 3
J C la s e 2

public interface Ixxx


1
public abstract v o i d m ( ); // m t od o m
public abstract void p (); // m t od o p
CA PTU LO 10: SUBC LA SES E IN TERFA CES 3 7 9

public class Clasel implements Ixxx


(
public void m )
I
S y s t e m . o u t . p r i n t l n ' m t o d o m de C l a s e l " ) ;
I
public void p() II

public class Clase? implements Ixxx


(
public void m ()
I
S y s t e m . o u t . p r i n t l n m t od o m d e C 1 a s e 2 " ) ;
1
public void p() II

public c la ss Clase3 implements Ixxx


I
public void m()
I
S y s t e m . o u t . p r i n t l n " m t o d o m de C a s e 3 " );
)
public void p() II

public class Test


I
public static v o i d main (Stringf] args)
I ..................... . . . . . .
I x x x [ ] o b j s = n e w I x x x [ 3 ] / / m a t r i z d e r e f e r e n c i a s a o b j e t o s

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

Interfaces frente a herencia mltiple


A m enudo se piensa en las interfaces com o en una alternativa a la herencia m lti
ple. Pero la realidad es que am bos conceptos, interfaz y herencia m ltiple, son
bastantes diferentes, a pesar de que las interfaces pueden resolver problem as si
m ilares. En particular:
380 JA V A: C U R SO DE PROGRAM A CIN

D esde una interfaz, una clase slo hereda constantes.


D esde una interfaz, una clase no puede heredar definiciones de m todos.
L a jerarq u a de interfaces es independiente de la jerarq u a de clases. De he
cho. varias clases pueden im plem entar la m ism a interfaz y no pertenecer a la
m ism a jerarq u a de clases. En cam bio, cuando se habla de herencia m ltiple,
todas las clases pertenecen a la m ism a jerarqua.

Para qu sirve una interfaz


D espus de todo lo expuesto es posible que an no est claro cul es el sentido de
utilizar interfaces. Si analizam os el ejercicio realizado anteriorm ente basado en la
jerarq u a de clases C C uenta y en la interfaz Fecha, seguro que llegarem os a al
guna conclusin sim ilar a la siguiente: puesto que los m todos da, m es y ao
pertenecen a la subclase que los im plem enta y las constantes no son ningn obst
culo, para qu querem os la interfaz? Pensando as, para nada.

U na interfaz se utiliza para definir un protocolo de conducta que puede ser


im plem entado por cualquier clase en una jerarq u a de clases. La utilidad que esto
pueda tener puede resum irse en los puntos siguientes:

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.

En este caso, otros desarrolladores recibiran la clase com pilada y la interfaz


correspondiente.

Implementar mltiples interfaces


U na clase puede im plem entar una o m s interfaces. Por ejem plo:
CA PTU LO 10: SU B C LA SE S E IN TERFA CES 3 8 1

public class miClase implements inte rfazl, interfaz2. interfaz3


I
II...

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 difieren en el nm ero o tipo de sus parm etros, estam os en el


caso de una sobrecarga del m todo: im plem ente todas las sobrecargas.

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:

public class CPersona


I
// M i e m b r o s d e C P e r s o n a __
p r i v a t e c l a s s CFecha
1
// M i e m b r o s de C F e c h a
I
// O t r o s miembros de C P e r s o n a
I

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.

U na clase anidada es un m iem bro m s de la clase que la contiene. En el ejem


plo anterior la clase C Fecha es un m iem bro m s de C Persona y com o tal se le
aplican las m ism as reglas que para el resto de los m iem bros. Segn esto, C Fecha
tendr acceso al resto de los m iem bros de C Persona independientem ente de su
m odificador de acceso (decir CFecha. im plica a los m iem bros de C F echa); C F e
cha puede ser pblica, privada o protegida; puede ser esttica; etc.
382 JA V A: C U R S O DE PROGRAM A CIN

R ecuerde: un m iem bro esttico (static) es un m iem bro de la clase y uno no


esttico es un m iem bro del objeto; y com o ocurra con los m todos estticos, una
clase anidada esttica no puede referirse directam ente a un m iem bro del objeto,
slo puede hacerlo a travs de un objeto de su clase.

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.

U n objeto de una clase interna puede existir slo dentro de un objeto de su


clase externa. A sim ism o, puesto que se trata de un m iem bro de su clase externa,
tiene acceso directo al resto de los m iem bros de esa clase. Por ejem plo, una fecha
puede ser un m iem bro de los datos relativos a la identificacin de una persona;
entonces, la persona puede ser representada por una clase C Persona y la fecha por
una clase CFecha, com o puede observar en el cdigo m ostrado a continuacin:

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

public C P e r s o n a ( S t r i n g nom. int dd . int mm. int aa)


I
nombre = nom;
f e c h a N a c i m i e n t o = new C F e c h a d d . mm. a a ) :
I

public String obtenerNombret) ( r e t u r n n o mb r e : I

public String obtenerFechaNa()


I
return f e c h a N a c i m i e n t o . d 1a + " / " +
fechaNacimiento.mes + " / " +
fechaNacim iento.ao:

El siguiente ejem plo crea un objeto C Persona invocando al constructor de


esta clase, el cual, a su vez, invocar al constructor de C Fecha para crear el objeto
fech a N a cim ien to con la fecha pasada com o argum ento.

public class Test


I
public static void m a in ( S trin g [] args)
I
C P e r s o n a u n a P e r s o n a = new C P e r s o n a ( " S u n o m b r e " . 22. 2. 2002):
System .out. p rin tln (u n a Persona.obtenerNombre());
System .out.println(unaPersona.obtenerFechaNa());

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.

Clases definidas dentro de un mtodo


Java perm ite definir una clase dentro de un m todo. Por ejem plo, el m todo met-
C lase2 de la C lase2 m ostrada a continuacin incluye la definicin de una C lase3:

public class Clasel


I
public static v o i d main (Stringf] args)
I
384 JA V A : C U R SO D E PROGRAM A CIN

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

U na clase definida dentro de un m todo tiene unas reglas de acceso bastante


restrictivas. U n m todo de una clase definida dentro de otro m todo slo tiene ac
ceso a sus variables locales o parm etros form ales declarados fin al. En el ejem
plo, m e tC la se l tiene dos parm etros form ales, x e y, y dos variables locales, i y c.
Se puede observar que el m todo m etC lase3 de la clase C lase3 definida dentro de
m etC lase2 slo tiene acceso a las variables locales y parm etros de este que han
sido declarados final.

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

class Clase3 implements Interfaz


I
public void p() I S y s t e m . o u t . p r i n t l n( " m t o d o p. " ) ; 1
public void m() I S y s t e m . o u t . p r i n t l n ! " m t o d o m " ); )
I

public class Clasel


I
public static v o i d main (String[] args)
I
C l a s e 2 o b j = new C l a s e 2 ( ) :
I n t e r f a z i o b j = o b j . m e t C l a s e 2 ( ): // d e v u e l v e un o b j e t o C l a s e 3
i o b j , m ( ):
I
I

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.

U na alternativa al ejem plo planteado es d efinir annim a la clase utilizada


dentro del m todo (en el ejem plo Clase3). Por ser annim a, su definicin debera
ocupar el lugar donde se utiliza su nom bre para crear un objeto de la misma. Esto
es, la definicin y la creacin del objeto se haran bajo la siguiente sintaxis:

new Ixxx () { ... }

donde Ixxx es el nom bre de la interfaz que im plem enta la clase. Por ejem plo:

public In te rfa z m etClase2()


I
r e t u r n new I n t e r f a z C )

public void p ( ) 1 System .out.p rintln ("m todo p"): )


public void m () 1 S y s t e m . o u t . p r i n t l n t " m t o d o m " ): I
386 JA V A: CU R SO DH PRO G R A M A CI N

Se puede observar que la llam ada a n ew va seguida de la definicin de la cla


se y que no se utiliza el nom bre de la clase, sino el nom bre de la interfaz que la
clase im plem enta; notar que en este caso no interviene la palabra clave im ple-
m e n ts y que la sentencia r e tu r n finaliza con punto y com a.

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:

2xJy - xy3 + 8.25 m s 5x?y - 2 x 3y + 7xT - 3 igual a 5 x sy + 7x2 - xy3 + 5.25

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.

Q uizs se pregunte qu sentido tiene realizar este ejercicio, si no trata con


subclases. La respuesta es sencilla, este ejercicio es la antesala al ejercicio que a
continuacin se propone.

La clase C Term ino puede escribirse as:

import java.m a th .*:


//////////////////////////////////////////////////////////////////
// C l a s e C T e r m i n o : e x p r e s i n de l a f o r m a a . x An . y Am
// a es el c o e f i c i e n t e de t i p o d o u b l e .
// n y m s o n l o s e x p o n e n t e s e n t e r o s de x e y .
//
public class CTermino
I
private double c o e f i c i e n t e = 0.0: // c o e f i c i e n t e
private i n t exponenteDeX = 1 ; II e x p o n e n t e d e x
private i n t e x p o n e n t e D e Y = 1; // e x p o n e n t e d e y

p u b lic CTerm ino() II


p u b l i c CTerminot double co e f, int expx, int expy ) // c o n s t r u c t o r
I
c o e f ic ie n t e = coef;
exponenteDeX = expx;
ex pon en teD eY = expy;
CA PTU LO 10: SU B C LA SE S E IN TE R FA C E S 3 8 7

public CTerm ino(CTermino t) // c o n s t r u c t o r c o p i a


I
coeficiente = t.coeficiente:
exponenteDeX = t.exponenteD eX:
exponenteOeY = t.exponenteDeY :
I
p u b l i c CTermino c o p ia r< C T e rm in o t) // a s i g n a c i n
I
coeficiente = t.coeficiente:
exponenteDeX = t.exponenteD eX:
exponenteDeY = t . e x p o n e n t e D e Y ;
return th is;
1
public void a sig n a rC o e ficie n te (d o u b le coef) (c o e fic ie n te - coef;l
public double o b t e n e r C o e f ic i e n t e ( ) (re t u rn c o e f i c i e n t e : !
public vo id a s i g n a r E x p o n e n t e D e X ( i n t expx) (exponenteDeX - expx;|
public i n t o b te nerExp on en teD e X ) ( re t u rn exponenteDeX:!
public v o i d asig n a rE x p o n e n t e D e Y ( in t expy) (exponenteDeY - e x p y : l
public i n t o b te n e r E x p o n e n t e D e Y ( ) ( r e t u r n exponenteDeY:!
public void m ostrarTerm ino()
(
i f ( c o e f i c i e n t e = = 0) r e t u r n ;
// S i g n o
S t r i n g sterm = ( c o e f i c i e n t e < 0)
// C o e f i c i e n t e
i f ( M a t h . a b s ( c o e f i c i e n t e ) ! - 1)
s t e r m = s t e r m + M a t h . a b s ( c o e f i c i e n t e ):
// P o t e n c i a de x
i f ( e x p o n e n t e D e X > 1 || e x p o n e n t e D e X < 0)
sterm - sterm + " x A " + exponenteDeX;
e l s e i f ( e x p o n e n t e D e X - - 1)
sterm = sterm + " x " ;
II P o t e n c i a de y
i f ( e x p o n e n t e D e Y > 1 || e x p o n e n t e D e Y < 0 )
sterm = sterm + " y A" + exponenteDeY;
e l s e i f ( e x p o n e n t e D e Y 1)
sterm - sterm + " y " :
// M o s t r a r t r m i n o
System .out.printsterm ):

//////////////////////////////////////////////////////////////////

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.

S iguiendo con el desarrollo, el esqueleto de la clase C P olinom io puede escri


birse as:

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

public CPolinom iot)


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:
t r m i n o s = new C T e r m i n o n E l e m e n t o s ] :

private vo id unElementoMs(CTermino[] t rm in osA ct) 1 ... )


private void unElementoMenos(CTermino[] t rm in osA ct) I ... 1
public void insertarTerm inoCTe rm ino obj) I ... I
public boolean e lim in a rT e rm in o t in t i ) 1 ... I
public C T e r m i n o t ri ni n o E n i n t i ) I . . . I
public i n t l o n g i t u d O 1 re tu rn nElementos: I
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) ( . . . 1
public C P o l i n o m i o s u m a r ( C P o l i n o m i o pB ) I . . . 1
public void m o st ra rP o lin o m io () ! ... )
public do u b le v a l o r P o l o n o m i o d o u b l e x. do u b le y ) I . . . I
)
//////////////////////////////////////////////////////////////////

C om o se puede observar, la clase C P olinom io tiene dos atributos: trm inos


que es una m atriz de referencias a objetos C Term ino y nE lem entos que es un ente
ro que especifica el nm ero de trm inos del polinom io.
C A P T U L O 10: SU B C LA SE S E IN TERFA CES 3 8 9

Para crear un polinom io escribirem os una sentencia anloga a la siguiente:

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

Esta sentencia, invoca al constructor C P olinom io e inicia un polinom io con 0


elem entos, segn se puede observar en la clase CPolinom io.

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:

private void unElementoMs(CTermino[] trm inosAct)


I
nEle mentos = t r m i n o s A c t .1e n g t h ;
// C r e a r una m a t r i z c o n un e l e m e n t o ms
t r m i n o s = new C T e r m i n o [ n E l e m e n t o s + 1 ] ;
// C o p i a r l o s t r m i n o s q u e h a y a c t u a l m e n t e
f o r ( i n t i = 0: i < nE le m e ntos: i+ + )
t r m i n o s t i j = t r m i n o s A c t [ i ]:
n E 1e m e n t o s + + :

private void unElementoMenos(CTermino[] trm inosAct)


I
i f ( t rm in o sA c t.1ength == 0) return:
i n t k = 0;
n E l e m e n t o s = t r m i n o s A c t . 1e n g t h ;
II C r e a r una m a t r i z c o n un e l e m e n t o s menos
t r m i n o s = new C T e r m i n o [ n E l e m e n t o s - 1 ] :
// C o p i a r l o s t r m i n o s n o n u l o s que h a y a c t u a l m e n t e
f o r ( i n t i = 0: i < n E l e m e n t o s : i + + )
i f ( t r m in o s A c t f i] != n u il )
t r m i n o s [ k + + ] = t r m i n o s A c t t i ]:
n E 1ementos - - ;
I

Para aadir un nuevo trm ino en el polinom io escribirem os el m todo inser-


tarTerm ino, que perm ite insertar el trm ino pasado com o argum ento, en orden as
cendente del exponente de y a exponentes iguales de x , en orden ascendente de
y. Este m todo prim eram ente verifica si el coeficiente del trm ino a insertar es 0,
en cuya caso finaliza sin realizar ninguna insercin. Si el coeficiente es distinto de
0, verifica si el trm ino en x y a insertar ya existe, en cuyo caso sim plem ente suma
al coeficiente existente el del trm ino pasado com o argum ento; si el resultado de
esta sum a es cero, invoca adem s al m todo elim inarT erm ino para quitar ese tr
mino. Si el trm ino no existe, entonces lo inserta en el lugar adecuado. Para reali
zar esta operacin, prim ero llam a al m todo unElem entoM s (aade un elem ento
390 JA V A: C U R SO D E PROGRAM A CIN

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.

public void insertarTerminotCTermino obj)


I
// I n s e r t a r un n u e v o t r m i n o en o r d e n a s c e n d e n t e del
// e x p o n e n t e de x ; y a i g u a l e x p o n e n t e d e x , en o r d e n
// a s c e n d e n t e d e l e x p o n e n t e de y .
if ( o b j.o b t e n e rC o e fic ie n t e !) == 0 ) return:
int k = 10. i :
int ex p X = o b j . o b t e n e r E x p o n e n t e D e X t );
int e xp Y = o b j . o b t e n e r E x p o n e n t e D e Y t );
// S i e l t r m i n o en x y e x i s t e , s u m a r l o s c o e f i c i e n t e s
for ( i = n E l e m e n t o s - 1: i > = 0 : i - - )
(
if ( ex p X = t r m i n o s t i ] . o b t e n e r E x p o n e n t e D e X ! ) &&
exp Y = = t r m i n o s [ i ] . o b t e n e r E x p o n e n t e D e Y ( ) )
I
double coef = t r m i n o s t i ] .o b t e n e r C o e f ic ie n t e ! ) +
o b j . o b t e n e r C o e f i c i e n t e ! );
i f ( co ef != 0 )
t rm in osfi] . asignarCoeficiente(coef);
el se
e l i m i n a r T e r m i n o ( i );
return:
1
I
// S i e l t r m i n o en x y no e x i s t e , i n s e r t a r l o .
w h i l e ( M a t h . a b s ( e x p X ) > k || M a t h . a b s ( e xp Y ) > k ) k = k * 10:
// S e a a d e un e l e m e n t o v a c i o
unElem entoMs(trm inos);
i = n E l e m e n t o s - 2 : // i - n E l e m e n t o s - 1 v a l e n u i l
w h i l e ( i > = 0 && ( e x p X * k + e xp Y <
trm inosti].ObtenerExponenteDeXt) * k +
trmi n o s [ i ] . o b te n e rE x p o n e n te D e Y ( ) ) )
I
t rm in o s[i+l] = trm inosti];
i - -:
I
trm inos[i+l] = o b j;
C A PTU LO 10: SU B C LA SE S E IN TERFA CES 3 9 1

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.

p u b lic boolean e lim in a rT e r m in o (in t i)


I
// E l i m i n a r e l o b j e t o q u e e s t en l a posicin i
i f ( i > = 0 && i < n E l e m e n t o s )
I
t r m i n o s E i ] = n u i l : // e n v i a r el objeto a la basura
unElem entoMenos(trm inos);
re tu rn true;
I
return false:
I

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;

El m todo longitud devuelve el nm ero de trm inos del polinom io.

Para poder copiar un polinom io en otro escribirem os el m todo copiar espe


cificado a continuacin:

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:

t rm in o s[i] = p .trm inos[ i ]

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

El proceso de sum ar consiste en:

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.

p u b lic CPolinomio s u m a r ( C P o l i n o m i o pB)


I
/ / pR = p A . s u m a r ( p B ) . pA e s t h i s y pR e l r e s u l t a d o .
int i p a = 0 , i p b = 0 , k = 0:
int na = n E l e m e n t o s . nb = p B . n E l e m e n t o s ;
CA PTU LO 10: SUBC LA SES E IN TERFACES 3 9 3

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.

public void m o st ra rP o lin o m io {)


I
int i = nElementos:

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.

p u b lic double valorPo lo no m io(do u ble x, double y)


I
double v = 0:

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

public static CTermino leerTerm ino()


I
CTermino ptx = n u i l ;
double coef;
i n t expx, expy;
System .out.p rin t("C o e fi c ie n te : ");
c o e f = L e e r . d a t o D o u b l e t ):
S y s t e m . o u t . p r i n t " E x p o n e n t e en X: " ) ;
expx = 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 ( " E x p o n e n t e en Y: " ) ;
e x p y = L e e r . d a t o l n t );
S y ste m .o u t .p ri n t l n () :
i f ( c o e f = = 0 && e x p x = 0 && e x p y = = 0 ) return nuil:
p t x = new C T e r m i n o t c o e f . e x p x . e x p y ):
re turn ptx;

public static void m a in ( S t r in g [ ] args)


I
// D e f i n i r l o s p o l i n o m i o s a suma r
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 ( ):
C P o l i n o m i o p o l i n o m i o B = new C P o l i nomi o ( ) :
// D e c l a r a r una r e f e r e n c i a a l p o l i n o m i o r e s u l t a n t e
CPolinom io polinomioR;
// D e c l a r a r una r e f e r e n c i a a un t r m i n o c u a l q u i e r a
C T e r m i n o p t x = n u i l ; // p u n t e r o a un t r m i n o
// L e e r l o s t r m i n o s d e l p r i m e r s umando
S y s t e m . o u t . p r i n t t " T r m i n o s del p o li n o m i o A "
+ " ( p a r a f i n a l i z a r in t r o d u z c a 0 para e l \ n "
+ " c o e f i c i e n t e y p a r a l o s e x p o n e n t e s ) . \ n \ n );
p t x = 1e e r T e r m i n o t );
whi 1 e ( p t x ! = n u i l )
I
pol i n o m i o A . i n s e r t a r T e r m i n o t ptx );
p t x = 1e e r T e r m i n o t );
I
// L e e r l o s t r m i n o s d e l s e g u n d o s umando
S y s t e m . o u t . p r i n t l n ( "T rm ino s del p o li n o m i o B "
+ " ( p a r a f i n a l i z a r i n t r o d u z c a 0 para e l \ n "
+ " c o e f i c i e n t e y p a r a l o s e x p o n e n t e s ) . \ n \ n " );
p t x = 1e e r T e r m i n o t ) :
w h i 1e ( p t x ! = n u l 1 )
I
polinom ioB.insertarTerm inot ptx );
p t x = 1e e r T e r m i n o t ) :
I
// S u m a r l o s d o s p o l i n o m i o s l e d o s
p o lin o m io R = p o l i n o m i o A . sum ar( p o l i n o m i o B );

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

Se quiere escribir un program a para m anipular ecuaciones algebraicas o polin-


m icas dependientes de las variables ,v. y, z. Por ejem plo:

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 ^

De acuerdo con el enunciado y apoyndose en el ejercicio anteriorm ente re


suelto, construya las clases a las que hem os hecho referencia para que soporten al
m enos la m ism a funcionalidad que vio all y realice un program a sim ilar al ante
rior, para probar las clases construidas.
CA PTU LO 11
F.J.Cebilos/RA-MA

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

Bsicam ente, el esquem a anterior dice que si el cdigo de la. aplicacin no


puede realizar alguna operacin, se espera lance una excepcin que ser tratada
por el cdigo de tratam iento especificado para esa clase de excepcin, o en su
defecto por Java.
CA PTU LO 11: EXCEPCION ES 3 9 9

A lo largo de este captulo com probar que: el m anejo de excepciones reduce


la com plejidad de la program acin; los m todos que invocan a otros no necesitan
com probar valores de retorno; si el m todo invocado finaliza de form a norm al, el
que llam est seguro de que no ocurri ninguna situacin anm ala; etc.

EXCEPCIONES DE JAVA
D urante el estudio de los captulos anteriores, seguro que se habr encontrado con
excepciones com o las siguientes:

C lase de excepcin__________________ Significado


A rith m e tic E x c e p tio n U na condicin aritm tica excepcional ha
ocurrido. P or ejem plo, una divisin p o r 0.
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 U na m atriz fue accedida con un ndice
ilegal (fuera de los lm ites perm itidos).
N u llP o in te rE x c e p tio n Se intent utilizar n u il donde se requera
un objeto.
N u m b e rF o rm a tE x c e p tio n Se intento convertir una cadena con un
form ato inapropiado en un nm ero.

Q u es lo que ocurri entonces cuando durante la ejecucin d e su program a


se lanz una excepcin? S eguram ente el program a d ej de funcionar y Java vi
sualiz algn m ensaje acerca de lo ocurrido. Si no es esto lo que deseam os, ten
drem os que aprender a m anipular las excepciones.

Las excepciones en Java son objetos de clases derivadas de la clase T h ro w a -


ble definida en el paquete ja v a .la n g. P or ejem plo, cuando se lanza una excepcin
A rith m e tic E x c e p tio n , autom ticam ente Java crea un objeto de esta clase. La fi
gura siguiente m uestra algunas de las clases de la jerarq u a de excepciones:

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

Un objeto E r r o r se crea cuando ha ocurrido un problem a serio. N orm alm ente


se lanza u na excepcin de este tipo, cuando durante la ejecucin ocurre un error
que involucra a la m quina virtual de Java, por lo que una aplicacin norm al no
suele m anipular este tipo de excepcin.

La clase E x ce p ci n cubre las excepciones que una aplicacin norm al puede


m anipular. T iene varias subclases entre las que destacan: R u n tim e E x c e p tio n e
IO E x c e p tio n .

La clase R u n tim e E x c e p tio n cubre las excepciones ocurridas al ejecutar ope


raciones sobre los datos que m anipula la aplicacin y que residen en m em oria; se
trata de excepciones que se lanzan en tiem po de ejecucin, en contraposicin a las
que se lanzaran por causas no dependientes de la m quina virtual de Java, com o
sucedera cuando no se pudiera leer de un fichero del disco. Son ejem plos de ex
cepciones de este tipo: A rith m e tic E x c e p tio n o N u llP o in te rE x c e p tio n . Este gru
po de excepciones pertenece al paquete ja v a.lan g.

L a clase IO E x c e p t io n cubre las excepciones ocurridas al ejecutar una opera


cin de entrada o salida. Este grupo de excepciones pertenece al paquete java.io.

Las excepciones d e tiem po de ejecucin son excepciones im plcitas y se c o


rresponden con las subclases de R u n tim e E x c e p tio n y E r r o r . Se dice que son
im plcitas porque son lanzadas por la m quina virtual de Java y por lo tanto, los
m todos im plem entados en las aplicaciones no tienen que declarar que las lanzan,
y aunque lo hicieran, cualquier otro m todo que los invoque no est obligado a
m anejarlas. El resto de las excepciones, com o las que se corresponden con las
subclases de IO E x c e p tio n , son excepciones explcitas; esto significa que, si se
quieren m anipular, los m todos im plem entados en las aplicaciones tienen que de
clarar que las lanzan y en este caso, cualquier otro m todo que los invoque est
obligado a m anejarlas.

C om o ejem plo, recuerde que en las aplicaciones desarrolladas hasta ahora el


com pilador Jav a nunca nos oblig a m anejar una excepcin de la clase A r ith m e
ticE xception. pero s una excepcin de la clase IO E x c e p tio n . Un ejem plo lo te
nem os cada vez que en alguna parte del cdigo de nuestra aplicacin invocam os
al m todo re a d L in e de la clase B u ffe re d R e a d e r; esta obligacin surge de que
r e a d L in e declara q ue puede lanzar una excepcin de la clase IO E x c e p tio n :

public String readLineO th rows IOException


I
II...
CAPTULO 11: EXCEPCIONES 4 0 1

N o se preocupe si no le qued todo claro; a continuacin aprender con deta


lle cm o atrapar, crear y lanzar excepciones, adem s de otras cosas.

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.

P or ejem plo, recuerda la clase L eer desarrollada en el captulo 5? Segn


puede observar a continuacin, el m todo dato de esta clase invoca a re a d L in e
con el propsito de devolver un objeto S t r in g correspondiente a la cadena leda.
Segn se ha explicado anteriorm ente, re a d L in e puede lanzar una excepcin de la
clase IO E x c e p tio n . Para m anejarla hay que atraparla, para lo cual se utiliza un
bloque catch, y para poder atraparla hay que encerrar el cdigo que puede lan
zarla en un bloque try.

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 ) :

// L e e r . La e n t r a d a f i n a l i z a al pulsar la tecla Entrar


s d a t o = f 1 u j o E . r e a d L i n e ( );
I
catch(IOException e)
I
System .err.println"Error: " + e.ge tM e ssag e ));

return sdato: // d e v o l v e r e l dato tecleado

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

Lanzar una excepcin


L anzar una excepcin equivale a crear un objeto de la clase de la excepcin para
m anipularlo fuera del flujo norm al de ejecucin del program a. Para lanzar una ex
cepcin se utiliza la palabra reservada th ro w y para crear un objeto, new. Por
ejem plo, volviendo al m todo datos de la clase L eer expuesta anteriorm ente, si
ocurre un erro r cuando se ejecute el m todo r e a d L in e se supone que ste ejecuta
r una sentencia sim ilar a la siguiente:

if (error) t h r o w new I O E x c e p t i o n ( ):

E sta sentencia lanza una excepcin de la clase IO E x c e p t io n lo que im plica


crear un objeto de esta clase. U n objeto de stos contiene inform acin acerca de la
excepcin, incluyendo su tipo y el estado del sistem a cuando el error ocurri.

Atrapar una excepcin


U na vez lanzada la excepcin, el sistem a es responsable de encontrar a alguien
que la atrape con el objetivo de m anipularla. El conjunto de esos alguien es el
conjunto de m todos especificados en la pila de llam adas hasta que ocurri el
error. Por ejem plo, considerem os la siguiente aplicacin, que invoca al m todo
d ato de la clase L eer con la intencin de leer un dato:

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

C uando se ejecute esta aplicacin y se invoque al m todo dato , la pila de lla


m adas crecer com o se observa en la figura siguiente:
C A PTU LO 11: EX CEPCION ES 4 0 3

B u ffe re d R e a d e r.re a d U n e
J

Si al ejecutarse el m todo re a d L in e ocurriera un error, segn hem os visto


anteriorm ente, ste lanzara una excepcin de la clase IO E x c e p t io n que inte
rrum pir el flujo norm al de ejecucin. D espus, el sistem a buscara en la pila de
llam adas hacia abajo y com enzando p o r el propio m todo que produjo el error,
uno que im plem ente un m anejador que pueda atrapar esta excepcin. Si el sistem a
descendiendo por la pila de llam adas n o encontrara este m anejador, el program a
term inara.

Para im plem entar un m anejador para una clase de excepcin hay que hacer
las do s cosas que se indican a continuacin:

1. Encerrar el cdigo que puede lanzar la excepcin en un bloque try. En la cla


se L eer presentada anteriorm ente, el m todo dato tiene un bloque tr y que en
cierra la llam ada al m todo re a d L in e , adem s de a otras sentencias:

try
I
// ...
s d a t o = f l u j o E . r e a d L i n e ):
I

2. E scribir un bloque catch capaz de atrapar la excepcin lanzada. En la clase


Leer presentada anteriorm ente, el m todo dato tiene un bloque catch capaz de
atrapar excepciones de la clase IO E x c e p t io n y de sus subclases:

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

En este m anejador se observa un parm etro e que referencia al objeto que se


cre cuando se lanz la excepcin atrapada. Para m anipularla, adem s de escribir
el cdigo que considerem os adecuado, disponem os de la funcionalidad proporcio
nada por la clase IO E x c e p tio n , y a la que podrem os acceder m ediante el objeto e.
P or ejem plo, el m todo g e tM e ssa g e devuelve una cadena con inform acin acerca
de la excepcin ocurrida.
404 JA V A : C U R SO DE PR O G R A M A C I N

C uando se trata de m anejar excepciones, un bloque try puede estar seguido de


uno o m s bloques catch, tantos com o excepciones diferentes tengam os que m a
nejar. C ada catch tiene un parm etro de la clase T h ro w a b le o de alguna subclase
de sta. C uando se lance una excepcin, el bloque catch que la atrape ser aquel
cuyo parm etro sea de la clase o de una superclase de la excepcin. D ebido a esto,
el orden en el que se coloquen los bloques catch tiene que ser tal, que cualquiera
de ellos debe perm itir alcanzar el siguiente, de lo contrario el com pilador produci
ra un error.

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.

En cam bio, en el ejem plo siguiente, una excepcin de la clase E O F E x c e p tio n


ser atrapada por el prim er bloque catch; una excepcin d e la clase IO E x c e p t io n
ser atrapada por el bloque segundo; una excepcin de la clase F ile N o tF o u n d E x -
ception, subclase de IO E x c e p tio n , ser atrapada tam bin p o r el bloque segundo;
y una excepcin de la clase C la ssN o tF o u n d E x c e p tio n , subclase de Excep tio n,
ser atrapada p o r el bloque tercero.

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

Un m ancjador de excepcin, catch, slo se puede u tilizar justam ente a conti


nuacin de un bloque try o de otro m anejador de excepcin (bloque catch). Las
palabras clave try y catch. por definicin, van seguidas de un bloque que encierra
el cdigo relativo a cada una de ellas, razn por la cual es obligatorio utilizar lla
ves: {}.
C A P T U L O 11: EX CEPCION ES 4 0 5

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.

Para aclarar lo expuesto analicem os el siguiente ejem plo. Se trata de un m to


do para escribir en un fichero datos procedentes de una m atriz. R ecuerda la apli
cacin Test que escribim os en el captulo anterior que operaba sobre un objeto
C Banco? Pues, suponga ahora que querem os aadir al m en que presentaba esta
aplicacin, una opcin m s que perm ita escribir en un fichero en disco una lista
con los nom bres de los clientes del banco (en el captulo siguiente aprenderem os a
trabajar con ficheros). Para ello, aadirem os a la clase Test el m todo que se ex
pone a continuacin. D icho m todo se ejecutar cuando se seleccione esa opcin:

public static void e scrib rD a to sC B a n co banco. String fich)


1
P r i n t W r i t e r f c l i = n u l 1;
CCuenta c l i e n t e :
C L i s t a C l i e n t e s l i s t a = new C L i s t a C l i e n t e s ( b a n c o . 1 o n g i t u d ( ) ) :
try
I
for (in t i =0: i < b a n c o . 1o n g i t u d ( ) : i++)
I
c l i e n t e = b a n c o . e l i e n t e E n ( i );
1 ista.aadi r(cli e n t e . o b t e n e r N o m b r e (). i );
I
// A b r i r e l f i c h e r o p a r a e s c r i b i r . S e c r e a e l flujo f c 1i :
f e l i = new P r i n t W r i t e r ( n e w F i 1e W r i t e r ( f i c h ) ) ;
l i s t a . e s c r i b i r ( f c l i );
I
catch ( lOException e)
I
S y s t ern. out . p r i n t l n ( e . g e t M e s s a g e ( ) ) :

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:

1. El bloque tr y finalice de ejecutarse satisfactoriam ente.


2. Se lance una excepcin IO E x c e p tio n .
3. Se lance una excepcin 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 .

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.

Si hubiram os incluido un m anejador para el caso 3, podram os cerrar el fi


chero en los bloques try y catch y prescindir del bloque finally, pero a costa de
duplicar cdigo y hacer m enos legible el program a.

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

birD atos. Y p o r qu sucede esto? Porque el m todo F ile W r it e r (se trata de un


constructor) invocado por escribirD atos est definido en la biblioteca de Java as:

public F i 1e W r i t e r ( S t r i n g nombre_fichero) throws IO E xce p tio n


I
// C u e r p o d e l mt od o
I

La palabra reservada th ro w s perm ite a un m todo declarar las lista de excep


ciones (nom bres de las clases de excepcin separados por com as) que puede lan
zar. E sto tiene dos lecturas:

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.

2. E scribir un m todo que lance una o m s excepciones que no sean atrapadas


por el propio m todo, sino por los m todos que lo llam en; al fin y al cabo, lo
nico q ue estam os haciendo cuando procedem os de esta form a es no antici
pam os a las necesidades que pueda tener el usuario en cuanto al tratam iento
de la excepcin se refiere.

Siguiendo con lo expuesto, si no deseram os que el m todo escribirD atos


atrapara las excepciones debidas a las anom alas que pudieran ocurrir dentro de
l, tendram os que escribirlo as:

p u b l i c s t a t i c vo i d e s c r i b i r D a t o s C Ba n c o banco, S t r i n g f i c h ) throws I OException


I
P r i ntWri t e r f c l i = n u i l ;
CCuenta c l i e n t e :
C L i s t a C l i e n t e s l i s t a = new C L i s t a C l i e n t e s ( b a n c o . 1o n g i t u d ( ) ) ;
try
I
for (in t i = 0: i < b a n co .1o n g i t u d ( ); i++)
1
c l i e n t e = b a n c o . e l i e n t e E n i );
1i s t a . a a d i r ( c l i e n te . o b t e n e r N o m b r e ! ). i ):
I
// A b r i r e l f i c h e r o p a r a e s c r i b i r . Se c r e a el flujo fc li;
f e 1 i = new P r i n t W r i t e r t n e w F i 1e W r i t e r ( f i c h ) ) ;
1 i s t a . e s c r i b i r ( f c l i );
1
f i nal ly
I
// C e r r a r e l f i c h e r o
i f ( f e l i ! = n u i l ) f c l i . e l o s e ( );
408 JA V A: C U R S O DE PROGRAM A CIN

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 static void m a in{String[] args)


I
// ...
c a s e 8: // e s c r i b i r
try
I
f l u j o S . p r i n t t " F i c h e r o : " ) ; nombr e = Leer.datoO;
e s c r i b i r D a t o s t b a n c o . nombre):
I
catch ( I O E x c e p t i o n e)
I
System.out.pri ntln(e.getMessaget));
I
break;
II...
I

En el caso de tener que redefinir el m todo en una subclase, la declaracin de


cuntas excepciones que puede lanzar puede ser inferior, nunca superior; incluso
puede no lanzar ninguna.

CREAR Y LANZAR EXCEPCIONES


En alguna ocasin puede que necesitem os crear nuestras propias excepciones, a
pesar de que en la biblioteca de clases de Java hay una gran cantidad de ellas que
podem os utilizar sin m s. En cualquier caso, todos los tipos de excepcin se co
rresponden con una clase derivada de T h ro w a b ie , clase raz d e la jerarq u a de
clases de excepciones de Java. M s an, el paquete ja v a .Ia n g proporciona dos
subclases de T h ro w a b ie que agrupan las excepciones que se pueden lanzar, com o
consecuencia de los errores que pueden ocurrir en un program a, en dos clases:
E r r o r y Exceptio n. L os errores que ocurren en la m ayora de los program as se
corresponden con excepciones de alguna de las subclases de E xcep tio n, razn por
la que esta clase ser la superclase directa o indirecta de las nuevas clases de ex
cepcin que creem os, quedando la clase E r r o r reservada para el tratam iento de
los errores que se puedan producir en la m quina virtual de Java.

En general, crearem os un nuevo tipo de excepcin cuando queram os m anejar


un determ inado tipo de error no contem plado por las excepciones proporcionadas
por la biblioteca de Java. Por ejem plo, para crear un tipo de excepcin EValor-
N oV ulido. con la intencin de m anejar un error valor no vlido , podem os dise
ar una clase com o la siguiente:
CA PTU LO I I : EX CEPCION ES 4 0 9

p u b lic c l a s s EV alorN oV alido extends Exception


I
p u b l i c E V a l o r N o V a l i do <) I I
p u b l i c E V a l o r N o V a l i d o ( S t r i n g mensaje)
I
super(mensaje);
I
// ...
1

Segn se observa en este ejem plo, la superclase de la nueva clase de excep


cin E V alorN oV alido es Exception. e im plem enta dos constructores: uno sin pa
rm etros y otro con un parm etro de tipo S tr in g ; esto es lo m s habitual. El
parm etro de tipo S t r in g es el m ensaje que devolver el m todo g e tM e ssa g e he
redado de la clase T h ro w a b le a travs de Exception. Para ello el constructor
E V alorN oV alido debe invocar al constructor de la superclase y pasar com o argu
m ento dicha cadena, la cual ser alm acenada com o un m iem bro de datos de la cla
se T h ro w a b le .

La clase de excepcin E V alorN oV alido relacionada con el error valor no v


lido ya est creada. Lgicam ente, siem pre que se im plem ente una clase de ex
cepcin es porque durante el desarrollo de una clase, p o r ejem plo C M iC lase, se ha
observado que su cdigo para determ inados valores durante la ejecucin, puede
presentar una anom ala de la que los usuarios de esa clase deben ser inform ados
para que la puedan tratar.

Q u aspecto tiene CM iC lase? Segn lo expuesto, el cdigo que im plem enta


esta clase ante determ inados valores produce un error. H abr entonces que aadir
el cdigo que chequee si se producen esos valores y en caso afirm ativo lanzar la
excepcin program ada para este caso. Por 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...

Lanzar, una excepcin equivale a crear un objeto de ese tipo de excepcin. En


el ejem plo anterior se observa que la circunstancia que provoca el error es que el
410 JA V A : C U R SO D E PROGRAM A CIN

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.

public class CMiClase


I
// ...
public void m(int a) throws EValorNoValido
I
11...
I
II...
I

O tra alternativa es que el propio m todo que lanza la excepcin la atrape, co


m o puede observar en el ejem plo siguiente. Lo que sucede es que escribir un m
todo que lance una o m s excepciones y l m ism o las atrape es anticiparnos a las
necesidades que pueda tener el usuario de la clase que proporciona ese m todo, en
cuanto al tratam iento de la excepcin se refiere.

public class CMiClase


l
/ / ...
public void m(int a)
i
11...
try
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 cero"):
I
catch ( E V a l o r N o V a l i d o e)
I
S y s t e m . o u t . p r i n t l n ( e . g e t M e s s a g e ( )):
1
11...
I
II

C om binar am bas form as (declarar la excepcin y adem s atraparla) no sirve


de nada, porque si un m todo lanza una excepcin y la atrapa, en el supuesto de
CA PTU LO 11: EX CEPCION ES 4 1 1

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:

public class Test


I
public static void m a in (S trin g [] args)
I
i n t x = 0:
C M i C l a s e o b j = new C M i C l a s e O :
try
I
obj .m(x);
)
catch ( EValorNoValido e)
I
S y ste m .o ut.p r i n t l n ( e .g e tM e ssa g e ()):
1
System .out.println("C ontina la ejecucin");
)
I

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.

C uando un m todo utilizando th ro w lanza una excepcin, crea un objeto de la


clase de excepcin especificada, que interrum pe el flujo de ejecucin del progra
m a y vuelve por la pila de llam adas hasta encontrar uno que sepa atrapar la e x
cepcin (que contenga un bloque catch con un argum ento de la clase de la
excepcin o de alguna de sus superclases). La ejecucin del program a se transfie
re entonces, directam ente al m todo que atrap la excepcin para que ejecute el
m anejador. Si el m anejador, una vez ejecutado, perm ite que la aplicacin conti
ne, la ejecucin se transfiere a la prim era lnea ejecutable que haya a continua
cin del ltim o m anejador del bloque try. Segn esto, cuando se ejecute el
m todo m a in del ejem plo anterior se obtendr el siguiente resultado:

Error: valor cero


Contina la ejecucin
412 JA VA : C U R SO DE PRO G R A M A CI N

Si un m todo lanza una excepcin y en la vuelta p o r la pila de llam adas no se


encuentra uno que la atrape, el program a finalizar. En cam bio, si se encuentra un
m anejador para esa excepcin, se ejecuta. E n el supuesto de que en la pila de lla
m adas quedaran otros m todos que pudieran atraparla, n o sern tenidos en cuenta;
esto es, slo se tiene en cuenta el m anejador del m todo por el que haya pasado el
flujo de control m s recientem ente.

A su vez, si el m todo contiene una lista de m anejadores slo se ejecutar el


correspondiente a la excepcin lanzada; esto es, el com portam iento es el m ismo
que el de una sentencia sw itch, pero con la diferencia de que los case necesitan
sentencias b re a k y los catch no.

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.

U na excepcin se considera m anejada desde el m om ento en que se entra en su


m anejador, as que cualquier otra excepcin lanzada desde el cuerpo de ste, de
ber ser atrapada por algn otro m todo cuya llam ada se encuentre en la pila de
llam adas; si la excepcin no es atrapada, el program a finaliza. Esto explica por
qu el siguiente cdigo no provoca un bucle infinito:

public void otroMtodot) th rows EValorNoValido


I
// ...
try
I
// ...
I
c a t c h ( E V a l o r N o V a l i d o e)

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

CUNDO UTILIZAR EXCEPCIONES Y CUNDO NO


N o todas los program as necesitan responder lanzando una excepcin a cualquier
situacin anm ala que se produzca. P or ejem plo, si partiendo de unos datos de
entrada estam os haciendo una serie de clculos m s o m enos com plejos con la
nica finalidad de observar unos resultados, quizs la respuesta m s adecuada a
un erro r sea interrum pir sin m s el program a, no antes de haber lanzado un m en
saje apropiado y haber liberado los recursos adquiridos que an no hayan sido li
berados. O tro ejem plo, podem os utilizar la clase de excepcin A r r a y ln d e x O u t o f-
B o u n d s para m anejar el error que se produce cuando se rebasan los lm ites de una
m atriz, pero es m s fcil utilizar el m iem bro le n gth de la m atriz para prevenir que
esto no suceda.

En cam bio, si estam os construyendo una biblioteca estam os obligados a evitar


todos los errores que se puedan producir cuando su cdigo sea ejecutado por
cualquier program a que la utilice.

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.

La clase de excepcin O u t O f M e m o r y E r r o r pertenece a la jerarq u a cuya


clase raz es E r r o r . A nteriorm ente se expuso que la jerarq u a derivada de la clase
E r r o r estaba reservada p ara el tratam iento de los errores que se puedan producir
en la m quina virtual de Java. El error de falta de m em oria para asignacin es un
erro r tpico q ue puede surgir en un program a que necesite reservar repetidas veces
bloques de m em oria de un tam ao considerable.

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.

public class CListaTfnos


(
p r i v a t e C P e r s o n a [ ] 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 de e l e m e n t o s de l a m a t r i z

private CPersona a s ig n a rM e m o ria in t nElementos)


I
try
I
return new C P e r s o n a f n E l e m e n t o s ] ;
1
catch ( O u t O f M e m o r y E r r o r e)
I
S y s t e m . o u t .p r in t ln ( e . g e t M e s s a g e ( ));
re tu rn 1i s t a T e l f o n o s ;
I
I

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

private void unElementoMs(CPersona[] listaActual)


I
nEle mentos = 1i s t a A c t u a l .1e n g t h ;
1 is t a T e l f o n o s = a signarM em oria(nElem en tos + 1):
// C o p i a r l a l i s t a a c t u a l
f o r ( i n t i = 0: i < n E l e m e n t o s : i + + )
1 i s t a T e l f o n o s [ i ] = 1 i s t a A c t u a l [ i 3:
nElementos++:

private void unElementoMenos(CPersona[] listaActual)


I
i f (1 i s t a A c t u a l . 1 e n g t h = = 0 ) r e t u r n ;
i n t k = 0;
nEle mentos = 1 i s t a A c t u a l .1ength ;
1ist a T e l f o n o s = as1gnarMemoria(nElementos - 1);
// C o p i a r l a l i s t a a c t u a l
f o r ( i n t i = 0; i < n E l e m e n t o s : i + + )
C A PTU LO I I: EX CEPCION ES 4 1 5

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.

Al principio de este captulo explicam os el m anejador de excepciones que in


cluye el m todo datos. C om o ejercicio se trata ahora de explicar y m odificar los
m anejadores de excepciones incluidos en el resto de los m todos.

El m todo d atoShort fue im plem entado de la form a siguiente:

public static short datoShortO


I
try
I
return S h o r t . p a r s e S h o r t ( d a t o ( ));
I
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 S h o r t . M I N _ V A L U E ; // v a l o r ms p e q u e o
I
416 JA VA : C U R S O DE PROGRAM A CIN

Este m todo devuelve el valor retornado a su vez por el m todo p a rse S h o rt


de la clase Sh o rt, resultado de co n v eitir la cadena de caracteres devuelta por dato.
Pero qu ocurre si la cadena de caracteres devuelta por dato no se corresponde
con un sh o r t? Pues que al ejecutarse el m todo p a rse S h o rt, Java lanza una ex
cepcin N u m b e rF o rm a tE x c e p tio n que es atrapada por el m anejador, que de
vuelve el valor S h o r t . M IN _ V A L U E .

U na alternativa al m anejador anterior podra ser otro que ante un dato no v


lido (por ejem plo: xxx; 3.5; 3,5; etc.) solicitara teclear un dato correcto. H arem os
una excepcin para el carcter fin de fichero (C trl+ Z ). En este caso, dato devuel
ve n u il (porque re a d L in e devuelve n u il) seal para que nuestro m todo devuelva
un valor que sirva para identificar que se puls Ctrl+Z; conviene, si es posible,
que este valor no pertenezca al conjunto de valores vlidos que se quiera leer. De
esta form a, podrem os u tilizar C trl+ Z com o m arca para finalizar una entrada m a
siva de datos. Segn esto, podem os reescribir el m todo datoShort as:

public static short datoShortO


!
try
I
S t r in g sdato = d a t o O ;
i f (sdato = nu il)
I
S y s t e m . o u t . p r i n t l n t );
r e t u r n S h o r t .MIN_VA L U E ;
1
el se
return Short.parseShort(sdato):
I
c a t c h ( N u m b e r F o r m a t E x c e p t i on e )
(
System .out.p rint"Ese dato no es v l i d o . Teclee otro: "):
r e t u r n d a t o S h o r t );

C om o ejem plo, el siguiente cdigo, utilizando el m todo anterior, perm ite in


troducir datos de tipo in t hasta pulsar las teclas Ctrl+Z:

i n t eof = Inte ger.M IN _ V A LU E , i = 0;


i n t [ ] a = new i n t [ 1 0 0 ]:

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

System .out.p rin t("D a to int: "):

A nlogam ente podram os escribir un m anejador para el m todo dato,Float:

public static float datoFloat)


I
try
I
S t r i n g s d a t o = d a t o ( ):
i f ( sdato = n u il)
I
S y s t e m . o u t . p r i n t l n );
r e t u r n F l o a t . N a N : // No e s un Nmero: valor float.
I
el se
I
F l o a t f = new F l o a t ( s d a t o ) :
r e t u r n f . f 1o a t V a l u e ( ):

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 ):

Si tenem os en cuenta que F loat(dato()) lanza la excepcin N u llP o in terE x -


c e p tio n cuando el m todo d ato devuelve nuil, el m todo anterior podra escribir
se tam bin as:

public static float datoFloat)


I
try
I
F l o a t f = new F l o a t d a t o ) ) :
r e t u r n f . f 1o a t V a l u e );
I
catchNumberFormatException e)
I
System .out.p rint"Ese dato no es v l i d o . Teclee otro: ");
r e t u r n d a t o F l o a t ):
I
c a t c h N u l l P o i n t e r E x c e p t i o n e)
I
return Float.NaN; // No e s un Nmero: valor float.
418 JA VA : C U R SO DE PROGRAM A CIN

C om o ejem plo, el siguiente cdigo utilizando el m todo anterior perm ite in


troducir datos de tipo flo a t hasta pulsar las teclas Ctrl+Z:

boolean eof = true;


f l o a t l ] a = new f 1o a t [ 1 0 0 ] :
i n t i = 0:

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

L a variable e o f se ha utilizado sim plem ente por m otivos didcticos. Q uiere


esto decir que la sentencia w hile podra escribirse tam bin as:

while (i < 100 && F l o a t . i s N a N ( a [ i ] = Leer.datoFloat()))


(
i++:
System .out.print("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 clase E Saldolnsuficiente tendr dos atributos, uno de la clase C Cuenta para


hacer referencia a la cuenta que caus el problem a, y otro de tipo d o u b le para al
m acenar la cantidad solicitada. A sim ism o tendr un constructor y el m todo m en
saje. El constructor E Saldolnsuficiente tendr dos parm etros que harn referen
cia a la cuenta causante del problem a y a la cantidad solicitada. El m todo m en
saje no tiene argum entos, generar un m ensaje de error basado en la inform acin
alm acenada en los atributos y devolver un objeto S tr in g con ese m ensaje.

C uando haya finalizado pruebe la jerarq u a de la clase C C uenta ju n to con la clase


C B anco que tam bin im plem entam os en ese captulo.
CA PTU LO 12
FJ.CebalIos/RA-MA

TRABAJAR CON FICHEROS


T odos los program as realizados hasta ahora obtenan los datos necesarios para su
ejecucin de la entrada estndar y visualizaban los resultados en la salida estn
dar. Por otra parte, una aplicacin podr retener los datos que m anipula en su es
pacio de m em oria, slo m ientras est en ejecucin; es decir, cualquier dato
introducido se perder cuando la aplicacin finalice.

Por ejem plo, si hem os realizado un program a con la intencin de construir


una agenda, lo ejecutam os y alm acenam os los datos nom bre, apellidos y telfono
de cada uno de los com ponentes de la agenda en una m atriz, los datos estarn dis
ponibles m ientras el program a est en ejecucin. Si finalizam os la ejecucin del
program a y lo ejecutam os de nuevo, tendrem os que volver a introducir de nuevo
todos los datos.

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

D esde el punto de vista inform tico, un fichero o archivo es una coleccin de


inform acin que alm acenam os en un soporte m agntico para poderla m anipular
en cualquier m om ento. E sta inform acin se alm acena com o un conjunto de regis
tros, conteniendo todos ellos, generalm ente, los m ism os cam pos. C ada cam po al
m acena un dato de un tipo predefinido o de un tipo definido por el usuario. El
registro m s sim ple estara form ado por un carcter.

P o r ejem plo, si quisiram os alm acenar en un fichero los datos relativos a la


agenda de telfonos a la que nos hem os referido anteriorm ente, podram os disear
cada registro con los cam pos nom bre, direccin y telfono. Segn esto y desde un
punto de vista grfico, puede im aginarse la estructura del fichero as:

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

En program acin orientada a objetos, hablarem os de objetos m s que de re


gistros, y de sus atributos m s que de cam pos.

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.

Para dar soporte al trabajo con ficheros, la biblioteca de Java proporciona va


rias clases de entrada/salida (E/S) que perm iten leer y escribir datos a, y desde, fi
cheros y dispositivos (en el captulo 5 trabajam os con algunas de ellas).
CAPTULO 12: T R A B A JA R C O N FICHEROS 4 2 1

VISION GENERAL DE LOS FLUJOS DE E/S


La com unicacin entre el program a y el origen o el destino de cierta inform acin,
se realiza m ediante un flu jo de inform acin (en ingls stream ) que no es ms que
un objeto que hace de interm ediario entre el program a, y el origen o el destino de
la inform acin. Esto es, el program a leer o escribir en el flu jo sin im portarle
desde dnde viene la inform acin o a dnde va y tam poco im porta el tipo de los
datos q ue se leen o escriben. Este nivel de abstraccin hace que el program a no
tenga que saber nada ni del dispositivo ni del tipo de inform acin, lo que se tradu
ce en una facilidad m s a la hora de escribir program as.

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

El paquete ja v a .io de la biblioteca estndar de Java, contiene una coleccin


de clases que soportan estos algoritm os para leer y escribir. Estas clases se divi
den en d o s grupos distintos, segn se m uestra en la figura siguiente. El grupo de
la izquierda ha sido diseado para trabajar con datos de tipo byte (8 bits) y el de
la derecha con datos de tipo c h a r (16 bits). A m bos grupos presentan clases anlo
gas que tienen interfaces casi idnticas, por lo que se utilizan de la m ism a m anera.
422 JA VA : C U R S O DE PRO G R A M A CI N

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 .

Sin em bargo, a m enudo es m s conveniente agrupar las clases segn su fina


lidad en vez de por el tipo de datos que leen o escriben (caracteres o bytes). Desde
este punto de vista distinguim os flujos que sim plem ente perm iten leer y escribir
datos y flujos que, adem s, procesan la inform acin leda o escrita.

Flujos que no procesan los datos de E/S


La tabla siguiente lista las subclases que perm iten definir flujos para leer o escri
bir inform acin en un m edio sin realizar ningn proceso aadido:

M edio Flujo de caracteres F lujo de bytes

M em oria C harA rrayR eader B y te A rray Inpu tS tream


C harA rrayW riter B yteA rrayO utputStream

StringR eader StringB ufferlnputStream


StringW riter

Fichero FileR eader FilelnputStream


FileW riter FileO utputStream

Tubera PipedR eader PipedlnputS tream


PipedW riter PipedO utputStream
C A PTU LO 12: TRA BA JA R C O N R C H E R O S 4 2 3

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.

El siguiente ejem plo m uestra cm o utilizar las clases C h a r A r r a y R e a d e r y


C h a r A r r a y W r it e r . El resto de las clases expuestas en la tabla anterior se utilizan
de form a anloga.

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

Q u hace este program a:


1. A lm acena datos en una m atriz m i.
2. A bre un flujo de entrada desde la m atriz m i . E ntonces, el program a puede
leer datos de este flujo de form a sim ilar a com o lo hace del flujo estndar de
entrada.
3. A bre un flujo de salida hacia una m atriz tem poral. C om o el tam ao de la m a
triz no ha sido especificado, ste se ajustar a la cantidad de inform acin que
se enve al flujo. D e esta form a, el program a puede escribir datos en este flujo
de form a sim ilar a com o lo hace en el flujo estndar de salida.
4. Lee datos del flujo abierto desde m i , flujoE, y los escribe en el flujo de salida,
flu jo S .
5. C opia los datos enviados a flu jo S en una m atriz m 2 y la m uestra.

Flujos que procesan los datos de E/S


La tabla siguiente lista las subclases que perm iten definir flujos para leer o escri
bir inform acin en un m edio, adem s de realizar alguna operacin com o aadir un
buffer, un filtro, realizar una conversin, etc.:

Operacin Flujo de caracteres Flujo d e bytes

E stablecer un B ufferedR eader B ufferedlnputStream


buffer B ufferedW riter B ufferedO utputStream

E stablecer un FilterReader FilterlnputStream


filtro FilterW riter FilterO utputStream
C onversin InputStream R cader
(bytes - cars.) O utputStream W riter

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

M irar anticipa PushbackR eader PushbacklnputStream


dam ente

Escribir PrintW riter PrintStream


CA PTU LO 12: TRA B A JA R CON FIC H ER O S 4 2 5

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.

A lguno de los m todos que proporciona la clase P u s h b a c k R e a d e r son:

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.

Si echam os una ojeada al m todo dato de la clase L eer observarem os que de


fine un flujo local. Pero los m todos que ahora vam os a aadir necesitan leer de
ese m ism o flujo; por lo tanto, tendrem os que declararlo com o un m iem bro de la
clase; dicho m iem bro tendr que ser declarado esttico puesto que los m todos
tam bin son estticos. R ecuerde que esto lo hicim os as para poder utilizar las ca
pacidades que proporciona la clase L eer sin necesidad de tener que utilizar un
objeto de la misma.

Para po d er im plem entar la capacidad de m irar cul es el siguiente carcter en


la entrada, el flujo debe de ser de la clase P u sh b a c k R e a d e r. El constructor de
esta clase requiere un argum ento que haga referencia a un objeto, origen de los
datos a leer, de la clase R e a d e r o de alguna de sus subclases y opcionalm ente
acepta un segundo argum ento que especifica el tam ao del buffer para alm acenar
los caracteres devueltos por el m todo u n re a d de P u sh b a c k R e a d e r, que por
om isin es uno. Por lo tanto, la clase L eer puede ser ahora as:
426 JA VA : CU R SO D E PROGRAM A CIN

import j a v a . i o . * :

public class Leer


1
// O 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 : flujoE
p r i v a t e s t a t i c InputStreamReader i s r -
new l n P u t S t r e a m R e a d e r ( S y s t e m . i n ) :
private static P u s h b a c k R e a d e r f l u j o E - new P u s h b a c k R e a d e r ( i s r ) :

public static void lim piar!)


I
// lim piar flujoE
I

public static char m irar!)


I
// r e t o r n a r e l primer car cter d is p o n ib le sin extraerlo
I

public static char c a r c te r !)


I
II d e v o l v e r e l siguiente c a r c t e r de l a entrada
I

public static String dato!)


I
// d e v o l v e r un S t r i n g que almac en e el dato tecleado
I

II...
I

A hora, la clase L eer define un m iem bro flu jo E de la clase P u sh b a c k R e a d e r


que se corresponde con el flujo abierto desde del origen de los caracteres. C om o
el origen real de los datos va a ser el teclado (dispositivo vinculado con System .in
que proporciona bytes), es preciso conectar am bos flujos por otro que convierta
los bytes procedentes del teclado a los caracteres que espera flu jo E . De esto se en
carga isr:

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

La clase In p u t S t r e a m R e a d e r establece un puente para pasar flujos de bytes


a flujos de caracteres.

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

Para lim piar el flujo de entrada definido por la clase L e e r aadirem os al m


todo lim piar el cdigo que se m uestra a continuacin. L o nico que hace este
m todo es leer caracteres, uno a uno, m ientras haya caracteres disponibles, ya que
cada carcter ledo es autom ticam ente elim inado del flujo de entrada.

public static void lim piarO


1
in t car - 0:
try
I
while ( f l u j o E . r e a d y ( )) f l u j o E . r e a d ( ); // l i m p i a r flujoE
1
c a t c h t I O E x c e p t i o n e)
I
S y s t e m . e r r .p r in t n ( "E r r o r : + e.ge tM essage());

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.

public static char m irart)


I
int c a r = 0;

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

El m todo carcter devolver el siguiente carcter disponible en el flujo de


entrada. Si no hubiera ningn carcter disponible, quedar a la espera de que se
introduzca uno.

public static char c a r c te r O


I
int car - 0:

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.

public static String dato()


I
StringBuffer s d a t o = new S t r i n g B u f f e r ( ):
i n t c a r = 0:

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

Es im portante tom ar buena nota de cm o la salida de un flujo se puede c o


nectar a la entrada de otro, lo que perm ite disponer de nuevas capacidades. Q u
flujos pueden utilizarse de esta form a? T odos aquellos cuyo constructor tenga un
parm etro que haga referencia a otro flujo.

A continuacin se m uestra un ejem plo que utiliza la nueva versin de la clase


L eer que acabam os de im plem entar. D icho ejem plo se lim ita a leer un valor de ti
po d o u b le si el p rim er carcter de la entrada efectuada p o r el usuario que ejecuta
la aplicacin es un dgito o el signo m enos; en otro caso lee un S trin g .

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.

U na vez descrita la jerarqua de clases que Java proporciona para realizar la


E/S, es el m om ento de plantearnos la utilizacin de esta jerarq u a de clases.

ABRIENDO FICHEROS PARA ACCESO SECUENCIAL


El tipo de acceso m s sim ple a un fichero de datos es el secuencial. Un fichero
abierto para acceso secuencial es un fichero que puede alm acenar registros de
cualquier longitud, incluso de un slo byte. C uando la inform acin se escribe re
gistro a registro, stos son colocados uno a continuacin de otro, y cuando se lee,
se em pieza por el prim er registro y se contina al siguiente hasta alcanzar el final.
430 JA VA : CU R SO DE PRO G R A M A CI N

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

Un flujo de la clase F ile O u tp u tS tr e a m perm ite escribir bytes en un fichero.


A dem s de los m todos que esta clase hereda de O u tp u tS tre a m , la clase propor
ciona los constructores siguientes:

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 p rim er constructor abre un flujo de salida hacia el fichero especificado por


nom bre, m ientras que el segundo hace lo m ism o, pero con la posibilidad de aadir
datos a un fichero existente (a a d ir = true); el tercero lo hace a partir de un o b
je to File. Un ejem plo aclarar los conceptos expuestos.

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.

La aplicacin definida p o r la clase C E scribirB ytes m ostrada a continuacin,


realiza lo siguiente:

1. D efine una m atriz buffer de 81 bytes.

2. Lee una lnea de texto desde el teclado y la alm acena en buffer.


3. D efine un flujo f s hacia un fichero denom inado texto.txt. T enga presente que
si el fichero existe, se borrar en el m om ento de definir el flujo que perm ite su
acceso, excepto si especifica com o segundo parm etro true.

F i l e O u t p u t S t r e a m f s = new F i l e O u t p u t S t r e a m t " t e x t o . t x t " ):


CA PTU LO 12: T R A B A JA R C O N FIC H ER O S 4 3 1

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

El program a com pleto se m uestra a continuacin:

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.

Si lo q ue desea es aadir inform acin al fichero, cree el flujo hacia el m ism o


com o se indica a continuacin:

f s = new F i 1e O u t p u t S t r e a m t " t e x t o . t x t " , t r u e ) :

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 )):

En la biblioteca de Java puede observar que el m todo cise de F ile O u tp u tS -


tre am declara que puede lanzar una excepcin de la clase IO E x c e p tio n , razn
p o r la que nuestro cdigo debe atraparla. Q uizs haya pensado invocar al m todo
cise despus de haber ejecutado el m todo w rite dentro del prim er bloque try:

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

Un flujo de la clase F ile ln p u tS tr e a m perm ite leer bytes desde un fichero. A de


m s de los m todos que esta clase hereda de In p u tS tre a m , la clase proporciona
los constructores siguientes:

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 prim er constructor abre un flujo de entrada desde el fichero especificado


por nom bre, m ientras que el segundo lo hace a partir de un objeto File. Un ejem
plo aclarar los conceptos expuestos.

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.

La aplicacin definida por la clase C LeerB ytes m ostrada a continuacin, rea


liza lo siguiente:

1. D efine una m atriz buffer de 81 bytes.

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.

FilelnputStream fe - new F i l e l n p u t S t r e a m t " t e x t o . t x t " ):

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.

nbytes - fe. re a d tb u ffe r. 0. 81):

4. C rea un objeto S t r in g con los datos ledos.

El program a com pleto se m uestra a continuacin:

import j a v a . i o . * :

public c la s s CLeerBytes
434 JA VA : C U R SO DE PROGRAM A CIN

public static v o i d main !String[] args)


I
F i l e I n p u t S t r e a m fe = n u i l ;
b y t e [ ] b u f f e r = new b y t e [ 8 1 ] ;
int nbytes:

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 )

El p rim er constructor crea un objeto F ile a partir de un nom bre de fichero m s


su ruta de acceso (relativa o absoluta). Por ejem plo, el siguiente cdigo crea un
CA PTU LO 12: T R A B A JA R CON FIC H ER O S 4 3 5

objeto File a p artir de la ruta relativa proyecto2\texto.txt. O bserve que el separa


d o r de directorios viene especificado p o r la secuencia de escape \V. E ste separa
d o r en un sistem a U N IX es 7 \

File f i c h e r o = new F i 1 e ( " p r o y e c t o W t e x t o . t x t );

S y s t e m . o u t . p r i n t l n ( " N o m b r e del f i c h e r o : " + f i c h e r o . g e t N a me ) ) ;


S y s t e m . o u t . p r i n t l n ( D i r e c t o r i o padre: " + f i c h e r o . g e t P a r e n t ( ));
S y s t e m . o u t . p r i n t l n ( Ruta r e l a t i v a : " + fic h e ro .g e t P a t h ));
Sy ste m .o u t.p rin tln ("R u ta absoluta: +
fic h e ro .g e t A b s o lu t e P a t h C ));

Los resultados que se visualizan cuando se ejecute el cdigo anterior seran


anlogos a los siguientes:

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 segundo constructor crea un objeto File a partir de una ruta (absoluta o re


lativa) 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:

File f i c h e r o = new F i 1e ( " p r o y e c t o " . " t e x t o . t x t " ) :

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:

File d i r = new F i 1e ( " p r o y e c t o " );


File f i c h e r o = new F i l e d i r , t e x t o . t x t " ) :

La tabla siguiente resum e los m todos de la clase File:

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.

P ara m s detalles sobre los m todos anteriores recurra a la ayuda proporcio


nada con el JDK. U tilizando las capacidades de la clase F ile podem os m odificar
la aplicacin C LeerB ytes para que solicite un nom bre de un fichero existente:

//
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:

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 - S y s t e m . in . r e 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): II menos C R+ L F
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 ) :
I
w hile ( ! f i c h e ro .e x is t s t )):
C A PTU LO 12: TRABAJAR CON FICHEROS 4 3 7

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

A nlogam ente, utilizando las capacidades de la clase File podem os m odificar


la aplicacin C E scribirB ytes para que verifique si existe el fichero en el que se va
a escribir los datos ledos desde el teclado:

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

char resp = s ';


i f ( f i c h e r o . e x i s t s t ))
I
S y s t e m . o u t . p r i n t ( " E l f i c h e r o e x i s t e d e s ea s o b r e e s c r i b i r l o ? ( s / n ) );
resp - (c h a r )S y s te m .in .re a d O ;
II S a l t a r l o s b y t e s no l e d o s d e l f l u j o i n
S y s te m , i n . s k i p( Sy s te m . i n . a v a i l a b l e 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

Un flujo de la clase F ile W r it e r perm ite escribir caracteres (c h a r) en un fichero.


A dem s de los m todos que esta clase hereda de W r ite r, la clase proporciona los
constructores siguientes:

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)

El prim er constructor abre un flujo de salida hacia el fichero especificado por


nom bre, m ientras que el segundo hace lo m ism o, pero con la posibilidad de aadir
datos a un fichero existente (a a d ir = true); el tercero lo hace a partir de un ob
je to File.

El siguiente ejem plo es la versin de la aplicacin Java C E scribirB ytes reali


zada anteriorm ente, adaptada para escribir caracteres en lugar de bytes. O bserve
que las variaciones son m nim as:

import ja v a .i o . * ;

public class CEscribirCars


I
public static v o i d main (String[] args)

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

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


n b y t e s = S y s t e m . i n . r e a d t 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 ( b u f f e r . 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 ) ;

char resp = ' s 1;


i f ( f i c h e r o . e x i s t s ( ))
I
S y s t e m . o u t . p r i n t ( " E l f i c h e r o e x i s t e desea s o b r e e s c r i b i r l o ? ( s /n) " ) ;
r e s p = ( c h a r ) S y s t e m . i n . r e a d t );
// S a l t a r l o s b y t e s n o l e d o s d e l f l u j o i n
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 ( ) ) ;
CA PTU LO 12: TR A B A JA R C O N FICHEROS 4 3 9

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 )

El prim er constructor abre un flujo de entrada desde el fichero especificado


por nom bre, m ientras que el segundo lo hace a partir de un objeto File.

El siguiente ejem plo es la versin de la aplicacin Java C LeerB ytes realizada


anteriorm ente, adaptada para leer caracteres en lugar de bytes. O bserve que las
variaciones son mnim as:

import j a v a . i o . * ;
440 JA V A: C U R S O DF. PROGRAM A CIN

public class CLeerCars


1
public static void ma i n ( S t r i n g args)
1
b y t e [ ] n o m F i c h = new b y t e [ 8 1 ] :
S t r i n g nombreFichero = n u i l ;
F ile fichero = nuil ;
int nbytes, ncars:
FileReader fe = n u il;
c h a r [ ] b u f f e r - new c h a r [ 8 1 ] :

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:

Se crea un flujo asociado con un origen o destino de los datos.


Se aso cia un filtro con el flujo anterior.
Finalm ente, el program a leer o escribir datos a travs de ese filtro.

DataOutputStream

Un flujo de la clase D a ta O u tp u tS tr e a m , derivada indirectam ente de O u tp u tS -


tream , perm ite a una aplicacin escribir en un flujo de salida subordinado, datos
de cualquier tipo prim itivo.

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 1e 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 C ' d a t o s . d a t " ) :


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 t f o s ) :

Un program a que quiera alm acenar datos en el fichero datos.dat, escribir ta


les datos en el filtro dos, que a su vez est conectado al flujo fo s abierto hacia ese
fichero. La figura siguiente m uestra de form a grfica lo expuesto:

El siguiente fragm ento de cdigo m uestra cm o utilizar el filtro anterior para


alm acenar los datos nom bre, direccin y telfono en un fichero especificado por
nom bre Fichero:
442 JA V A: C U R SO DE PROGRAM A CIN

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 ;

Los m todos m s utilizados de esta clase se resum en en la tabla siguiente:

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

U n flujo de la clase D a ta ln p u tS tr e a m , derivada indirectam ente de In p u tS tre a m ,


perm ite a una aplicacin leer de un flujo de entrada subordinado, datos de cual
quier tipo prim itivo escritos por un flujo de la clase D a ta O u tp u tS tr e a m .

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 ) :

Un program a que quiera alm acenar datos en el fichero datos.dat, escribir ta


les datos en el filtro dis. que a su vez est conectado al flujo f i s abierto desde ese
fichero. La figura siguiente m uestra de form a grfica lo expuesto:
CA PTU LO 12: T R A B A JA R C O N FIC H ER O S 4 4 3

El siguiente fragm ento de cdigo m uestra cm o utilizar el filtro anterior para


leer los datos nom bre, direccin y telfono desde un fichero especificado por
nom breFichero:

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 ;

Los m todos m s utilizados de esta clase se resum en en la tabla siguiente:

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.

Un ejemplo de acceso secuencial


D espus de la teora expuesta hasta ahora acerca del trabajo con ficheros, habr
observado que la m etodologa de trabajo se repite. Es decir, para escribir datos en
un fichero:

D efinim os un flujo hacia el fichero en el que deseam os escribir datos.


L eem os los datos del dispositivo de entrada o de otro fichero y los escribim os
en nuestro fichero. E ste proceso se hace norm alm ente registro a registro. Para
ello, utilizarem os los m todos proporcionados p o r la interfaz del flujo.
C erram os el flujo.
444 JA V A: C U R SO DU PROGRAM A CIN

Para leer datos de un fichero existente:

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.

E sto pone de m anifiesto que un fichero no es m s que un m edio perm anente


de alm acenam iento de datos, dejando esos dalos disponibles para cualquier pro
gram a que necesite m anipularlos. Lgicam ente, los datos sern recuperados del
fichero con el m ism o form ato con el que fueron escritos, de lo contrario los re
sultados sern inesperados. Es decir, si en el ejercicio siguiente los datos son
guardados en el orden: una cadena, otra cadena y un long, tendrn que ser recupe
rados en este orden y con este m ism o form ato. S era un erro r recuperar prim ero
un lo n g despus una cadena y finalm ente la otra cadena, o recuperar prim ero una
cadena, despus un float y finalm ente la otra cadena; etc.

El siguiente ejem plo lee de la entrada estndar grupos de datos (registros) de


finidos de la form a que se indica a continuacin y los alm acena en un fichero.

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.

El m todo m a in realiza las tareas siguientes:

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

Si no existe, o bien si existe y se desea sobreescribir, invoca al m todo crear-


F ichero pasando com o argum ento el objeto F ile creado.

import j a v a . i o . * ;

// Se u t i l i z a tambin la clase Leer m o d if ic a d a en e s t e c a p i t u l 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 ) :

f 1u j o S . p r i n t " d e s e a e s c r i b i r otro registro? (s/n) ");


r e s p = L e e r . c a r c t e r );
L e e r . 1 i m p i a r ( );
1
w h i 1e ( r e s p 's O :
1
f i n a l 1y
1
// C e r r a r el flujo
446 JA V A : C U R SO DE PRO G R A M A CI N

if (dos != n u i l ) dos.closet);

public static void m a in (S trin g [] args)


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
S t r i n g nombreFichero = n u i l ; II no mb r e d e l f i c h e r o
F i l e f i c h e r o = n u i l ; // 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

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

Para leer el fichero creado p o r la aplicacin anterior, vam os a escribir otra b a


sada en la clase M ostrarListaTfhos. E sta clase define dos m todos: m ostrarFiche-
ro y m ain.

El m todo m ostrarF ichero recibe com o parm etro un objeto S tr in g que al


m acena el nom bre del fichero que se desea leer y realiza las tareas siguientes:

C rea un objeto F ile para identificar al fichero.


Si el fich ero especificado existe, crea u n flujo desde el m ism o que perm ite
leer datos de tipos prim itivos utilizando un buffer.
C A P T U L O 12: T R A B A JA R CON FIC H ER O S 4 4 7

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:

V erifica si se pas un argum ento cuando se ejecut la aplicacin con el nom


bre del fichero cuyo contenido se desea visualizar.
Si no se pas un argum ento, la aplicacin m ostrar un m ensaje indicando la
sintaxis que se debe de em plear p ara ejecutar la m ism a y finalizar. En otro
caso, invoca al m todo m ostrarF ichero pasando com o argum ento argsjO].

import j a v a . i o . * ;

public class M ostrarListafnos


I
public s t a t ic void m ostrarFich ero(String 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
D a t a l n p u t S t r e a m d i s = n u i l : / / e n t r a d a de d a t o s d e s d e e l f i c h e r o
F ile fichero = n u il: // o b j e t o q u e i d e n t i f i c a el f i c h e r 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 );

// M o s t r a r l o s d a t o s n o mbr e , direccin y telfono


flujoS.println(nom bre);
f l u j o S . p r i n t n ( d i r e c e i n );
flujoS.println< telfono):
f l u j o S . p r i n t l n ( );
I
w hile (true);
I
el se
flu jo S.p rintn ("El fichero no e x i s t e );
I
catch(EOFException e)
(
flu joS.p rintn ("Fin del listado");
)
finally
(
// C e r r a r el f l u j o
i f ( d i s ! = n u l 1) d i s . e l o s e ( ):

public static void m a in (S trin g [] args)


I
if ( a r g s . l e n g t h ! = 1)
S y ste m .e rr.p r i n t l n ( " S i n t a x i s : java M o s tra rL ista T fn o s +
"Ofichero fuente>"):
el se
[
try
{
m o s t r a r F i c h e r o a r g s [ 0 ] );
I
catch(IOException e)
I
System .out.p rintln"Error: " + e .g e tM e ssa g e ()):
1
I
1
i

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

m os aisladam ente; m s bien se corresponder con los atributos de un objeto, por


ejem plo de la clase C P ersona, lo que nos conducir a escribir y leer objetos a y
desde un fichero.

N orm alm ente la operacin de enviar u na serie de objetos a un fichero en disco


para hacerlos persistentes recibe el nom bre de seriacin, y la operacin de leer o
recuperar su estado del fichero para reconstruirlos en m em oria recibe el nombre
de deseriacin. Para realizar estas operaciones de una form a autom tica, el paque
te ja v a .io proporciona las clases O b je c tO u tp u tS tr e a m y O b je c tln p u tS tre a m .
A m bas clases dan lugar a flujos que procesan sus datos; en este caso, se trata de
convertir el estado de un objeto (los atributos excepto las variables estticas), in
cluyendo la clase del objeto y el prototipo de la m ism a, en una secuencia de bytes
y viceversa. Por esta razn los flujos O b je c tO u tp u tS tr e a m y O b je c tln p u t
S tre a m deben ser construidos sobre otros flujos que canalicen esos bytes a y des
de el fichero. El esquem a grfico que responde a este proceso es el siguiente:

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 . * ;

public class CPersona implements S e r i a l i z a b l e


I
// C u e r p o de l a el a s e
450 JA VA : C U R S O DE PRO G R A M A CI N

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.

Escribir objetos en un fichero


Un flujo de la clase O b je c tO u tp u tS tr e a m perm ite enviar datos de tipos prim iti
vos y objetos hacia un flujo O u tp u tS tre a m o derivado; concretam ente, cuando se
trate de alm acenarlos en un fichero, utilizarem os un flujo F ile O u tp u tS tre a m .
Posteriorm ente, esos objetos podrn ser reconstruidos a travs de un flujo O b ject-
In p u tStre a m .

Para escribir un objeto en un flujo O b je c tO u tp u tS tr e a m utilizarem os el


m todo w rite O bje ct. L os objetos pueden incluir Strings y m atrices, y el alm ace
nam iento de los m ism os puede com binarse con datos de tipos prim itivos, y a que
esta clase im plem enta la interfaz D a ta O u tp u t. E ste m todo lanzar la excepcin
N o tS e ria liz a b le E x c e p tio n si se intenta escribir un objeto de una clase que no im
plem enta la interfaz Serializable.

P o r ejem plo, el siguiente cdigo construye un O b je ctO u tp u tStre am sobre un


F ile O u tp u tS tre a m , y lo utiliza para alm acenar un S t r in g y un objeto C Persona
en un fichero denom inado datos:

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 a t o s " ):


O b j e c t O u t p u t S t r e a m o o s = new O b j e c t O u t p u t S t r e a m ( f o s );

oos.writeUTF( " Fichero da to s"):


o o s . w r i t e O b j e c t ( new C P e r s o n a t n o m b r e . direccin, telfono)):
o o s . e l o s e ( ):

C om o ejercicio, vam os a m odificar la aplicacin C rearListaTfnos anterior pa


ra que perm ita alm acenar objetos C Persona en un fichero (la clase C Persona fue
im plem entada en el captulo 9 al hablar de m atrices de objetos):

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

Leer objetos desde un fichero


Un flujo de la clase O b je c tln p u tS tre a m perm ite recuperar datos de tipos prim iti
vos y objetos desde un flujo In p u t S t r e a m o derivado; concretam ente, cuando se
trate de datos de tipos prim itivos y objetos alm acenados en un fichero, utilizare
m os un flujo F ile ln p u tS tre a m . L a clase O b je c tln p u tS tre a m im plem enta la in
terfaz D a t a ln p u t para perm itir leer tam bin datos de tipos prim itivos.

Para leer un objeto desde un flujo O b je c tln p u tS tre a m utilizarem os el m to


do read O bject. Si se alm acenaron objetos y datos de tipos prim itivos, deben ser
recuperados en el m ism o orden.

P o r ejem plo, el siguiente cdigo construye un O b je c tln p u tS tre a m sobre un


F ile ln p u tS tre a m , y lo utiliza para recuperar un S t r in g y un objeto C Persona de
un fichero denom inado datos:

F i l e l n p u t S t r e a m f o s = new F i 1e I n p u t S t r e a m " d a t o s " ) ;


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 I n p u t S t r e a m f o 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

C om o ejercicio, vam os a m odificar la aplicacin M ostrarL istaT fnos anterior


para que perm ita recuperar objetos C Persona desde un fichero (la clase C Persona
fue im plem entada en el captulo 9 al hablar de m atrices de objetos):

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 ;

public static void m a in (S trin g [] args)


I
II ...

Seriar objetos que referencian a objetos


C uando en un fichero se escribe un objeto que hace referencia a otros objetos,
entonces todos los objetos accesibles desde el prim ero deben ser escritos en el
m ism o proceso para m antener as la relacin existente entre todos ellos. Este pro
ceso es llevado a cabo autom ticam ente por el m todo w rite O b jcct, que escribe
el objeto especificado, recorriendo sus referencias a otros objetos recursivam ente,
escribiendo as todos ellos.

A nlogam ente, si el objeto recuperado del flujo por el m todo re a d O b je c t


hace referencia a otros objetos, re a d O b je c t recorrer sus referencias a otros ob
jeto s recursivam ente, para recuperar todos ellos m anteniendo la relacin que
exista entre ellos cuando fueron escritos.

V eam os un ejem plo donde se aplique lo expuesto. Si recuerda, en el captulo


9 im plem entam os una clase C ListaTfnos para m antener una lista de telfonos; y
despus en el 11, 1a m ejoram os aadiendo el tratam iento de algunas excepciones.
Un objeto de esta clase representaba una lista de telfonos; la lista est im ple-
m entada com o una m atriz de referencias a objetos C P ersona, y cada objeto C P er
sona tiene com o atributos el nom bre, la direccin y el telfono de un m iem bro de
la lista. D espus escribim os una clase aplicacin Test, que utilizando las clases
CListaTfnos y C Persona perm ita buscar, aadir y elim inar telfonos en una lista.
Para que d icha aplicacin fuera til slo le faltaba un detalle m uy im portante, que
la lista creada fuera persistente. Esto im plica guardar la lista en un fichero cuando
la aplicacin finalice, y recuperarla del fichero cuando la aplicacin se inicie.
Realicem os pues, una tercera versin que incluya de form a autom tica las opera
ciones de guardar y recuperar el objeto C ListaTfnos en un fichero denom inado
listatfnos.dat .

Segn lo explicado, para poder seriar un objeto de la clase CListaTfnos, sta


debe im plem entar la interfaz Se rializable:
454 JA VA : C U R S O D E PROGRAM A CIN

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:
)

public static void m a in (S trin g [] args)


C A PTU LO 12: T R A B A JA R C O N FICHEROS 4 5 5

// 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 ()):

ABRIENDO FICHEROS PARA ACCESO ALEATORIO


Hasta este punto, hem os trabajado con ficheros de acuerdo con el siguiente es
quema: abrir el fichero, leer o escribir hasta el final del m ism o, y cerrar el fichero.
Pero no hem os ledo o escrito a partir de una determ inada posicin dentro del fi
chero. Esto es particularm ente im portante cuando necesitam os m odificar algunos
de los valores contenidos en el fichero o cuando necesitem os extraer una parte
concreta dentro del fichero.

El paquete ja v a .io contiene la clase R a n d o m A c c e ss F ile la que proporciona


las capacidades que perm iten este tipo de acceso directo. A dem s, un flujo de esta
clase perm ite realizar tanto operaciones de lectura com o de escritura sobre el fi
chero vinculado con el m ism o. E sta clase se deriva directam ente de O bject, e im-
plementa las interfaces D a t a ln p u t y D a ta O u tp u t.

Un fichero accedido aleatoriam ente es com parable a una m atriz. En una ma


triz para acceder a uno de sus elem entos utilizam os un ndice. En un fichero acce
dido aleatoriam ente el ndice es sustituido por un puntero de lectura o escritura
(L/E). Dicho puntero es situado autom ticam ente al principio del fichero cuando
ste se abre para leer y/o escribir. P or lo tanto, una operacin de lectura o de es
critura com ienza en la posicin donde est el puntero dentro del fichero; final
mente, su posicin coincidir ju sto a continuacin del ltim o byte ledo o escrito.

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

La clase R a n d o m A c c e ss F ile proporciona d os constructores:

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)

El prim er constructor abre un flujo vinculado con el fichero especificado por


nom bre-fichero, m ientras que el segundo hace lo m ism o, pero a partir de un o b
jeto File. El argum ento m odo puede ser:

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 ):

A sim ism o, la clase R a n d o m A c c e ss F ile provee, adem s de los m todos de las


interfaces D a t a ln p u t y D a ta O u tp u t (vea el apartado flujos de datos" expuesto
anteriorm ente), los m todos getF ile P ointer, length y seek que se definen de la
form a siguiente:

public lo n g g e t F i l e P o i n t e r ) th rows IOException

Este m todo devuelve la posicin actual en bytes del puntero de L /E en el fi


chero. Piense en el puntero de L /E anlogam ente a com o lo hace cuando piensa en
el ndice de una m atriz. Este puntero m arca siem pre la posicin donde se iniciar
la siguiente operacin d e lectura o de escritura en el fichero.

public long 1e n g t h ( ) throws IOException

Este otro m todo devuelve la longitud del fichero en bytes.

public void seekdong pos) throws IOException

Y este otro m todo, m ueve el puntero de L /E a una nueva localizacin d es


plazada p o s bytes del principio del fichero. N o se perm iten desplazam ientos ne
C A PTU LO 12: TR A B A JA R C O N FIC H ER O S 4 5 9

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.

Segn lo expuesto, las dos lneas de cdigo siguientes sitan el puntero de


L/E, la prim era desp bytes antes del final del fichero y la segunda desp bytes des
pus de la posicin actual.

1 i s t a T e l f o n o s . s e e k (1is t a T e l f o n o s .1e n g t h ( ) - desp);


1 i s t a T e l f o n o s . s e e k ( 1 i s t a T e l f o n o s . g e t F i 1e P o i n t e r ) + d e s p ) :

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

Si para nuestros propsitos, pensam os en los atributos nom bre, direccin y


telfono com o si de un registro se tratara, cul es el tam ao en bytes de ese re
gistro? Si escribim os m s registros todos tienen el m ism o tam ao? Evidente
m ente no; el tam ao de cada registro depender del nm ero de caracteres
alm acenados en los S trin g nom bre y direccin (telfono es un dato de tam ao fi
jo, 8 bytes, puesto que se trata de un long) A cuento de qu viene esta exposi
cin?

Al principio de este apartado dijim os que el acceso aleatorio a ficheros es


particularm ente im portante cuando necesitem os m odificar algunos de los valores
contenidos en el fichero, o bien cuando necesitem os extraer una parte concreta
dentro del fichero. Esto puede resultar bastante com plicado si las unidades de
grabacin que hem os denom inado registros no son todas iguales, ya que intervie
nen los factores de: posicin donde com ienza un registro y longitud del registro.
Tenga presente que cuando necesite reem plazar el registro n de un fichero por
otro, no debe sobrepasarse el nm ero de bytes que actualm ente tiene. T odo esto es
viable llevando la cuenta en una m atriz de la posicin de inicio de cada uno de los
registros y de cada uno de los cam pos si fuera preciso (esta inform acin se alm a
cenara en un fichero ndice para su utilizacin posterior), pero resulta m ucho m s
fcil si todos los registros tienen la m ism a longitud.
460 JA V A : C U R S O D E P R O G R A M A C I N

C om o ejem plo, vam os a escribir o tra versin d e la aplicacin lista de telfo


nos desarrollada en el captulo 9 y m odificada en el 11 y en ste. Esta nueva ver
sin bsicam ente sustituir la m atriz de objetos C Persona encapsulada en
C ListaTfnos p o r un fichero con registros, conteniendo cada uno de ellos los atri
butos n om bre, direccin y telfono de un objeto C Persona.

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

p u b l i c C P e r s o n a C S t r i n g nom. S t r i n g dir. long t e l )


I
n o mb r e = nom;
d ireccin = d ir;
telfono = t e l ;

public void asignarN om breString nom)


I
nombre = nom;
)

public String obtenerNombre()


I
return n o mb r e :
I

p u b lic void asignarD ire ccin(String dir)


I
di r e c c i n = d i r ;
)
CA PTU LO 12: TRA BA JA R C O N FIC H ER O S 4 6 1

public Strin g obtenerDireccin()



return direccin:
I

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

public int tamaoO


(
II L o n g i t u d en b y t e s de l o s a t r i b u t o s ( u n L o n g = 8 b y t e s )
r e t u r n n o m b r e . 1 e n g t h ( ) * 2 + d i r e c c i n . l e n g t h ( ) * 2 + 8;

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

C uando desde algn m todo se cree un objeto C ListaTfnos qu esperam os que


ocurra? L gicam ente que se cargue la lista de telfonos especificada, o bien que
se cree una nueva cuando el fichero especificado no exista. P or ejem plo:

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

Segn lo expuesto, la lista de telfonos especificada se cargar desde un fi


chero alm acenado en el disco y si ese fichero no existe, se crear uno nuevo. Para
ello, el constructor de la clase C ListaTfnos abrir un flujo para acceso aleatorio
desde el fichero especificado, alm acenar una referencia al m ism o en un atributo
fe s de la clase, y en otro, nregs, alm acenar el nm ero de registros existentes en el
fichero. Un atributo m s, tarnaoRegs, especificar el tam ao que hayam os pre
visto para cada registro. En nuestro caso, la inform acin alm acenada en un regis
tro se corresponde con el nom bre, direccin y telfono de un objeto CPersona.
462 JA V A : C U R S O D E P R O G R A M A C I N

A tenindonos a lo explicado, veam os a continuacin el esqueleto de la clase


C ListaTfnos y el constructor de la misma:

/////////////////////////////////////////////////////////////////
// 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 C L ista T fn o s(F ile fichero) throws IOException


I
if ( f i c h e r o . e x i s t s t ) && ! 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 " ) :
f e s - new R a n d o m A c c e s s F i l e t f i c h e r o . " r w " )
// Como e s c a s i s e g u r o que e l l t i m o r e g i s t r o no o c u p e el
// t a m a o f i j a d o , 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 il ( ( d o u b l e ) f e s . l e n g t h ( ) / (double)tamaoReg):

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

p u b lic boolean p o ne rV a lo rE n int i. CPersona ob je to )


th rows IO E x c e p t io n
1
// ...

p u b lic CPersona v a lo r E n int i ) th rows IOException

// ..

public void aadir(CPersona obj) throws IOException

// ...

public boolean e l i m i n a r ( l o n g tel) th rows IOException

II . ..

public int buscar(String str. in t pos) th rows IOException


I
// ...
CA PTU LO 12: TRA BA JA R C O N FIC H ER O S 4 6 3

O bserve que el constructor de la clase verifica si el argum ento pasado corres


ponde a un nom bre existente en el directorio actual de trabajo y, en caso de que
exista, si realm ente se trata de un nom bre de fichero; si no es as, lanzar una ex
cepcin del tipo lO E x c e p tio n ; en otro caso, abre un flujo desde el fichero para
leer y escrib ir que perm ite el acceso aleatoriam ente al m ism o y calcula el nm ero
de registros del fichero.

Escribir un registro en e l fichero

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.

p u b lic boolean p o ne rV alorEnt int i, CPersona objeto )


throws lOException
1
if (i > = 0 && i <= n r e g s )
I
if ( o b j e t o . t a m a o ) + 4 > tamaoReg)
S y s t e m . e r r . p r i n t l n ( " t a m a o del r e g i s t r o excedido"):
el se
I
f e s . s e e k d * t a m a o R e g ) : I I s i t u a r e l p u n t e r o de L/E
f e s . w r i t e UT F ( o b j e t o . o b t e n e r N o m b r e ( ) ) :
fe s.w rite llT F (ob je to .o b te n e rD i r e c c i n ( ));
f e s . w r it e lo n g ( o b j e t o . o b t e n e r T e l f o n o ( ));
return true:
I
I
el se
S y s t e m . e r r . p r i n t l n t " n m e r o de r e g i s t r o fuera de l i m i t e s " ) :
return false:
1

Se observa que lo prim ero que hace el m todo es verificar si el nm ero de re


gistro es vlido (cuando i sea igual a nregs es porque se quiere aadir un registro
al final del fichero). El p rim er registro es el cero. D espus com prueba que el ta
m ao de los atributos del objeto C Persona m s 4, no superen el tam ao estableci
do para el registro (m s 4 porque cada vez que w rite U T F escribe un S trin g ,
aade 2 bytes iniciales p ara dejar constancia del nm ero de bytes que se escriben;
esto perm itir posteriorm ente al m todo re a d U T F saber cuntos bytes tiene que
464 JA V A : C U R S O DE PRO G R A M A CI N

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

Aadir un registro al final del fichero

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.

public void aadir(CPersona obj) th rows IOException


I
if (ponerValorEn( nregs. obj )) nregs++:
I

Leer un registro del fichero

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.

public CPersona valorEnf int i ) th rows IOException


I
i f ( i > = 0 && i < n r e g s )
I
fes.seek(i * tamaoReg): // s i t u a r el p u n t e r o de L/E

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

r e t u r n new C P e r s o n a ( n o m b r e . direccin, telfono):


I
el se
1
S y s t e m . o u t .p r i n t n ( " n m e r o de r e g i s t r o fuera de l i m i t e s " ) :
return n u l1 ;

Se observa que lo prim ero que hace el m todo es verificar si el nm ero de re


gistro es vlido (el prim er registro es el cero). Si el nm ero de registro est dentro
de los lm ites perm itidos, sita el puntero de L /E en la posicin de inicio corres
C A P T U L O 12: TRA BA JA R CON FICHEROS 4 6 5

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

Elim inar un registro del fichero

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.

p u b lic boolean e l i m i n a r l o n g t e l ) throws IOException


(
CPersona obj;
// B u s c a r e l t e l f o n o y m a r c a r e l r e g i s t r o p a r a
// p o s t e r i o r m e n t e e l i m i n a r l o
f o r ( i n t re g _ i = 0; re g _ i < n r e g s ; r e g _ i + + )
I
o b j = v a l o r E n ( r e g _ i );
if (obj.obtenerTelfono() = tel)
1
o b j .asignarTelfono(O ):
p o n e r V a l o r E n ( r e g _ i , o bj );
re tu rn true:
I
I
return false:
I

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.

Buscar un registro en el fichero

U na operacin m uy com n en el trabajo con registros es localizar uno determ ina


do. C m o buscar un telfono en una lista de telfonos? L o m s com n es buscar
466 JA V A : C U R SO DE PRO G R A M A CI N

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.

public int buscar(String str, int pos) throws IOException


I
// B u s c a r un r e g i s t r o p o r una s u b c a d e n a d e l nombre
// a p a r t i r d e un r e g i s t r o d e t e r m i n a d o
CPersona obj:
S t r i n g nom;
if (str = n u i l ) re t u r n -1;
i f ( p o s < 0 ) p o s = 0;
f o r ( i n t reg_i = pos; reg_i < n regs: re g _ i+ + )
[
o bj = v a l o r E n ( r e g _ i ) ;
nom = o b j . o b t e n e r N o m b r e l ):
// s t r e s t c o n t e n i d a en nom?
i f ( n o m. i n d e x O f ( s t r ) > - 1 )
return r e g _ i;
I
return -1;
I

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 ejemplo de acceso aleatorio a un fichero


A continuacin vam os a escribir una aplicacin basada en una clase Test para tra
b ajar con u na lista de telfonos construida a partir de un objeto C ListaTfnos. Esta
aplicacin ser prcticam ente la m ism a que vim os en la versiones de la aplicacin
lista de telfonos desarrollada en el captulo 9 y m odificada en el 11 y al princi
pio de ste; por eso no abundarem os en detalles en aquellas partes que ya hayan
sido explicadas. Esto dem uestra que cuando una clase, com o C ListaTfnos, se m o
difica y no se alteran los prototipos de los m todos que com ponen su interfaz, las
aplicaciones que la utilizan no se ven afectadas. En nuestro caso, esta clase tiene
C A P T U L O 12: TRA BA JA R C O N FIC H ER O S 4 6 7

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

El esqueleto de esta aplicacin se m uestra a continuacin. En l se puede ob


servar que se han definido com o atributos de la clase T est los flujos para acceder a
la entrada y salida estndar, as com o una referencia listatfnos al objeto que en-
capsular la lista de telfonos con la que deseam os trabajar.

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 i c boolean m o d i f i c a r ( i n t nreg) throws IOException


f1
// .
I

public s ta t ic void a c t u a l i z a r ( F i 1e f A c t u a l ) throws IOException


1
// .
1

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

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 t f i c h e r o ) :

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

L a ejecucin de la aplicacin se iniciar p o r el m todo m a in que, en prim er


lugar, crea el objeto C ListaT fnos cuya interfaz nos dar acceso aleatorio al fichero
especificado. D espus, ejecutar un bucle que invocar al m todo m en encarga
d o de solicitar la eleccin de una de las opciones presentadas p o r l:

public static int me n ( )


I
f l u j o S . p r i n t ( " \ n \ n " ):
f 1 u j o S . p r i n t l n ( " 1 . B u s c a r " );
f l u j o S . p r i n t l n ( 2. B u s c a r s i g u i e n t e " ) :
f 1 u j o S . p r i n t l n ( 3. Modi f i c a r " );
f l u j o S . p r i n t l n t "4. A a d i r " ) ;
f l u j o S . p r i n t l n ( " 5 . El i m i n a r " );
f 1 u j o S . p r i n t l n{ " 6 . S a l i r ' ' ) :
f 1 u j o S . p r i n t l n ( ):
flujoS.printl" Opcin: " ) ;
C A P T U L O 12: TRA BA JA R C O N FICHEROS 4 6 9

int op:
do
o p = Leer . d a t o l n t ) ;

while ( o p< 1 || o p > 6):


r e t u r n o p :

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.

Para realizar tal m odificacin, el proceso seguido por el m todo es:

L eer el registro correspondiente al nm ero pasado com o argum ento y crear un


objeto C Persona a partir de los datos ledos. Esto perm itir m anipular el re
gistro utilizando la interfaz del objeto.

Presentar un m en que perm ita m odificar el nom bre, la direccin o el telfo


no, as com o salir del proceso guardando los cam bios efectuados, o bien salir
sin g u ardar los cam bios. Los nuevos datos sern solicitados desde el teclado.

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

p u b l i c s t a t ic b o o l e a n m o d i f i c a r ( i n t nreg) throws IOException


I
S t r i n g nombre, d i r e c c i n ;
l ong telfono;
int op;
// Leer el r e g i s t r o
C P e r s o na obj = 1 i s t a t f n o s .v a l o r E n n r e g );
if (obj = nuil) r e t u r n false;

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

El proceso seguido para realizar lo expuesto es sencillo. B sicam ente se crea


r un fichero tem poral (fichero que existe durante un corto espacio de tiem po,
m ientras lo necesitem os) para guardar todos los registros del fichero actual cuyo
nm ero de telfono sea distinto de cero. D espus de realizar esta operacin, cerra
rem os am bos ficheros y utilizarem os la interfaz de la clase F ile para borrar el fi
chero actual y renom brar el fichero tem poral con el nom bre que tena el fichero
actual.

public static v o i d a c t u a l i z a r ( F i 1e f A c t u a l ) th rows IOException


I
// C r e a r un f i c h e r o t e m p o r a l
F i l e f i c h e r o T e m p - new F i l e "1 i s t a t f n o s . t m p " ) :
C L i s t a T f n o s f t e m p - new C L i s t a T f n o s ( f i c h e r o T e m p ) :

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

UTILIZACIN DE DISPOSITIVOS ESTNDAR


La salida de un program a puede tam bin ser enviada a un dispositivo de salida
que no sea el disco o la pantalla; por ejem plo, a una im presora conectada al puerto
paralelo. C om o Java no tiene definido un flujo estndar para el puerto paralelo, la
solucin es d efinir uno y vincularlo a dicho dispositivo.

U na form a de realizar lo expuesto es crear un flujo hacia el dispositivo L P T l,


LP T2, o P R N y escribir en ese flujo (los nom bres indicados son los establecidos
p o r W indow s para nom brar a la im presora; en U N IX la prim era im presora tiene
asociado el nom bre /devApO, la segunda / d ev A p I, etc.). Las siguientes lneas de
cdigo m uestran cm o realizar esto:

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 om o ejem plo, vam os a aadir al m en de la aplicacin anterior, una opcin


im prim ir q ue perm ita obtener la lista de telfonos por la im presora.

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

El cdigo anterior indica que cuando el usuario seleccione la opcin 6 del


m en de la aplicacin, se invocar al m todo esttico imprimirLstaTfnos de la
clase aplicacin Test. E ste m todo, crear un flujo hacia la im presora, obtendr el
nm ero total de registros del fichero lista de telfonos y establecer un bucle
para im prim ir cada uno de ellos. El cdigo com pleto se m uestra a continuacin:

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

for (in t n = 0: n < nregs: n++)


I
// S a l t a r p g i n a i n i c i a l m e n t e y d e s p u s c a d a 6 0 l i n e a s
i f (n % 60 0) f l u j o S . w r i t e ( f f ) :
II I m p r i m i r e l r e g i s t r o n d e l a l i s t a de t e l f o n o s
i = new I n t e g e r ( n ) ; // n me r o d e r e g i s t r o
flujoS.w riteC Registro: " + i.to S trin g O + c rlf);
flujoS.w rite (listatfnos.valorEn (n).obtene rN om bre() + c r lf ):
flu jo S .w ri t e ( 1ist a t fn o s .v a lo rE n (n ).o b t e n e rD i recei n ( ) + c r l f ) :
1 = new L o n g ( 1 i s t a t f n o s . v a l o r E n ( n ) . o b t e n e r T e l f o n o ( ) ) :
flu jo S.w rite d .to String) + crlf):
f l u j o S . w r i t e t c r l f ) : // s a l t a r una l i n e a
I
f l u j o S . w r i t e t f f ): // s a l t a r a l a s i g u i e n t e pgina
f l u j o S . c l o s e ( ): II c e r r a r e l f l u j o h a c i a la impresora

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:

java C o p ia r F ic h e ro f i c h e r o fuente> f i c h e r o destino?

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.

La funcionalidad de la clase C opiarF ichero estar soportada fundam entalm ente


por el m todo copiar que tiene el prototipo siguiente:

public static void copiar(String fuente. String destino)

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.

A continuacin se m uestra la aplicacin com pleta, suficientem ente com entada


com o para no tener que abundar en m s explicaciones:

import j a v a . i o . * :

public class CopiarF


i
public s t a t ic void c o p ia r(S trin g fuente, Strin g destino)
th rows IO E x c e p tio n
I
// S i el f i c h e r o f u e n t e y e l d e s t i n o s o n e l mi s mo f i c h e r o . . .
i f ( f u e n t e . c o m p a r e T o ( d e s t i n o ) = = 0)
t h r o w new E C o p i a r F i c h e r o ( " N o p u e d e s o b r e e s c r i b i r s e un " +
" f i c h e r o s o b r e s i m i s m 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 );

d m ain (Strin g [] args)

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

copiar(args[0], a rgs[l]); // r e a l i z a r la copia

catch(IOException e)

S y s t e m .o u t .p r in t n ("E r r o r : " + e.getM essage()):


CA PTU LO 12: TRA B A JA R CON FICHEROS 4 7 7

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

La clase aplicacin, G rep, deber proporcionar al m enos los siguientes m todos:

a) B uscarC adena para buscar una cadena de caracteres dentro de otra. El prototi
po de este m todo ser:

static boolean B u s c a rC a d e n a (S t rin g cadenal. String cadena?)

E ste m todo devolver tr u e si cadena2 se encuentra dentro de c a d e n a l; en


otro caso, devolver false.

b) B uscarE nF ich para buscar una cadena de caracteres en un fichero de texto e


im prim ir el nm ero y el contenido de la lnea que contiene a la cadena. El
prototipo de este m todo ser:

static void B u s c a r E n F ic h (S t r in g nombrefich, String cadena)

c) m a in para que utilizando los m todos anteriores perm ita buscar una palabra en
uno o m s ficheros.

La form a de invocar a la aplicacin ser as:

java Grep p a l a b r a fichero_l fichero_2 ... fichero_n

A continuacin se m uestra la aplicacin com pleta, suficientem ente com entada.

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

C rear un flujo F ile ln p u tS tr e a m asociado con el fichero de texto.


C onectar un filtro In p u t S t r e a m R e a d e r con el flujo anterior.
Y finalm ente, conectar el filtro B u ffe r e d R e a d e r con el filtro anterior.

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

public static void B u s c a r E n F i c h ( S t r i n g nombrefich, Strin g cadena)


I
// D e f i n i c i o n e s de v a r i a b l e s
F i l e f i c h F u e n t e = new F i l e ( n o m b r e f i c h ) ;
BufferedReader flu jo E - n u il;

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

public static void m ainStringC ] args) . ,/


I
// m a i n d e b e r e c i b i r d o s o ms p a r m e t r o s : la cadena a buscar
// y l o s f i c h e r o s f u e n t e . P o r e j e m p l o :
// j a v a G r e p c a t c h G r e p . j a v a L e e r . j a v a

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:

Nombre d e l fichero: artculos

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.

Segn el enunciado, la funcionalidad de la clase C Registro estar soportada


por los atributos referencia y precio y por los m todos siguientes:

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

Y el m todo tam ao que devolver el tam ao en bytes de los atributos.


C A P T U L O 12: TRA BA JA R CON FICHEROS 4 8 1

La declaracin de esta clase se m uestra a continuacin:

/////////////////////////////////////////////////////////////////
// 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:

public void asignarR eferencia(Strin g ref)

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:

public void asignarPreciotdouble pre)


I
p r e c io = pre:

p u b lic double o b t e n e r P r e c io t )
I
return precio:

public int tamaot)


(
// L o n g i t u d en b y t e s de l o s a t r i b u t o s (un D o u b le = 8 b y t e s )
r e t u r n r e f e r e n c i a . 1 e n g t h ( ) * 2 + 8:

S iguiendo con el ejem plo, la funcionalidad d e la clase C BaseD edatos deber


perm itir, abrir el fichero, cerrarlo, calcular su longitud, insertar, obtener, buscar y
elim in ar un registro, as com o actualizar el fichero cuando sea preciso. Para ello,
482 JA VA : C U R S O DE PRO G R A M A CI N

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.

Los m todos cerrar y longitud para cerrar el fichero y calcular su longitud,


respectivam ente.

Los m todos ponerV alorE n , para sobreescribir un registro en una posicin


cualquiera dentro del fichero, y a a d ir para insertarlo al final.

El m todo valorEn para obtener un registro del fichero.

El m todo buscar para localizar un determ inado registro en el fichero.

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.

Segn lo expuesto, la declaracin de la clase C B aseD eD atos puede ser com o


se m uestra a continuacin. L os com entarios introducidos son suficientes para en
tender el cdigo sin necesidad de tener q ue abundar m s explicaciones.

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

p u b lic void cerrarO th rows IOException I fes.closeO ; I

public int longitudO | return nregs: I // n me r o de r e g i s t r o s

p u b lic boolean ponerValorEn( int i. CRegistro objeto )


th rows IO E x c e p tio n
I
if (i >=0 && i <= n r e g s )
I
// L o s 2 p r i m e r o s b y t e s q u e e s c r i b e w r i t e U T F i n d i c a n l a
// l o n g i t u d de l a S t r i n g q u e e s c r i b e a c o n t i n u a c i n . E s t a
// i n f o r m a c i n e s u t i l i z a d a p o r r e a d U T F .
i f ( o b j e t o . t a m a o ! ) + 2 > tamaoReg)
S y s t e m . e r r . p r i n t l n ( " t a m a o del r e g i s t r o e x c e d i d o " ) :
el s e
I
// S i t u a r e l p u n t e r o de L/E en e l r e g i s t r o i .
f e s . s e e k t i * tamaoReg):
// S o b r e e s c r i b i r e l r e g i s t r o con l a n u e v a i n f o r m a c i n
fes.w rite U TF(objeto.obte nerR efere ncia());
fe s.w ri te o u b le (o b je t o .o b t e n e r P r e c io ());
return true;
I
I
el se
S y s t e m . e r r . 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 );
return false;

public void a a d ir(C R e g istro obj) throws IOException


I
// A a d i r un r e g i s t r o a l f i n a l d e l f i c h e r o e incrementar
// e l n mero de r e g i s t r o s
i f ( p o n e r V a l o r E n ( n r e g s . obj ) ) n r e g s + + ;

public CRegistro valorEnt int i ) th rows IOException


I
if (i > = 0 && i < nregs)
[
// S i t u a r e l p u n t e r o de L /E en e l registro i.
fes.seek(i * 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;

public int buscar(String str. int nreg) th rows IOException


I
// B u s c a r un r e g i s t r o p o r una s u b c a d e n a de l a r e f e r e n c i a
// a p a r t i r d e un r e g i s t r o d e t e r m i n a d o . S i s e e n c u e n t r a .
// s e d e v u e l v e e l n me r o de r e g i s t r o , o -1 en o t r o c a s o .
C R e g i s t r o obj;
S trin g ref;
if (str n u i l ) re tu rn -1;
i f ( n r e g < 0 ) n r e g = 0;
fo r ( in t reg_i - nreg; reg_i < nregs: re g _ i+ + )
I
// O b t e n e r e l r e g i s t r o r e g _ i
o b j = v a l o r E n ( r e g _ i );
// O b t e n e r s u r e f e r e n c i a
r e f = o b j . o b t e n e r R e f e r e n c i a );
// s t r e s t c o n t e n i d a en r e f e r e n c i a ?
i f ( r e f . in d e x O f( s t r ) > -1)
r e t u r n r e g _ i ; // d e v o l v e r e l n me r o de r e g i s t r o
I
return -1; // la bsqueda fall

p u b lic boolean e l i m i n a r ( S t r i n g ref) th rows IOException


I
CRegistro o b j:
// B u s c a r l a r e f e r e n c i a y m a r c a r e l r e g i s t r o c o r r e s p o n d i e n t e
// p a r a p o d e r e l i m i n a r l o en o t r o p r o c e s o ,
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
// Obtener el r e g i s t r o re g _ i
obj = valorEn(reg_i) ;
// T iene la re fe re n c ia re f ?
if (ref.com pareTo(obj.obtenerReferencia()) = = 0)
I
// M a r c a r el r e g i s t r o con l a r e f e r e n c i a "borrar
o b j . a s i g n a r R e f e r e n c i a ( " b o r r a r " );
CA PTU LO 12: T R A B A JA R C O N FIC H ER O S 4 8 5

// G r a b a r l o
ponerValorEn! re g _ i . obj );
return true:

return false:

public void actualizare) th rows IOException


I
// C r e a r un f i c h e r o t e m p o r a l .
F i l e f i c h e r o T e m p = new F i 1e ( " a r t i c u l o s . t m p " ) ;
C B a s e D e D a t o s f t em p = new C B a s e D e D a t o s ( f i c h e r o T e m p ) ;

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

public static void nuevoFichl) throws IOException

// ...

public static void a b r i r F i c h l ) throws IOException

// ...

public static void aadirRegO th rows IOException

II...

public static void m o d if ic a r R e g t ) throws IOException

// ...

public static boolean e l i m i n a r R e g l ) th rows IOException

II...

public static void v i s u a l i z a r R e g s ! ) throws IOException


I
// ...

public static i n t men O


I
f 1 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 ' l . N u e v o f i c h e r o );
flu jo S .p rin tln ("2 . A brir fiche ro ");
f l u j o S . p r i n t l n ( " 3 . A a d i r r e g i s t r o );
f lu j o S . p r i n t l n ( "4. M od ificar r e g is t r o ") ;
f l u j o S . p r i n t l n ( 5. E l i m i n a r r e g i s t r o " ) ;
flu jo S.p rin tln ("6 . V isualizar re g istro s");
f l u j o S . p r i n t n ( 7. S a l i r " ) ;
f l u j o S . p r i n t l n );
flu joS.printl" Opcin: ") ;
i n t op;
do
CA PTU LO 12: TRA BA JA R CON FIC H ER O S 4 8 7

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

if ( o p > 2 && op < 7 && I f i c h e r o A b i e r t o )


I
f l u j o S . p r i n t l n( " N o h a y un f i c h e r o a b ie rto .'');
r e t u r n 0:
I
return op;

public static void m a in (S trin g [] args)


I
i n t o p c i n - 0;
boolean elim inado = f a ls e : // t r u e c u a n d o s e m a r q u e un r e g i s t r o
// p a r a "borrar
try
I
do
I
o p c i n - men():
sw itch (opcin)
(
c a s e 1: // n u e v o f i c h e r o
n u e v o F i c h t );
break;
c a s e 2 : // a b r i r f i c h e r o
a b r i r F i c h ( );
break;
c a s e 3: // a a d i r r e g i s t r o a l f i n a l d e l f i c h e r o
a a d i r R e g ( ):
break;
c a s e 4 : // m o d i f i c a r r e g i s t r o
m o d i f i c a r R e g ( );
break;
c a s e 5: // e l i m i n a r r e g i s t r o
e l i m i n a d o = e l i m i n a r R e g ):
break;
c a s e 6: // v i s u a l i z a r r e g i s t r o s
v i s u a l i z a r R e g s ):
break;
c a s e 7: // s a l i r
i f ( e l i m i n a d o ) a r t c u l o s . a c t u a l i z a r ( );
a rtc u lo s = nuil;

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.

F inalm ente, cuando se seleccione la opcin Salir, se actualizar el fichero


slo si se m arc algn registro para borrar. El resto de las operaciones (aadir y
m odificar) realizan los cam bios directam ente sobre el fichero.

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.

public static void nuevoFichO throws IOException


I
if (ficheroAbierto)
1
f 1u j o S . p r i n t l n ( " Y a h a y un f i c h e r o abierto."):
return:
I

f l u j o S . p r i n t " N o m b r e del f i c h e r o : " ) ;


F i l e o b j F i c h e r o = new F i 1e ( L e e r . d a t o ( ) ) ; // no mb r e f i c h e r o
w h i l e ( o b j 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 l n E s t e f i c h e r o e x i s t e . Escriba otro."):
o b j F i c h e r o = new F i 1 e ( L e e r . d a t o ( ) ) :
I
artculos = new C B a s e D e D a t o s ( o b j F i c h e r o ) ;
C A P T U L O 12: TRA BA JA R CON FIC H ER O S 4 8 9

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.

public static void abrirFichO th rows IOException


I
if (ficheroAbierto)
I
f 1u j o S . p r i n t l n ( " Y a h a y un f i c h e r o abierto."):
return;

f l u j o S . p r i n t ( " N o m b r e del f i c h e r o : " ) :


F i l e o b j F i c h e r o = new F i 1 e ( L e e r , d a t o ( ) ) ; // nombre f i c h e r o

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;

A adir un registro al fichero

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

m ensaje a a d ir (se ejecuta el m todo a adir de su clase) pasando com o argu


m ento el objeto C Registro obtenido a partir de los datos ledos.

public static void aadirRegO th rows IOException


I
Strin g referencia:
double pre cio:

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)):

M odificar un registro del fichero

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:

Finalm ente, slo si se eligi la opcin 3, enviar al objeto artculos el m ensaje


ponerV alorE n (se ejecuta el m todo ponerV alorE n de su clase) pasando com o a r
gum ento el objeto C R egistro obtenido a partir de los nuevos datos ledos.

public static void m odificarReg!) throws IOException


I
S trin g referencia:
double p re cio :
i n t o p, n r e g ;

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

if (op = = 3) artculos.ponerValorEntnreg. obj);

Eliminar un registro del fichero

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

public static b o o lea n e l i m i n a r R e g ) th rows IOException


I
S trin g referencia;
flu jo S . p rin t ( "R e fe re n c ia : ") : referencia = Leer.dato);
b o o l e a n e l i m i n a d o = a r t i c u l o s . e l i m i n a r ( r e f e r e n c i a ):
i f (elim inado)
f lu j o S . p r in t ln " r e g is t r o elim inado");
el se
i f ( a r t i c u l o s . 1 o n g i t u d ( ) ! = 0)
f l u j o S . p r i n t n( " r e f e r e n c i a no e n c o n t r a d a ' ' ) ;
else
f 1 u j o S . p r i n t l n ( 1 i s t a v a c i a " );
return eliminado;

Visualizar registros del fichero

El m todo visualizar R egs se disear para que visualice el conjunto de registros


cu y o cam po referencia coincida o contenga la cadena/subcadena solicitada a tra
vs del teclado. Para ello, enviar al objeto artculos el m ensaje buscar (se ejecuta
el m todo buscar de su clase) pasando com o argum entos la cadena/subcadena a
b uscar y el nm ero de registro donde debe em pezar la bsqueda (inicialm ente el
cero), proceso que se repetir utilizando el siguiente nm ero de registro al ltim o
encontrado, m ientras la bsqueda no falle.

public static void v i s u a l i z a r R e g s ) throws IOException


I
i n t n r e g = - 1 , n r e g s = a r t i c u l o s . 1 o n g i t u d );
i f (nregs = 0)
f l u j o S . p r i n t l n ( 1i s t a v a c i a " ) ;

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 buscar "):


Strin g s t r = Leer.dato);
CRegi s t r o o bj = n u i l ;

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

while (nreg != -1);


C A PTU LO 12: TRA BA JA R CON FIC H ER O S 4 9 3

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:

public class Cabecera


I
private class Posicin
I
// A t r i b u t o s
in t grad os, minutos;
f l o a t segundos:
II M t o d o s
// . . .
I
// P o s i c i n g e o g r f i c a d e l p u n t o
private Posicin latitud;
private Posicin longitud;
private int total_m uestras;
II M t o d o s
// . . .
I

A continuacin de la cabecera estarn especificadas todas las tem peraturas. Cada


una de ellas es un valor float.

El program a deber perm itir realizar las operaciones siguientes:

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:

public class CRegistro


I
// A t r i b u t o s
p r i v a t e i n t n m e r o M a t r 1c u l a ;
p r i v a t e S t r i n g nombre:
private Strin g c a lific a c i n :
// M t o d o s
// . . .
I

La calificacin viene dada por dos caracteres: SS (suspenso), A P (aprobado), NT


(notable) y SB (sobresaliente). R ealizar un program a que perm ita visualizar el %
de los alum nos suspendidos, aprobados, notables y sobresalientes.

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.

En el fichero m odificaciones se han grabado las m odificaciones que posterior


m ente realizarem os sobre el fichero alum nos. E n m odificaciones hay com o m
xim o un registro por alum no y se corresponden con:

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.

P o r tanto, no es posible asignar una cantidad fija de m em oria para una es


tructura dinm ica, y com o consecuencia un com pilador n o puede asociar direc
ciones explcitas con las com ponentes de tales estructuras. La tcnica que se
utiliza m s frecuentem ente p ara resolver este problem a consiste en realizar una
asignacin dinm ica p ara las com ponentes individuales, al tiem po que son creadas
durante la ejecucin del program a, en vez de hacer la asignacin de una sola vez
para un nm ero de com ponentes determ inado.

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

E ste captulo introduce tcnicas en program acin orientada a objetos para


co n stru ir estructuras abstractas de datos. U na vez que haya trabajado los ejem plos
d e este captulo, ser capaz de explotar en sus aplicaciones la potencia de las listas
enlazadas, pilas, colas y rboles binarios.

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.

Listas lineales simplemente enlazadas


U na lista lineal sim plem ente enlazada es una coleccin de objetos (elem entos de
la lista), cada uno d e los cuales contiene datos o una referencia a los datos, y una
referencia al siguiente objeto en la coleccin (elem ento de la lista). G rficam ente
puede representarse de la form a siguiente:
C A P T U L O 13: ESTR U C TU R A S DINM ICA S 4 9 7

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.

U na vez creada la clase de objetos C E lem entoLse la asignacin de m em oria


para un elem ento se hara as:

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 cdigo C E lem entoLse p define una referencia p a un objeto de la clase


C Elem entoLse. La sentencia p = new C E lem entoL sef) crea (asigna m em oria para)
un objeto de tipo C Elem entoLse, genera una referencia (direccin de m em oria)
que direcciona este nuevo objeto y asigna esta referencia a la variable p . L a sen
tencia p .siguiente = nuil asigna al m iem bro siguiente del objeto referenciado por
p el valor nuil, indicando as que despus de este elem ento no hay otro; esto es,
que este elem ento es el ltim o de la lista.

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

tenem os una lista de un elem ento:

nuil

Para aadir un nuevo elem ento a la lista, procederem os as:

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

Por ltim o, la sentencia p = q hace que la lista quede de nuevo referenciada


por p \ es decir, para nosotros p es siem pre el p rim er elem ento de la lista.

/
n u il

A hora p y q referencian al m ism o elem ento, al prim ero. Si ahora se ejecutara


una sentencia com o la siguiente qu sucedera?

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:

Q u sucede? Sucede que com o q.siguiente vale nuil, a q se le ha asignado el va


lor nuil. C onclusin, cuando en una lista utilizam os una referencia para ir d e un
elem ento al siguiente, en el ejem plo anterior q, direm os que hem os llegado al fi
nal de la lista cuando q tom a el valor nuil.

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

1. Insertar un elem ento en una lista.


2. B orrar un elem ento de una lista.
3. R ecorrer los elem entos de una lista.
4. B orrar todos los elem entos de una lista.
5. B uscar un elem ento en una lista.

Partiendo de las definiciones:

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:

public elass Test


I
public static v o i d main( StringC ] args )
I
C E l e m e n t o L s e p. q. r: // r e f e r e n c i a s
II ...

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.

Insercin de un elemento al comienzo de la lista

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;

El orden en el que se realizan estas operaciones es esencial. El resultado es:

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

System .out.p rin t("d a to : "):


w h i le ( ( n = L e e r .dato I n t )) != eof)
(
q = new C E 1 e m e n t o L s e t ):
q .dato = n :
q . s i g u i e n t e = p;
P - q;
System .out.p r in t ( "d a t o : "):

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

Insercin de un elemento en general

La insercin de un elem ento en la lista, a continuacin de otro elem ento cualquie


ra referenciado por r, es de la form a siguiente:

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

Insercin en la lista detrs d e l elem ento referenciado p o r r

La insercin de un elem ento en la lista antes de otro elem ento referenciado


por r, se hace insertando un nuevo elem ento detrs del elem ento referenciado por
r, intercam biando previam ente los valores del nuevo elem ento y del elem ento re
ferenciado por r.

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

Insercin en la lista antes d e l elem ento referenciado p o r r


C A P T U L O 13: ESTRU C TU R A S D IN M ICA S 5 0 3

Borrar un elemento de la lista

Para borrar el sucesor d e un elem ento referenciado p o r r, las operaciones a reali


zar son las siguientes:

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 )

B o rrar el su ceso r d e l elem ento referenciado p o r r

Un objeto es enviado a la basura para ser recogido p o r el recolector de basura


de Java, slo cuando se elim inan todas las referencias que perm iten acceder al
mismo.

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:

B orrar el elem ento referenciado p o r r

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 )

C om o ejercicio, escribir la secuencia de operaciones que perm itan borrar el


ltim o elem ento de una lista.
504 JA V A : C U R S O D E P R O G R A M A C I N

Recorrer una lista

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

Borrar todos los elementos de una lista

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:

p = nuil; // b o r r a r la lista referenciada por p

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.

Buscar en una lista un elemento con un valor x

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 .

UNA CLASE PARA LISTAS LINEALES


B asndonos en las operaciones bsicas sobre listas lineales descritas anterior
mente, vam os a escribir a continuacin una clase que perm ita crear una lista lineal
sim plem ente enlazada en la que cada elem ento conste de dos m iem bros: un valor
real de tipo d o u b le y una referencia a un elem ento del m ism o tipo.

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:

private cla ss CElemento


I
// A t r i b u t o s
p r i v a t e double dato;
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
p r i v a t e CElemento) II // c o n s t r u c t o r
I

Finalm ente, para sim plificar, la interfaz pblica de la ciase C ListaLinealSE


proporcionar solam ente tres m todos: un constructor sin parm etros, aadirAl-
Prncipio y m ostrarTodos.

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.

Segn lo expuesto, C L istaL inealSE ser as:


506 J A V A : C U R S O D E P R O G R A M A C I N

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

II E l e m e n t o de una l i s t a lineal simplemente enlazada


p r i v a t e c l a s s CElemento
I
// A t r i b u t o s
p r i v a t e double dato;
p r i v a t e C E l e m e n t o 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
p r i 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 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

public void m ostra rT o d o s)


I
// R e c o r r e r l a l i s t a
C E l e m e n t o q = p; // r e f e r e n c i a al prim er elemento
w h i l e ( q ! = n u l 1)
I
System .out.printCq.dato + ");
q = q.siguiente;

//////////////////////////////////////////////////////////////////

A poyndonos en esta clase, vam os a escribir una aplicacin basada en una


clase T est que cree una lista lineal sim plem ente enlazada que alm acene una serie
de valores de tipo d o u b le introducidos desde el teclado. F inalm ente, para verificar
que todo ha sucedido com o esperbam os, m ostrarem os la lista de valores.

Para llevar a cabo lo expuesto, el m todo m a in de esta aplicacin realizar


tres cosas:
C A PTU LO 13: ESTR U C TU R A S DINM ICA S 5 0 7

1. D efinir un objeto Ise de la clase C ListaLinealSE .


2. Solicitar datos de tipo d o u b le del teclado y los aadir a la lista, para lo cual
enviar al objeto Ise el m ensaje aadirA lP rincipio p o r cada dato que aada.
3. M ostrar la lista de datos, para lo cual enviar al objeto Ise el m ensaje mos-
trarTodos.

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

C on el fin de acercarnos m s a la realidad de cm o debe ser la clase C Lista


L inealSE , vam os a sustituir el m todo m ostrarTodos p o r otro m todo obtener que
devuelva el v alo r alm acenado en el elem ento i de la lista. D e esta form a, ser la
aplicacin que utilice la clase C L istaL inealSE la que decida qu hacer con el valor
retom ado (im prim irlo, acum ularlo, etc.).

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

p u b lic double obtener(int i)


I
if ( p == n u il)
I
S y s t e m . e r r .pri n t l n ( 1 i s t a v a c i a " ):
r e t u r n Double.NaN;

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

A hora, para que el m todo m a in de la aplicacin anterior m uestre los datos


utilizando este m todo, tenem os que reescribir la parte del m ism o que realizaba
este proceso, com o se indica a continuacin:

public static void m a in (S trin g [] args)


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

Clase genrica para listas lineales


La clase C L istaL inealSE im plem entada anteriorm ente ha sido diseada para m a
nipular listas de un tipo especfico de elem entos: datos de tipo double. No cabe
duda que esta clase tendra un m ayor inters para el usuario si estuviera diseada
para perm itir listas de objetos de cualquier tipo. sta es la direccin en la que va
mos a trabajar a continuacin. E n otros lenguajes com o C++, esto se hace u tili
zando plantillas. En Java se hace utilizando la clase O bject.

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:

public class C ListaLinealSE 1 ... )

public class C ListaLinealSE extends Object I ... 1

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 :

// E l e m e n t o de una l i s t a lineal simplemente enlazada


5 10 JA V A : CU R SO D E PRO G R A M A CI N

prvate class CElemento


I
// A t r i b u t o s
p riva te 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
p rivate CElementoO II // c o n s t r u c t o r

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;

//////////////////////////////////////////////////////////////////

V eam os ahora en qu se m odifica la aplicacin Test que creaba una lista de


valores de tipo d o u b le introducidos desde el teclado. Igual que antes, el mtodo
m a in de T est realizar tres cosas:

1. D efinir un objeto Ise de la clase C ListaLinealSE.


CListaLinealSE l s e = new C l i s t a L i n e a l S E ( ) :
CA PTU LO 13: ESTR U C TU R A S D IN M ICA S 5 1 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 ));

3. M ostrar la lista de valores, para lo cual enviar al objeto h e el m ensaje obte


ner por cada uno de los elem entos de la lista. El m todo obtener devuelve una
referencia de tipo O b je c t que, en nuestro caso, apunta a un objeto de su sub
clase D ou ble . Pero, si accedem os a un objeto de una subclase por m edio de
una referencia a su superclase, ese objeto slo puede ser m anipulado por los
m todos de su superclase. T endrem os entonces que convertir la referencia de
tipo O b je ct a tipo Dou ble . Segn estudiam os en el captulo 10, se trata de
una conversin explcita de una referencia del tipo de una superclase a una
referencia a una de sus subclases, lo cual slo puede hacerse si el objeto refe
renciado es del tipo de la subclase, condicin que en nuestro ejem plo se cum
ple, ya que el o bjeto es de la clase D ou ble .
Double d = ( D o u b l e ) 1 s e . o b t e n e r i );

A continuacin se m uestra la aplicacin Test com pleta:

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

A continuacin se m uestra el cdigo com pleto de la clase C ListaLinealSE.


O bservar que adem s de los m todos especificados en la tabla anterior, se ha aa
dido a la clase C E lem ento un constructor con parm etros.

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

// E l e m e n t o de una l i s t a lineal sim plemente en laz ada


p r i v a t e c l a s s CElemento
I
// A t r i b u t o s
p riv a t e Object datos:
p r i v a t e C E l e m e n t o s i g u i e n t e : // s i g u i e n t e e l e m e n t o
// M t o d o s
p r i v a t e C E l e m e n t 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 l O b j e c t d . C E l e m e n t o 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;
I

public C ListaLinealSE!) II // c o n s t r u c t o r

public int tamao!)


I
// D e v u e l v e e l n me r o de e l e m e n t o s d e l a l i s t a
C E l e m e n t o q = 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
i n t n = 0: // n me r o de e l e m e n t o s
w h i1e ( q != n u i l )
I
n++;
q = q.siguiente:
I
return n:
1

public boolean a a d i r ! i n t i, Object obj)


I
// A a d i r un e l e m e n t o en 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)
I
System .err.p rin tln !"nd ice fuera de l m i t e s " ) :
514 JA V A : C U R SO D E PRO G R A M A CI N

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 r e f e r e n c i a d a por p e st vacia, aadirlo sin ms


i f (nmeroDeElementos = 0)
I
// A a d i r e l prim er elemento
P = q:
return true;

// 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 boolean aadirAlPrincipioO bject obj)


I
// A a d i r un e l e m e n t o a l principio
return aadir(0. obj):

public boolean a a d ir A l F i n a l ( O b j e c t obj)


I
// A a d i r un e l e m e n t o a l f i n a l
r e t u r n a a d i r ( t a m a o ! ). o b j ) ;
I
CA PTU LO 13: ESTR U C TU R A S DINM ICA S 5 1 5

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 rra r P rim e ro ()


I
// B o r r a r e l p r i m e r e l e m e n t o
return borrar(O);

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

p u b lic Object o b te n e rtin t i)


I
// O b t e n e 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 - ta maot):
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;
516 JA V A: C U R S O DE PROGRAM A CIN

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:

p u b lic Object ob te n e rP rim e ro ()


I
// R e t o r n a r e l p r i m e r e l e m e n t o
r e t u r n o b t e n e r ( 0 ):

p u b lic Object o b te n e r ltim o ()


I
// R e t o r n a r e l l t i m o e l e m e n t o
re tu r n o b te n e r ( tamao() - 1):

//////////////////////////////////////////////////////////////////

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

public void a s i g n a r N o m b r e l S t r i n g nom)


CA PTU LO 13: ESTR U C TU R A S D IN M ICA S 5 1 7

nombre = nom:
)

public String obtenerNombret)


I
return n o mbr e :
1

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

El cdigo de la aplicacin Test que se m uestra a continuacin ensea cm o


crear y m anipular una estructura de datos com o la de la figura anterior:

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

public s t a t ic void m a in (S trin g [] args)


(
// C r e a r una l i s t a lin e a l vacia
C ListaLinealSE lse = new C L i s t a L i n e a l S E ( ) ;

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

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() + " " +


o b j.o b t e n e r N o t a )):
// M o s t r a r t o d o s
S y s te m . o u t.p r i n t l n ( Li s t a : " ) ;
m ostrarLista(lse):

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

A continuacin se presenta otra versin de la aplicacin Test utilizando ahora


la clase L in k e d L is t en lugar de C ListaLinealSE .

import java .u t i 1 .*;


//////////////////////////////////////////////////////////////////
// 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 class Test
1
public static void m o st r a r L is t a ( L in k e d L ist 1s e )
I
i n t i = 0, tam = l s e . s i z e O :
CDatos o b j ;
w h i l e ( i < tam)
I
o bj = ( C D a t o s ) 1 s e . g e t ( i );
System .out.p r in t n ( i + " + o b j .obtenerNombre() + " " +
o b j .o b t e n e r N o t a ( ) ) ;
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 v a c i a
L i n k e d L i s t I s e = new L i n k e d L i s t ( ) :
CA PTU LO 13: ESTR U C TU R A S DINM ICA S 5 2 1

// 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:

private class 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
C A P T U L O 13: E S T R U C T U R A S D IN M IC A S 523

// 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 ___________________________________________


tam ao D evuelve el nm ero de elem entos de la lista. N o tiene pa
rm etros.
aadirAIPrincipio A ade un elem ento al principio (el prim er elem ento es el
referenciado p o r ltim o.siguiente). 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.
aadirAlF inal A ade un elem ento al final (el ltim o elem ento siem pre
estar referenciado por ltim o). 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.
borrar B orra el elem ento prim ero (el p rim er elem ento es el refe
renciado por ltim o.siguiente). N o tiene parm etros. D e
vuelve una referencia al objeto borrado o n u il si la lista est
vaca.
524 JA V A: C U R SO D E PRO G R A M A CI N

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.

A continuacin se presenta el cdigo correspondiente a la definicin de la cla


se C L is ta d rcularSE:

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 ;

// E l e m e n t o de una l i s t a lineal circular sim plemente enlazada


p r i v a t e c l a s s CElemento
I
// 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 C E l e m e n t o s i g u i e n t e : // s i g u i e n t e e l e m e n t o
// M t o d o s
p r i v a t e C E l e m e n t o O I ) // c o n s t r u c t o r
p r i v a t e C E 1 e m e n t o ( O b j e c t d . C E l e m e n t o s ) // c o n s t r u c t o r
I
datos = d :
siguiente = s :

public C L ista C ire u la rS E ( ) 11 // c o n s t r u c t o r

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

public void aadirAlPrincip io(0bject obj)


I
// A a d e un e l e m e n t o a l p r i n c i p i o d e l a lista.
// C r e a r e l n u e v o e l e m e n t o
C E l e m e n t o q = new C E l e m e n t o t o b j , n u i l ) :

if( ltimo != nu il ) // e x i s t e una lista


I
q .siguiente = ltim o.siguiente:
ltim o.siguiente - q:
I
else // i n s e r c i n del prim er elemento
I
ltimo = q ;
ltim o.siguiente - q;
I

public void a a d irA lF in a l(O b je c t obj)


I
// A a d e un e l e m e n t o a l f i n a l de l a l i s t a .
// P o r l o t a n t o , l t i m o r e f e r e n c i a r e s t e n u e v o e l e m e n t o .
// C r e a r e l n u e v o e l e m e n t o .
C E l e m e n t o q = new C E l e m e n t o t o b j . n u i l ) :

if( ltimo != n u il ) // e x i s t e una l i s t a


I
q .siguiente = ltim o.siguiente:
ltimo = ltim o .sig u ie n te = q;
I
else // insercin del prim er elemento
I
ltimo = q :
ltim o.siguiente = q:

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 .

p u b lic Object o b te n e r tin t i)


I
II O b t e n e r e l e l e m e n t o d e l a p o s i c i n i
i n t nmeroDeElementos = t a m a o O ;
i f ( i > = n m e r o D e E l e m e n t o s || i < 0 )
return nu il:

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

U na v ez que hem os escrito la clase C ListaC ircularSE vam os a realizar una


aplicacin que utilizndola cree una lista circular y ponga a prueba las distintas
operaciones que sobre ella pueden realizarse. L os elem entos de esta lista sern
objetos de la clase C D atos utilizada en ejem plos anteriores. El cdigo de esta
aplicacin puede ser el siguiente:

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

while (i < tam)


I
o b j = ( C D a t o s )1 e s e . o b t e n e r ( i );
CA PTU LO 13: ESTR U C TU R A S D IN M ICA S 5 2 7

System .out. p r in t ln ( i + ".- " + o b j .obtenerNombre() + " " +


o b j .o b t e n e r N o ta )):
i++:
I
if ( t am = = 0 ) S y s t e m . o u t . p r i n t n ( "1 i s t a vacia"):

public static void m a in (S trin g [] args)


I
II C r e a r una l i s t a c i r c u l a r v a c i a
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 );

// 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:

M to d o____________ S ig n ificad o ______________________________________________


m eterE nP ila M ete un elem ento en la cim a de la pila (todas las insercio
nes se hacen por el principio de la lista). T iene un parm e
tro que es una referencia de tipo O b je c t al objeto a aadir.
N o devuelve ningn valor.
sacarD eP ila S aca el p rim er elem ento de la cim a de la pila, elim inndolo
de la m ism a (todas las supresiones se hacen por el principio
de la lista). N o tiene parm etros. D evuelve una referencia
_____________________ al objeto sacado de la pila o n u il si la pila est vacia._______

Segn lo expuesto, la definicin de esta clase puede ser as:

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

public void meterEnPila(Object obj)


I
a a d i r A l P r i n c i p i o ( o b j );
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
//////////////////////////////////////////////////////////////////

El constructor de la clase C Pila llam a prim ero al constructor de la clase base


que crea una lista con cero elem entos. El que la lista sea circular es transparente al
usuario de la clase.
CA PTU LO 13: ESTR U C TU R A S D IN M ICA S 5 2 9

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.

O bserve que la derivacin de la clase C P ila de C ListaC ircularSE no oculta al


usuario la interfaz pblica de sta, lo que perm itira utilizarla. Si quisiram os
ocultarla podram os haber declarado todos sus m iem bros de form a predeterm ina
da, adem s de d efinir la clase dentro de un paquete concreto (por ejem plo, es
tructuras). E ste es un trabajo que queda fuera de los propsitos de este captulo,
pero con lo explicado en el captulo de S ubclases e interfaces" no tendra ningu
na dificultad en hacerlo. Lo que se ha pretendido aqu es crear un interfaz espec
fica para el trabajo con pilas, y eso es lo que se ha hecho. V erem os una pequea
aplicacin despus de exponer el apartado relativo a colas.

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:

M to d o_____________S ig n ificad o _____________________________________________


m eterE nC ola M ete un elem ento al final de la cola (todas las inserciones
se hacen por el final de la lista). T iene un parm etro que es
una referencia de tipo O b je c t al objeto a aadir. No d e
vuelve ningn valor.
sacarD eC ola S aca el prim er elem ento de la cola, elim inndolo de la
m ism a (todas las supresiones se hacen por el principio de la
lista). N o tiene parm etros. D evuelve una referencia al ob-
_____________________ je to sacado de la co la o n u il si la cola est vaca.__________

Segn lo expuesto, la definicin de esta clase puede ser as:

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

// h a c e n p o r e l o t r o extremo (por el principio).


II
public class CCola extends CListaCircularSE
I
public CCola() 11

public void meterEnCola(Object obj)


I
a a d i r A l F i n a l ( o b j );
)

public Object sacarDeColaf)


I
r e t u r n b o r r a r ( ):
1
I
//////////////////////////////////////////////////////////////////

El constructor de la clase C C ola llam a p rim ero al constructor de la clase base


que crea una lista con cero elem entos. El que la lista sea circular es transparente al
usuario de la clase.

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.

O bserve que la derivacin de la clase C C ola de C L istaC ircularSE no oculta al


usuario la interfaz pblica de sta, lo que perm itira utilizarla. Lo que se ha pre
tendido aq u es crear un interfaz especfica para el trabajo con colas, y eso es lo
que se ha hecho. V ea la explicacin que hem os dado en este sentido al exponer las
pilas.

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

objeto in sta n c e o f clase

El resultado de una expresin com o la anterior es tr u e si el objeto es un


ejem plar de la clase y false en caso contrario. C om o ejem plo, observe el m todo
m ostrarLista de la aplicacin siguiente. E ste m todo tiene un parm etro que le
perm ite recib ir objetos de la clase C ListaC ircularSE o de sus derivadas: C P ila y
CCola. U tiliza el operador in s ta n c e o f para saber con qu clase de objeto est tra
bajando y enviarle as los m ensajes adecuados. Se puede observar que para sacar
un elem ento del objeto lista, si es de la clase CPila se le enva el m ensaje sacar-
D eP ila y si es la clase C C ola, sacarD eC ola\ en otro caso, no se hace nada.

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

System .out.p r i n t l n ( " 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 ( nombre:
w h i le ((nombre = L e e r . d a t o O ) != n u i l )
I
System .out.p r in t " n o t a : ");
n o t a = L e e r . d a t o D o u b l e t ):
p i 1a . m e t e r E n P i l a ( n e w C D a t o s ( n o m b r e . nota)):
cola.m eterEnColatnew CDatos(nombre, nota)):
System .out.printt"nom bre: "):
I
S y s t e m . o u t . p r i n t n ( " \ 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 '

Si ejecutam os esta aplicacin e introducim os los siguientes datos.

In tro d u c ir datos. Finalizar con C t r l + Z .


n o mbr e : A l u m n o 1
nota: 7.5
n o mbr e : A l u m n o 2
nota: 8.5
n o mbr e : A l um n o 3
nota: 9.5
nombre: [ C t r l + Z ]

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 :

T am bin se puede observar en estos resultados, que en las pilas el ltim o ob


jeto en entrar es el prim ero en salir y en las colas, el prim ero en entrar es el prim e
ro en salir.

LISTA DOBLEMENTE ENLAZADA


En una lista doblem ente enlazada, a diferencia de una lista sim plem ente enlazada,
cada elem ento tiene inform acin de dnde se encuentra el elem ento posterior y el
elem ento anterior. E sto perm ite leer la lista en am bas direcciones. E ste tipo de
listas es til cuando la insercin, borrado y m ovim iento de los elem entos son ope
raciones frecuentes. U na aplicacin tpica es un procesador de textos, donde el ac
ceso a cada lnea individual se hace a travs de una lista doblem ente enlazada.

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.

En el apartado siguiente se expone la form a de construir y m anipular una lista


circular doblem ente enlazada.
534 JA V A : C U R S O D E P R O G R A M A C I N

Lista circular doblemente enlazada


U na lista circular doblem ente enlazada (led e) es una coleccin de objetos, cada
uno de los cuales contiene datos o una referencia a los datos, una referencia al
elem ento siguiente en la coleccin y una referencia al elem ento anterior. G rfica
m ente puede representarse de la form a siguiente:

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:

private class CElemento


I
// 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 CElemento a n t e r i o r : // a n t e r i o r e l e m e n t o
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 e l e m e n t o

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

A continuacin se presenta el cdigo correspondiente a la definicin de la cla


se C ListaC ircularD E :
536 JA V A : C U R S O D E P R O G R A M A C I N

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

// E l e m e n t o de una l i s t a lineal circular doblemente enlazada


p r i v a t e c l a s s CElemento
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 CElemento a n t e r i o r ; // a n t e r i o r e l e m e n t o
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 e l e m e n t o

// M t o d o s
p riva te CElementoO II // c o n s t r u c t o r

public C ListaC ircu larD EO // c o n s t r u c t o r


I
a c t u a l = l t i m o = n u l 1:
n m e r o D e E l e m e n t o s = OL;
p o s i c i n = - I L : // l a p o s i c i n del p rim e r elemento s e r la 0

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:

public void insertar(Object obj)


I
II A a d e un n u e v o e l e m e n t o a l a l i s t a a c o n t i n u a c i n
// d e l e l e m e n t o a c t u a l ; e l n u e v o e l e m e n t o p a s a a s e r el
// a c t u a l .
C E l e m e n t o q:

if (ltim o == n u il) // lista vacia


I
l t i m o = new C E l e m e n t o O :
CA PTU LO 13: E S T R U C T U R A S D IN M IC A S 5 3 7

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

actual = q: // e l nuevo elemento pasa a s e r el actual.


I // f i n else

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 irA lSigu ie n te )


I
// A v a n z a l a p o s i c i n a c t u a l al s i g u i e n t e elemento,
i f (posicin < n m e r o D e E l e m e n t o s - 1)
I
actual = a c t u a l.s ig u ie n te ;
p o s i c i n++:

public void irA lA nterior()


I
II R e t r a s a l a posicin actual al elemento a n t e r i o r ,
i f ( posicin > 01 )
I
actual = a c t u a l.a n t e r i o r ;
p o s i c i n - -;
)
)

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:

public boolean irAl(long i)


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
l o n g n m er o D e E l e m e n t o s - t a m a o O ;
i f ( i > - n m e r o D e E l e m e n t o s || i < 0 ) return false:

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:

p u b lic Object o b te n e rlo n g i)


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 de I n d i c e i .
i f ( ! i r A l ( i ) ) r e t u r n n u l 1:
r e t u r n o b t e n e r ( );

pu b lic void m o d ifica r(0 b je c t pNuevosDatos)


i
// El m t o d o m o d i f i c a r e s t a b l e c e n u e v o s d a t o s p a r a el
// 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 : // l i s t a v a c i a

a c t u a l. d a t o s = pNuevosDatos:

//////////////////////////////////////////////////////////////////

C uando se declara un objeto de la clase C U staC ircularD E , se ejecuta el


constructor de la m ism a que realiza las siguientes operaciones:
540 JA V A: C U R S O DE PROGRAM A CIN

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.

A signa un valor 0 al atributo nrneroD eElem entos y un valor -1 a p o si


cin; el valor de este atributo pasar a ser 0 cuando se aada el prim er
elem ento.

El m todo insertar de la clase C L istaC ircularD E aade un elem ento a la lista


a continuacin del elem ento actual. C ontem pla dos casos: que la lista est vaca, o
que la lista ya exista. El elem ento insertado pasa a ser el elem ento actual, y si se
aade al final, ste pasa a ser el ltim o y el actual. A adir un elem ento im plica
realizar los enlaces con el anterior y siguiente elem entos y actualizar los parm e
tros a ctu a l, nrneroD eElem entos y ltim o, si procede.

El m todo b orrar devuelve una referencia al objeto de datos asociado con el


elem ento actual, elem ento que ser enviado a la basura cuando finalice la ejecu
cin del m todo por quedar desreferenciado. C ontem pla dos casos: que el ele
m ento a borrar sea el ltim o o que no lo sea. Si el elem ento a borrar es el ltim o, y
slo quedaba ste, los atributos de la lista deben iniciarse igual que lo hizo el
constructor; si quedaban m s de uno, el que es ahora el nuevo ltim o p asa a ser
tam bin el elem ento actual. Si el elem ento a borrar no era el ltim o, el elem ento
siguiente al elim inado pasa a ser el elem ento actual. El m todo devuelve n u il si la
lista est vaca.

Para el resto de los m todos es suficiente con la explicacin dada al principio


de este apartado, adem s de en el cdigo.

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

public static void m a in (S trin g [] args)


(
// C r e a r un a l i s t a v a c i a
C L i s t a C i r c u l a r D E l c d e - new C L i s t a C i r c u l a r D E ( ) :

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

De un modo ms form al, direm os que un rbol es un conjunto finito de uno o


m s nodos tales que:

a) Existe un nodo especial llam ado raz del rbol, y


b) los nodos restantes estn agrupados en n > 0 conjuntos disjuntos A, ... , A,
cada uno de los cuales es a su v ez un rbol que recibe el nom bre de subrbol
de la raz.

Evidentem ente, la definicin dada es recursiva; es decir, hem os definido un


rbol com o un conjunto de rboles, que es la form a m s apropiada de definirlo.

De la definicin se desprende, que cada nodo de un rbol es la raz de algn


subrbol contenido en la totalidad del m ism o.

El nm ero de ram as de un nodo recibe el nom bre de grado del nodo.

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

El rbol binario es una estructura de datos m uy til cuando el tam ao de la


estructura no se conoce, se necesita acceder a sus elem entos ordenadam ente, la
velocidad de bsqueda es im portante o el orden en el que se insertan los elem en
tos es casi aleatorio.

En definitiva, un rbol binario es una coleccin de objetos (nodos del rbol)


cada uno de los cuales contiene datos o una referencia a los datos, una referencia a
su subrbol izquierdo y una referencia a su subrbol derecho. Segn lo expuesto,
la estructura de datos representativa de un nodo puede ser de la form a siguiente:

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

La definicin dada de rbol binario, sugiere una form a natural de representar


rboles binarios en un ordenador. U na variable raz referenciar el rbol y cada
nodo del rbol ser un objeto de la clase C Nodo. E sto es, la declaracin genrica
de un rbol binario puede ser as:

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 CNo d o r a z ; // 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
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.

Formas de recorrer un rbol binario


O bserve la figura expresin algebraica m ostrada anteriorm ente partiendo del
nodo raz, qu orden seguim os para poder evaluar la expresin que representa el
rbol? Hay varios algoritm os para el m anejo de estructuras en rbol y un proceso
que generalm ente se repite en estos algoritm os es el de recorrido de un rbol. Este
proceso consiste en exam inar sistem ticam ente los nodos de un rbol, d e forma
que cada nodo sea visitado solam ente una vez.

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

F orm as de recorrer un rbol

E videntem ente, las definiciones dadas son definiciones recursivas, y a que, re


correr un rbol utilizando cualquiera de ellas, im plica recorrer sus subrboles em
pleando la m ism a definicin.

Si se aplican estas definiciones al rbol binario de la figura expresin alge


braica m ostrada anteriorm ente, se obtiene la siguiente solucin:

Preorden: / + a * b c - d / e f
Inorden: a + b * c / d - e / f
Postorden: a b c * + d e f / - /

El recorrido en preorden produce la notacin p refija ; el recorrido en inorden


produce la notacin convencional; y el recorrido en postorden produce la notacin
p ostfijo o inversa.

L os nom bres de preorden, inorden y postorden derivan del lugar en el que se


visita la raz con respecto a sus subrboles. E stas tres form as, se exponen a conti
nuacin com o tres m todos recursivos de la clase C A rbolB inario, con un nico
parm etro r que representa la raz del rbol cuyos nodos se quieren visitar.

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

public void 1 no r d e n ( G N ' o d o r )


I
if ( r != n u i l )
(
i n 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
// 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
inorden( r.d e re c h o ): // s e v i s i t a e l s u b r b o l derecho
1

public void postorden(CNodo r)


I
if ( r ! = n u 11 )
I
p o s t o r d e n t r . i z q u i e r d o ) : II s e v i s i t a e l s u b r b o l izquierdo
postorden r.derecho): // s e v i s i t a e l s u b r b o l derecho
// 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
// con e l n o d o r e f e r e n c i a d o r

/////////////////////////////////////////////////////////////////

RBOLES BINARIOS DE BSQUEDA


U n rbol binario de bsqueda es un rbol ordenado; esto es, las ram as de cada
nodo estn ordenadas de acuerdo con las siguientes reglas: para todo nodo a, to
das las claves del subrbol izquierdo de a, son m enores que la clave de a, y todas
las claves del subrbol derecho de a son m ayores que la clave de a.

C on un rbol de estas caractersticas, encontrar si un nodo de una clave de


term inada existe o no es una operacin m uy sencilla. P or ejem plo, observando la
figura siguiente, localizar la clave 35 es aplicar la definicin de rbol de busque-
CA PTU LO 13: ESTRU C TU R A S D IN M ICA S 5 4 7

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.

rbol binario de bsqueda

En Java podem os autom atizar el proceso de im plem entar un rbol binario de


bsqueda diseando una clase C ArbolBinB (C lase A rb o l Binario de Bsqueda)
que proporcione los atributos y m todos necesarios para crear cada nodo del r
bol, as com o para perm itir el acceso a los m ism os. La clase que diseam os a
continuacin cubre estos objetivos.

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:

M to d o ____________ S ig n ificad o _____________________________________________


C ArbolBinB Es el constructor. C rea un rbol vaco (raz a nuil).
insertar Inserta un nodo en el rbol binario basndose en la defini
cin de rbol binario de bsqueda. T iene un parm etro que
es una referencia de tipo O b je c t al objeto a aadir. D evuel
ve un 0. definido por la constante C O RREC TO , si la opera
cin de insercin se realiza satisfactoriam ente, o un valor
548 JA V A : C U R S O D E P R O G R A M A C I N

distinto de 0, definido por alguna de las constantes si


guientes: N O _D A T O S si la raz es igual a nuil, o
YA_EXISTE si el nodo con esos datos ya existe.
borrar B orra un nodo de un rbol binario de bsqueda. T iene un
parm etro para alm acenar una referencia de tipo O b je c t a
los datos que perm itirn localizar en el rbol el nodo que se
desea borrar. D evuelve una referencia al rea de datos del
nodo borrado, o bien n u il si el rbol est vaco o no existe
un nodo con esos datos.
buscar Busca un nodo determ inado en el rbol. T iene un parm e
tro para alm acenar una referencia de tipo O b je c t a los d a
tos que perm itirn localizar el nodo en el rbol. D evuelve
una referencia al rea de datos del nodo, o bien n u il si el
rbol est vaco o no existe un nodo con esos datos.
inorden Recorre un rbol binario utilizando la form a inorden. Tiene
dos parm etros: el prim ero especifica la referencia al nodo
a partir del cual se realizar la visita; el valor del prim er pa
rm etro slo ser tenido en cuenta si el segundo es false,
porque si es tr u e se asum e que el p rim er parm etro es la
raz del rbol. N o devuelve ningn valor.
com parar M todo que debe ser redefinido por el usuario en una sub
clase para especificar el tipo de com paracin que se desea
realizar con dos nodos del rbol. D ebe de devolver un ente
ro indicando el resultado de la com paracin (-1, 0 I si
n o d o l< n o d o 2 , n o d o l = =nodo2. o n o d o l> n o d o 2 , respecti
vam ente). E ste m todo es invocado por los m todos inser
tar, borrar y buscar.
proceso M todo que debe ser redefinido p o r el usuario en una sub
clase para especificar las operaciones que se desean realizar
con el nodo visitado. Es invocado p o r el m todo inorden.
visitarlnorden M todo sin parm etros que debe ser redefinido por el usua
rio en una subclase para invocar al m todo inorden.

A continuacin se presenta el cdigo correspondiente a la definicin de la cla


se C ArbolBinB:

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

// P o s i b l e s e r r o r e s q u e s e p u e d e n dar re la tiv o s a un nodo


public s t a t i c f i n a l i n t CORRECTO = 000;
public s t a t i c f i n a l i n t NO_DATOS = 100
public s t a t i c f i n a l i n t YA_EXISTE = 101
public s t a t i c f i n a l i n t N0_EXISTE = 102

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

p u b lic Object b u sc a r(0 b je c t obj)


I

public int insertar(0bject obj)


550 J A V A : C U R S O D E P R O G R A M A C I N

public void inordent CNodo r , boolean nodoRaiz)


I
// El m t o d o r e c u r s i v o i n o r d e n v i s i t a l o s n o d o s d e l r b o l
II u t i l i z a n d o l a forma i n o r d e n ; e s t o e s , p r i m e r o s e v i s i t a
// el su b r b o l i z q u i e r d o , despus se v i s i t a la r a z , y por
// l t i m o , el su b r b o l derecho.
// S i el segundo parm etro es t r u e , la v i s i t a comienza
// 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 p a r m e t r o .

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 .

/////////////////////////////////////////////////////////////////

Buscar un nodo en el rbol


El m todo buscar cuyo cdigo se m uestra a continuacin perm ite acceder a los
datos de un nodo del rbol. Su sintaxis es la siguiente:

pu blic Object buscartObject obj)

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.

pu b lic Object buscar(Object obj)


I
// El m t od o b u s c a r p e r m i t e a c c e d e r a un d e t e r m i n a d o n o do .
CNodo a c t u a l = r a z ;
i n t nComp = 0:

// B u s c a r un n o d o q u e t e n g a asociados los datos dados p o r obj


w h i 1e ( a c t u a l ! = n u i l )
I
if ( ( nComp = c o m p a r a r e o b j . a c t u a l . d a t o s ) ) - - 0)
r e t u r n ( a c t u a l . d a t o s ): // CORRECTO ( n o d o e n c o n t r a d o )
e l s e i f ( nComp < 0 ) // b u s c a r en e l s u b r b o l i z q u i e r d o
actual - actual .izquierdo;
else // b u s c a r en e l subrbol derecho
actual = actual.derecho:
I
return n u l 1; // N 0 _ E X I S T E

Insertar un nodo en el rbol


El m todo insertar cuyo cdigo se m uestra a continuacin perm ite aadir un nodo
que an no existe en el rbol. Su sintaxis es la siguiente:

public int insertar(Object obj)

El parm etro o b j se refiere al objeto de datos que ser apuntado p o r el nodo


que se aadir al rbol. D evuelve un entero N O _D A T O S si o b j es nuil, C O RREC
TO si la operacin de insertar se ejecuta con xito, y Y A_EXISTE si ya hay un no
do con los datos referenciados p o r obj.

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

m ism o proceso descrito en el m todo buscar), en cuyo caso, com o ya se indic en


el prrafo anterior, lo notificar. Si ese nodo no se encuentra, el proceso de bs
queda nos habr conducido hasta un nodo term inal, posicin donde lgicamente
debe aadirse el nuevo nodo que alm acenar la referencia o b j a los datos.

public int in se rta r(O b je ct obj)


I
// El m t od o i n s e r t a r p e r m i t e a a d i r un n o d o que a n no e s t
// en e l r b o l .
CNodo l t i m o = n u i l , a c t u a l = r a i z :
i n t nComp = 0;
i f ( obj n u i l ) r e t u r n N0_DAT0S;

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

if ( actual = nuil ) // n o s e e n c o n t r e l nodo, aadirlo


I
CNodo n u e v o N o d o = new C N o d o ( ) :
nuevoNodo.datos = obj:
n u evoN od o.izq uierd o - nuevoNodo.derecho = n u i l :
// El n o d o a a a d i r p a s a r a s e r l a r a z d e l r b o l t o t a l s i
// s t e e s t v a c i o , d e l s u b r b o l i z q u i e r d o d e " l t i m o " s i l a
// c o m p a r a c i n f u e m e n or , o d e l s u b r b o l d e r e c h o de " l t i m o " s i
// l a c o m p a r a c i n f u e m a y o r ,
i f ( ltimo = n u i l ) // r b o l v a c i o
r a z = nuevoNodo:
e l s e i f ( nComp < 0 )
l t i m o . i z q u i e r d o = nuevoNodo:
el se
l t i m o . d e r e c h o = nuevoNodo:
r e t u r n CORRECTO:
) // f i n d e l b l o q u e i f ( a c t u a l - - n u i l )
e l s e // e l n o d o y a e x i s t e en e l r b o l
r e t u r n Y A _ E X 1S T E ;
C A P T U L O 13: ESTR U C TU R A S D IN M ICA S 5 5 3

Borrar un nodo del rbol


A continuacin se estudia el problem a de borrar un determ inado nodo de un rbol
que tiene las claves ordenadas. E ste proceso es una tarea fcil si el nodo a borrar
es un nodo term inal o si tiene un nico descendiente. La dificultad se presenta
cuando deseam os borrar un nodo que tiene dos descendientes (en la figura, 17), ya
que con una sola referencia no se puede apuntar en dos direcciones. E n este caso,
el lugar en el rbol del nodo a borrar ser reem plazado p o r su sucesor presentn
dose dos casos: si tom am os com o sucesor la raz d e su subrbol izquierdo (13), su
subrbol derecho (21) lo ser ahora del nodo m s a la derecha (13) en el subrbol
izquierdo (13), y si tom am os com o sucesor la raz de su subrbol derecho (21), su
subrbol izquierdo (13) lo ser ahora del nodo m s a la izquierda (18) en el subr
bol derecho (21).

B orrar e l nodo con clave 17

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:

1. El nodo a borrar es un nodo term inal; no tiene descendientes.


2. El nodo a borrar no tiene subrbol izquierdo.
3. El nodo a borrar no tiene subrbol derecho.
554 JA V A : C U R S O D E P R O G R A M A C I N

4. El nodo a borrar tiene subrbol izquierdo y derecho.

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.

p u b lic Object b o rra r(O b je c t obj)


I
// El m t o d o b o r r a r p e r m i t e e l i m i n a r un n o d o d e l rbol.
CNodo l t i m o = n u i l , a c t u a l = r a z ;
CNodo m a r c a d o = n u i l , s u c e s o r = n u i l ;
i n t n A n t e r i o r C o m p = 0. nComp = 0;

if (obj == n u i l ) return n u il: // N 0 _ D A T 0 S

// C o m i e n z a l a bsqueda para ve rificar si 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 .
while ( actual != n u l 1 )
I
n A n t e r i o r C o m p = nComp; // r e s u l t a d o de l a comparacin a n t e r i o r
i f ( ( nComp = c o m p a r a r t 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
ltimo = actual ;
i f ( nComp < 0 ) // b u s c a r en e l subrbol izquierdo
actual = a c t u a l. izquierdo;
else // b u s c a r en e l subrbol derecho
actual = actual.derecho;
I
) // f i n del bloque w hile ( actual != n u i l )

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

Utilizacin de la clase CArboIBinB


La clase C ArboIBinB es una clase abstracta; p o r lo tanto, para hacer uso del so
porte que proporciona para la construccin y m anipulacin de rboles binarios de
bsqueda, tendrem os que derivar una clase de ella y redefinir los m todos abs
tractos heredados: com parar, p ro ce sa r y visitarlnorden. L a redefinicin de estos
m todos est condicionada a la clase de objetos que form arn parte del rbol.

C om o ejem plo, vam os a construir un rbol binario de bsqueda en el que cada


nodo haga referencia a un objeto de la clase C D atos ya utilizada anteriorm ente en
este m ism o captulo. Esto sugiere pensar en la clave de ordenacin que se utilizar
para construir el rbol. En nuestro ejem plo vam os a ordenar los nodos del rbol
p o r el atributo nom bre de CD atos. Se trata entonces de una ordenacin alfabtica;
por tanto, el m todo com parar d ebe ser redefm ido para que devuelva - 1 , 0 1 se
gn sea el nom bre de un objeto C D atos, m enor, igual o m ayor, respectivam ente,
que el nom bre del otro objeto con el que se com para.

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

C uando se declare un objeto de la clase C A rbolB inarioD eB usqueda, el cons


tructor de esta clase invoca al constructor C ArbolBinB de su clase base, que crear
un rbol vaco (raz = nuil). El atributo raz apunta siem pre a la raz del rbol.

F inalm ente, escribirem os una aplicacin Test que, utilizando la clase C Ar


bolB inarioD eB usqueda, cree un objeto arbolbb correspondiente a un rbol binario
de bsqueda en el que cada nodo haga referencia a un objeto C D atos que encap-
sule el nom bre de un alum no y la nota de una determ inada asignatura que est
cursando. C on el fin de probar que todos lo m todos proporcionados por la clase
funcionan adecuadam ente (piense en los m todos heredados y en los redefinidos),
la aplicacin realizar las operaciones siguientes:

1. C rear un o b jeto arbolbb de la clase C ArbolBinarioD eBusqueda.

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.

3. D urante la construccin del rbol, perm itir m odificar la nota de un alum no ya


existente, o bien elim inarlo. Para discrim inar una operacin de otra tomaremos
com o referencia la nueva nota: si es positiva, entenderem os que deseam os m o
dificar la nota del alum no especificado y si es negativa, que hay que eliminarlo.

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;

S y s t e m . o u t .p rin t n ( " In tr o d u c ir datos. Finalizar con C t r l + Z . " ) :

System .out.print"nom bre: "):


w h i l e ((nombre = L e e r . d a t o O ) !- nu il)
I
System .out.p r i n t " n o t a : ");
n o t a = L e e r . d a t o D o u b l e ):
cod - r b o l b b . i n s e r t a r t n e w C D a to s ( n o m b re , nota)):
558 JA V A : C U R S O D E P R O G R A M A C I N

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

System .out.print("nom bre: ):


I
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 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

RBOLES BINARIOS PERFECTAMENTE EQUILIBRADOS


U n rbol binario est perfectam ente equilibrado si, para todo nodo, el nm ero de
nodos en el subrbol izquierdo y el nm ero de nodos en el subrbol derecho, di
fieren com o m ucho en una unidad.

rboles p erfectam ente equilibrados

C om o ejem plo, considere el problem a de construir un rbol perfectam ente


equilibrado siendo los valores de los nodos, n referencias a objetos de la clase
C D atos im plem entada anteriorm ente en este m ism o captulo. R ecuerde que cada
objeto de esta clase encapsula el nom bre de un alum no y la nota de una determ i
nada asignatura que est cursando.
C A P T U L O 13: ESTR U C TU R A S D IN M IC A S 5 5 9

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:

1. U tilizar un nodo para la raz.


2. G enerar el subrbol izquierdo con n i = n/2 nodos utilizando la m ism a regla.
3. G enerar el subrbol derecho con n d = n-ni-1 nodos utilizando la m ism a regla.

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.

private class CNodo

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

En Java podem os autom atizar el proceso de im plem entar un rbol binario


perfectam ente equilibrado diseando una clase C A rholB inE (C lase A rb o l Binario
E quilibrado) que proporcione los atributos y m todos necesarios para crear cada
nodo del rbol, as com o para perm itir el acceso a los m ism os.

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:

M to d o_____________S ig n ificad o_____________________________________________


C ArboIB inE Es el constructor; com o es igual que el constructor por
om isin, podra om itirse. C rea un rbol vaco (raz a nuil).
construirA rbol Es un m todo privado que perm ite construir un rbol bina
rio perfectam ente equilibrado. T iene un parm etro de tipo
in t que se corresponde con el nm ero d e nodos que va a te
ner el rbol. D evuelve una referencia a la raz del rbol.
560 JA V A : C U R S O DF. P R O G R A M A C I N

constru rA rbolE qui librado


Invoca al m todo construirA rbol pasando com o argum ento
el nm ero de nodos y alm acena el v alor devuelto p o r l, en
el atributo raz de la clase. N o devuelve nada. Su m isin es
evitar que el usuario de la clase tenga que utilizar directa
m ente el atributo raz,
b u sca r B usca un nodo determ inado en el rbol. T iene un parm e
tro para alm acenar una referencia de tipo O b je c t a los da
tos que perm itirn localizar el nodo en el rbol. D evuelve
una referencia al rea de datos del nodo, o bien nuil si el
rbol est vaco o no existe un nodo con esos datos. O pcio
nalm ente se puede especificar un segundo parm etro co
rrespondiente a la posicin del nodo segn el orden de
acceso seguido p o r el m todo inorden (consideram os q ue la
prim era posicin es la 0).
inorden R ecorre un rbol binario utilizando la form a inorden. Tiene
dos parm etros: el prim ero especifica la referencia al nodo
a partir del cual se realizar la visita; el valor del p rim er pa
rm etro slo ser tenido en cuenta si el segundo es false.
porque si es tr u e se asum e que el p rim er parm etro es la
raz del rbol. N o devuelve ningn valor.
leerD atos M todo q ue debe ser redefinido por el usuario en una sub
clase para que perm ita leer los datos que sern referencia-
dos p o r un nodo del rbol. D evuelve el objeto de datos. Es
invocado p o r el m todo construirArbol.
com parar M todo que debe ser redefinido p o r el usuario en una sub
clase para especificar el tipo de com paracin que se desea
realizar con dos nodos del rbol. D ebe d e devolver un ente
ro indicando el resultado de la com paracin (-1, 0 1 si
n o d o l < nodo2, n o d o l = =nodo2, o n o d o l> n o d o 2 . respecti
vam ente). E ste m todo es invocado por los m todos inser
tar, borrar y buscar,
pro ceso M todo que debe ser redefinido p o r el usuario en una sub
clase para especificar las operaciones que se desean realizar
con el nodo visitado. Es invocado p o r el m todo inorden.
visitarlnorden M todo sin parm etros que debe ser redefinido por el usua-
_____________________ rio en una subclase para invocar al m todo inorden.________

A continuacin se presenta el cdigo correspondiente a la definicin de la cla


se C A rbolB inE :

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

private CNodo c o n s t r u ' r A r b o l ( i n t n )


I
// C o n s t r u y e un r b o l de n n o d o s p e r f e c t a m e n t e e q u i l i b r a d o

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

p riva te void buscar(Object obj. CNodo r . O b j e c t [ ] datos, i n t [] pos)


(
II El m t o d o b u s c a r p e r m i t e a c c e d e r a un d e t e r m i n a d o n o do .
// S i l o s d a t o s e s p e c i f i c a d o s p o r " o b j " s e l o c a l i z a n en el
// r b o l r e f e r e n c i a d o p o r " r a p a r t i r de l a p o s i c i n " p o s [ 0 ] " ,
// " b u s c a r " d e v u e l v e en d a t o s [ 0 ] l a r e f e r e n c i a a e s o s d a t o s :
// en o t r o c a s o , d e v u e l v e n u i l .
// L o s n o d o s s e c o n s i d e r a n n u m e r a d o s ( 0 . 1. 2. . . . ) s e g n
// e l o r d e n en e l q u e s o n a c c e d i d o s p o r e l m t o d o " i n o r d e n " .
CNodo a c t u a l = r ;

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

public Object b u sc a r(0 b je c t obj)


I
return buscar(obj, 0):

p u b lic Object b u scar(O b ject obj. int posicin)


I
O b j e c t t ] d a t o s = ( n u i l ):
i n t [ ] pos = I p o s i c i n ) ;
buscar(obj. ra z , datos, pos):
return d a to stO ]:
CA PTU LO 13: ESTR U C TU R A S D IN M ICA S 5 6 3

public void inorden( CNodo r . boolean nodoRaiz )


I
// El m t od o r e c u r s i v o i n o r d e n v i s i t a l o s n o d o s d e l r b o l
// u t i l i z a n d o l a f o r m a i n o r d e n : e s t o e s , p r i m e r o s e v i s i t a
// el s u b r b o l i z q u i e r d o , d e s p u s s e v i s i t a l a r a z , y p o r
// l t i m o , e l s u b r b o l d e r e c h o .
// 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 .
CNodo a c t u a l = n u i l ;

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 .

/////////////////////////////////////////////////////////////////

El proceso de construccin lo lleva a cabo el m todo recursivo denom inado


construir A rb o l, el cual construye un rbol de n nodos (ste, es a su vez invocado
por construirA rbolE quilibrado). El prototipo de este m todo es:

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.

El m todo privado bu sca r tam bin se ha declarado com o un m todo recursi


vo. P erm ite acceder a unos datos determ inados, com enzando la bsqueda desde
cualquier nodo. Para facilitar la labor del usuario de la clase, se ha aadido a la
interfaz pblica de la m ism a dos sobrecargas de este m todo: una con un parm e
564 JA V A: C U R S O DE PRO G R A M A CI N

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.

Utilizacin de la clase CArboIBinE


L a clase C ArboIBinE es una clase abstracta; p o r lo tanto, para h acer uso del so
porte que proporciona para la construccin y m anipulacin de rboles binarios
perfectam ente equilibrados, tendrem os que derivar una clase de ella y redefinir ios
m todos abstractos heredados: leerD atos, com parar, p ro ce sa r y visitarlnorden.
La redefm icin de estos m todos est condicionada a la clase de objetos que for
m arn parte del rbol.

C om o ejem plo, vam os a construir un rbol binario perfectam ente equilibrado


en el que cada nodo haga referencia a un objeto de la clase C D atos y a utilizada
anteriorm ente en este m ism o captulo.

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.

S egn lo expuesto, la clase C A rbolB inarioE quilibrado derivada de CAr-


bolB inE puede ser de la form a siguiente:

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

/////////////////////////////////////////////////////////////////

C uando se declare un objeto de la clase C A rbolB inario E quilibrado, el cons


tructor de esta clase invoca al constructor C ArboIBinE de su clase base, que crear
un rbol vaco (ra z = nuil). El atributo raz apunta siem pre a la raz del rbol.

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:

1. C rear un objeto arbolbe de la clase C ArbolBinarioEquilibrado.


2. C onstruir el rbol equilibrado de n nodos, enviando al objeto arbolbe el men
saje construirArbolEquilibrado.
3. Buscar un determ inado nodo enviando al objeto arbolbe el mensaje buscar.
4. Finalm ente, 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 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 );

CLASES RELACIONADAS DE LA BIBLIOTECA JAVA


Jav a soporta diferentes grupos de objetos, entre los que cabe destacar de forma
genrica los siguientes:

C ollection. U na coleccin no tiene un orden especial y perm ite claves dupli


cadas.
List. U na lista est ordenada y perm ite claves duplicadas. En unos casos los
elem entos se colocan en el orden en el que son aadidos y en otros, los mis
m os elem entos asum en un orden natural.
Set. U n conjunto no tiene un orden especial pero no perm ite claves duplica
das.
M ap. Un m apa utiliza un conjunto de claves no duplicadas (un ndice) para
acceder a los datos alm acenados.

Pues bien, adem s de la clase L in k e d L is t para trabajar con listas enlazadas,


la biblioteca de Java proporciona en su paquete ja v a .u til las clases TreeSet.
T r e e M a p , H a sh S e t, H a s h M a p y H a sh T a b le .

La clase T re e Se t proporciona un conjunto ordenado, utilizando para el alma


cenam iento de los datos un rbol. Los elem entos deben ten er un orden asociado
(saber qu elem ento sigue a cul) im plem entando la interfaz C o m p a r a b le o pro
porcionando u na clase C o m p a r a t o r para efectuar las com paraciones.
C A PTU LO 13: ESTR U C TU R A S DINM ICA S 5 6 7

L a clase T re e M a p proporciona un m apa ordenado, utilizando para el alm ace


nam iento de los datos un rbol. Igual que la clase T re eS et, los elem entos deben
tener un orden asociado.

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

La clase C ListaLinealSE O debe incluir los atributos:

private CElemento p = nuil: // ele m en t o de c a b e c e ra


private CElemento elem Anterior - n u il ; // elemento a n t e r i o r
private CElemento ele mActual - n u i l : // elemento actual

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:

public a b stra c t in t comparartObject o b j l. O bject o b j 2):


public boolean l i s t a V a c i a O
public Object bu scartO bject obj)
public void a a d irtO b je ct obj)
public Object b o rra r O b je c t obj)
public Object o b te n e rP rim e ro ()
public Object o b t e n e r S ig u ie n t e ( )

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 buscar localiza un elem ento determ inado en la lista. T iene un pa


rm etro para alm acenar una referencia de tipo O b je c t a los datos que permitirn
localizar el elem ento en la lista, y devuelve una referencia al rea de datos del
elem ento, o bien nu il si la lista est vaca o no existe un elem ento con esos datos.

El m todo a a d ir inserta un elem ento en la lista en orden ascendente de una


clave seleccionada del rea de datos. T iene un parm etro q u e es una referencia de
tipo O b je c t al objeto a aadir. N o devuelve nada.

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.

El m todo obtenerSiguiente devuelve una referencia al rea de datos del ele


m ento siguiente al actual, o bien n u il si la lista est vaca.

S egn el enunciado, la clase C ListaLinealSE O puede ser com o se m uestra a


continuacin:

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

// E l e m e n t o de una l i s t a lineal simplemente enlazada


C A PTU LO 13: ESTR U C TU R A S D IN M ICA S 5 6 9

prvate class 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 C E l e m e n t o s i g u i e n t e : // s i g u i e n t e e l e m e n t o
II M t o d o s
p r i v a t e C E l e m e n t o ! ) 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 f O b j e c t d . C E l e m e n t o 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;

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):

public boolean U staV aciaO


I
r e t u r n p = = n u l 1;

p u b lic Object b u scar(O b ject obj)


I
// B u s c a r un e l e m e n t o d e t e r m i n a d o en una l i s t a o r d e n a d a .
II El m t o d o a l m a c e n a en e l e m A c t u a l l a r e f e r e n c i a del
// e l e m e n t o b u s c a d o y en e l e m A n t e r i o r l a r e f e r e n c i a d e l
// e l e m e n t o a n t e r i o r .
e le m A n t e r i o r = ele m Actual - n u i l :

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

public void a a d ir(O b je c t obj)


I
// A a d i r un e l e m e n t o en o r d e n a s c e n d e n t e s e g n una c l a v e
II p r o p o r c i o n a d a p o r o b j .
C E l e m e n t o q = new C E l e m e n t o o b j , n u i l ) ; // c r e a r e l e l e m e n t o

// S i l a l i s t a r e f e r e n c i a d a por p e st vacia, aadirlo s i n ms


if ( listaV aciaO )
I
II A a d i r e l prim er elemento
P - q:
e le m A nte rio r = elemActual = p; // a c t u a l i z a r referencias
return;

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

public Object b o rra r(O b je c t obj)


I
// B o r r a r un d e t e r m i n a d o e l e m e n t o .
// S i l a l i s t a e s t v a c i a , r e t o r n a r ,
i f ( li s t a V a c i a O ) return n u il;

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

Object borrado = elem Actual.datos:


e l e m A c t u a l = e l e m A c t u a l . s i g u i e n t e : // a c t u a l i z a r r e f e r e n c i a
r e t u r n b o r r a d o : // r e t o r n a r el e l e m e n t o b o r r a d 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 b o r r a d o s e r e n v i a d o a l a
// b a s u r a a l q u e d a r d e s r e f e r e n c i a d o , p o r t r a t a r s e de una
// v a r i a b l e l o c a l .

p u b lic Object o b te n e r P rim e ro )


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 p rim e r elemento.
// 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 ( lis t a V a c ia ) ) return n u il:
e l e m A c t u a l = e l e m A n t e r i o r - p:
return p.datos:

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:

//////////////////////////////////////////////////////////////////

En la lista que crearem os a partir de la clase anterior vam os a alm acenar ob


jeto s de la clase:

public class CDatos


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 riv a t e double n o t a :
// M t o d o s
public CD atosO II // 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 D a t o s t S t r i n g 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;
572 JA V A : C U R SO D E PROGRAM A CIN

public void a s i g n a r N o m b r e ( S t r i n g nom)

nombre = nom;

public String obtenerNombre( )

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;

Pero, para utilizar la clase abstracta C ListaLinealSE O tenem os que derivar de


ella otra clase, p o r ejem plo C ListaLinealSE O rdenada, que redefina el m todo
com parar para que perm ita com parar dos objetos C D atos p o r el atributo n om bre:

public class CListaLinealSEO rdenada extends C ListaLin e alSE O


1
// P e r m i t e c o m p a r a r d o s e l e m e n t o s d e l a l i s t a por
// e l a t r i b u t o no mbre.
p u b lic in t comparartObject o b j l. Object obj2)
I
String s t r i = 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 ( ) ) ;
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 s t r i . c o m p a r e T o s t r 2 );

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 ;

public static void m a in (S trin g [] args)


I
// C r e a r un a lista lineal vacia

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

D e form a resum ida, el program a realizar las siguientes operaciones:

a) L eer un dato, operando u operador, y lo alm acenar en la variable oper.


b) A nalizar o p er; si se trata de un operando lo m ete en la pila y si se trata de un
operador saca los dos ltim os operandos de la pila, realiza la operacin indi
cada por dicho operador y m ete el resultado en la pila para poder utilizarlo
com o operando en una posible siguiente operacin.

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.

El program a com pleto se m uestra a continuacin:

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

public static void obtenerOperandosi)


I
i f ( p i l a . t a m a o ( ) < 2 ) t h r o w new N u l l P o i n t e r E x c e p t i o n C );
o p e r a n d o [ l ] = ( ( D o u b le ) p i 1a . s a c a r D e P i 1a ( ) ) . d o u b l e V a l u e ( );
o p e r a n d o [ 0 ] = ( ( D o u b l e ) p i 1 a . s a c a r D e P i 1 a ( ) ) . d o u b l e V a l u e ( );
1

public static void m a in (S trin g [] args)


I
// o p e r a l m a c e n a l a entrada realizada desde el teclado
S t r i n g oper = n u il :

System .out.p rin tln ("O p e r a c io n e s : + - * / \ n ):


CA PTU LO 13: ESTRU C TU R A S DINM ICA S 5 7 5

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:

java Palabras fichero_de_texto

donde fich ero _ d e_ texto es el nom bre del fichero de texto del cual deseam os obte
ner la estadstica.

El proceso de contabilizar las palabras que aparezcan en el texto de un deter


m inado fichero, lo podem os realizar de la form a siguiente:

a) Se lee la inform acin del fichero y se descom pone en palabras, entendiendo


por palabra una secuencia de caracteres delim itada p o r espacios en blanco, fa
buladores, signos de puntuacin, etc.

b) C ada palabra deber insertarse p o r orden alfabtico ascendente ju n to con un


contador que indique su nm ero de apariciones, en el nodo de una estructura
en rbol. E sto facilitar la bsqueda.

c) U na vez construido el rbol de bsqueda, se presentar p o r pantalla una esta


d stica con el siguiente form ato:

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

Total palabras diferentes: 35

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:

public class CDatos


I
// A t r i b u t o s
p riv a t e S t r in g palabra:
p riv a t e in t contador:

// 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 CDatostString pal) // c o n s t r u c t o r c o n un p a r m e t r o


I
palabra p a l :
c o n t a d o r = 0:
1

public CDatostString pal. int cont) // c o n s t r u c t o r c o n d o s p a ra m s


I
palabra = p a l :
contador = cont:
I

public void a s ig n a r P a la b r a S t r in g pal)


I
palabra = p a l :
I

public String obtenerPalabra()


I
return palabra;
1

public void a sig n a rC o n ta d o r(in t cont)


I
contador = cont:
I

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

El rbol de bsqueda que tenem os que construir ser un objeto de la clase


C ArbolBinarioD eBusqueda derivada de C ArbolBinB. R ecuerde que la clase CAr
bolB inB fue im plem entada anteriorm ente en este m ism o captulo, al hablar de r
boles binarios d e bsqueda. La razn de por qu derivam os un clase de
C ArbolBinB es porque esta clase es abstracta, con la intencin de redefinir los
m todos que procesan inform acin contenida en el rea de datos referenciada por
cada nodo, que en nuestro caso se corresponde con objetos CDatos.

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

/////////////////////////////////////////////////////////////////

Se puede observar que el m todo p ro cesa r de la clase C ArbolBinarioD eBus


queda, adem s de visualizar la inform acin alm acenada en el objeto C D atos refe-
CA PTU LO 13: ESTR U C TU R A S DINM ICA S 5 7 9

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.

S lo queda construir una aplicacin que cree un objeto de la clase C ArbolBi-


narioD eB usqueda a partir de las palabras alm acenadas en un fichero y presente
los resultados pedidos. El cdigo de esta aplicacin se va a apoyar en tres m to
dos: m a in , leerFichero y palabras.

El m todo m a in verifica que, cuando se ejecute la aplicacin, se haya pasado


com o parm etro el nom bre del fichero de texto, invoca al m todo leerFichero y
una vez construido el rbol, lo recorre para visualizar los resultados pedidos.

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

El cdigo com pleto de la aplicacin que hem os denom inado P alabras, se


m uestra a continuacin:

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

public static void palabras(String linea)


I
// D e s c o m p o n e r l i n e a en p a l a b r a s
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 ( 1 1 n e a , , ; . : \ n \ r \ t \ f " ) ;

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

while ( ca d e n a .ha sM o reT o kenst))


I
p a l a b r a - c a d e n a . n e x t T o k e n ( );
i f ((o b j = (C D ato s)a rb o lb b .b usca r(n ew CDatos(pal a b r a ) ) ) nuil)
r b o l b b . i n s e r t a r t n e w C D a t o s ( pal a b r a . 1 ) ) ;
el se
o b j . a s i g n a r C o n t a d o r ( o b j . o b t e n e r C o n t a d o r ( ) + l );

public static void 1e e r F i c h e r o t S t r i n g nombrefich)


I
// D e f i n i c i o n e s de v a r i a b l e s
F i l e f i c h F u e n t e = new F i l e ( n o m b r e f i c h ) ;
BufferedReader flu jo E = n u il;

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;

while ((linea = f 1uj oE . r e a d L i n e ( )) != n u i l )


[
// S i s e a l c a n z e l f i n a l del fichero.
// r e a d L i n e d e v u e l v e n u i l
p a l a b r a s ( 1 i n e a );

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

public static void m a in (S trin g [] args)


I
// mairi d e b e r e c i b i r un p a r m e t r o : el no mb r e d e l fichero
// j a v a P a l a b r a s p a l a b r a s . t x t

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 ] ):

rb olb b.visitarlnorde n):


S y s t e m . e r r . p r i n t l n );
S y s t e m . e r r . p r i n t n ( " T o t a l p a l a b r a s : " + r b o l b b . t o t a l P a l a b r a s );
S y ste m .e rr .p r in tln "T o ta l palabras d ife re n te s: " +
r b o l b b . t o t a 1Pal a b r a s O i f e r e n t e s ) :

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:

2 x \ ' - xyJ + 8.25 m s 5xsy - 2x[y + 7x2 - J igual a 5 r y + 7x2 - x y s + 5.25

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.

La clase C Term ino ya fue desarrollada en el apartado ejercicios resueltos


del captulo 10. Tam bin se im plem ento una clase CPoiinom io. E sta clase debe
ser ahora reem plazada por una lista lineal sim plem ente enlazada ordenada.
582 JA V A: C U R SO D E PROGRAM A CIN

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 uando se m uestre la inform acin alm acenada en el rbol, el listado de los


nom bres y sus correspondientes notas debe aparecer en orden ascendente. Por de
finicin de rbol de bsqueda, para todo nodo, las claves m enores que la del pro
pio nodo form an el subrbol izquierdo y las m ayores, el subrbol derecho. Segn
esto, la clave m enor se encuentra en el nodo m s a la izquierda y la clave m ayor
en el nodo m s a la derecha del rbol. P or lo tanto, para visualizar los nom bres en
orden ascendente tendrem os que recorrer el rbol en inorden. Entonces, si pensa
m os en el proceso inverso, esto es, si partim os de un fichero con las claves orde
nadas y construim os un rbol perfectam ente equilibrado tenem os que utilizar la
form a inorden para conseguir al m ism o tiem po que el rbol sea de bsqueda. Es
decir, el m todo que cree el rbol debe incluir los siguientes procesos en el orden
m ostrado:

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:

java Ordenar fic h e r o _ d e _ t e x t o [-r]

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.

L a recursin es un proceso extrem adam ente potente, pero consum e m uchos


recursos, razn por la que la analizarem os detenidam ente, para saber cundo y
cm o aplicarla. D e este anlisis deducirem os que aunque un problem a por defini
cin sea recursivo, no siem pre ser el m todo de solucin m s adecuado.

En las aplicaciones prcticas, antes de poner en m archa un proceso recursivo


es necesario dem ostrar que el nivel m xim o de recursin, esto es. el nm ero de
veces que se va a llam ar a s m ism o, es no slo finito, sino realm ente pequeo. La
razn es que se necesita cierta cantidad de m em oria para alm acenar el estado del
proceso cada vez que se abandona tem poralm ente, debido a una llam ada para eje
cutar otro proceso que es l m ism o. El estado del proceso de clculo en curso hay
586 J A V A : C U R S O D E P R O G R A M A C I N

que alm acenarlo para recuperarlo cuando se acabe la nueva ejecucin del proceso
y haya que reanudar la antigua.

En trm inos de un lenguaje de program acin, un m todo es recursivo cuando


se llam a a s mismo.

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)

El seudocdigo que especifica cm o solucionar este problem a aplicando la


recursin, es el siguiente:

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

A continuacin presentam os este m todo com o parte de una clase C Recur-


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

Para probar cm o funciona este algoritm o podem os escribir la aplicacin si


guiente:
C A PTU LO 14: A LG O RITM O S 5 8 7

public class Test


I
public static void m a in (S trin g [] args)
I
i n t m. n . a ;
S y s t e m . o u t . p r i n t l n ( " C l c u l o de A ( m , n ) = A ( m - l , A ( m , n - l ) ) \ n ):
S y s t e m . o u t . p r i n t C ' V a l o r d e m: " ) ; m = L e e r . d a t o n t C );
S y s t e m . o u t . p r i n t ( " V a l o r d e n: " ) : n = L e e r . d a t o I n t ( ):
a = CRecursion.Ackerm an(m .n);
System .out.p rintln("\nA(" + m + + n + ) = " + a);

Supongam os ahora que nos planteam os el problem a de resolver el m todo de


A ckerm an, pero sin aplicar la recursin. Esto nos exigir salvar las variables ne
cesarias del proceso en curso, cada vez que el m todo se llam e a s m ism o, con el
fin de poder reanudarlo cuando finalice el nuevo proceso invocado.

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.

El seudocdigo para este m todo puede ser el siguiente:

< 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

A continuacin presentam os el cdigo correspondiente a este m todo que


hem os denom inado A ckernum N R . D icho m todo se ha incluido en la interfaz de
la clase CRecursion anterior y utiliza la clase CPila, im plem entada en el captulo
de Estructuras dinm icas , para crear una pila que alm acene los valores m y n
cada vez que es invocado para una nueva ejecucin.

public static i n t A c k e r m a n N R t i n t m. int n)


I
C P i l a p i l a = new C P i l a O ; // p i l a de e l e m e n t o s (m.n)
CDatos dato:
i n t Ac k e r ma n _ m_ n = 0:
p ila . m e te rE n P ila tn e w CDatosm, n ) ) :
w hile (true)
1
// Tomar l o s d a t o s de l a c i m a d e 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 ( ):
m = d a t o . o b t e n e r M ( ):
n - d a t o . o b t e n e r N );
i f (m 0 ) // A c k e r m a n ( O . n ) = n+1
(
Ac k e r ma n _ m_ n = n + 1 ;
i f ( p i l a . t a m a o t ) ! - 0)
1
// S a c a r m y n d e l a p i l a
d a t o - ( C D a t o s ) p i 1 a . s a c a r D e P i 1a ( ) :
m = d a t o . o b t e n e r M ( );
n = d a t o . o b t e n e r N );
// M e t e r m y Ac k e r ma n _ m_ n en l a p i l a
p i l a . m e t e r E n P i l a n e w C D a t o s t m . A c k e r m a n _ m _ n ) ):
I
el se
r e t u r n Ackerman_m_n:
I
e l s e i f (n ~ 0 ) // A c k e r m a n m - 1 , 1 )
// M e t e r m-1 y 1 en l a p i l a
pila.m eterEnPila(new CDatosdn-l. 1)):
e l s e // A c k e r m a n m - 1 , A c k e r m a n ( m , n - 1 ) )
I
II M e t e r m-1 y Ac k e r ma n _ m_ n en l a p i l a
p i 1a . m e t e r E n P i 1 a ( n e w C D a t o s ( m - l . A c k e r m a n _ m _ n ) ) :
// M e t e r m y n -1 en l a p i l a
p i l a . m e t e r E n P i l a ( n e w CDatostm, n - 1 ) ) :

Segn se puede observar, los valores de m y n son encapsulados p o r objetos


de la clase C D atos definida as:
CA PTU LO 14: A LG O RITM O S 5 8 9

public class CDatos


I
// A t r i b u t o s
p r i v a t e i n t m. 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

public int obtenerM()


I
r e t u r n m;
I

public int obtenerN()


I
r e t u r n n;

Un proceso en el que es realm ente eficaz aplicar la recursin es el problem a


de las torres d e H anoi. Este problem a consiste en tres barras verticales A , B y C y
n discos, de diferentes tam aos, apilados inicialm ente sobre la barra -4, en orden
de tam ao decreciente.

A B C

l 1
I ]

El objetivo es m over los discos desde la barra A a la C, conservando su orden,


bajo las siguientes reglas:

1. Se m over un slo disco cada vez.


2. Un disco no puede situarse sobre otro m s pequeo.
3. Se utilizar la barra B com o pila auxiliar.

U na posible solucin, es el algoritm o recursivo que se m uestra a continua


cin:

1. M over n-1 discos de la barra A a la B (el disco n es el del fondo).


590 JA V A : C U R SO D E PROGRAM A CIN

2. M over el disco n de la barra A a la C, y


3. M over los n-1 discos de la barra B a la C.

R esum iendo estas condiciones en un cuadro obtenem os:

n discos origen otra torre destino


inicialmente n A B C
1 n-1 A C B
2 1 A B C
3 n-1 B A C

El m todo a realizar ser m over n discos de origen a destino :

m over(n_diseos, origen, otratorre, destino):

El seudocdigo para este program a puede ser el siguiente:

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

A continuacin presentam os el m todo correspondiente a este problem a. El


resultado ser los m ovim ientos realizados y el nm ero total de m ovim ientos.

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:

public static in t mover(int n_discos, c h a r a. c h a r b, c h a r c)


I
if (n_discos > 0)
1
m o v e r ( n _ d i s c o s - 1. a . c . b ) :
System .out.println("m over d isco de " + a + " a " + c ) ;
movimientos++;
m o v e r ( n _ d i s e o s - 1 , b. a . c ) ;
)
return movimientos:

Para probar cm o funciona este m todo escribim os la aplicacin siguiente:


CA PTU LO 14: ALGORITM OS 5 9 1

public class Test


I
public static void m a in ( S t r in g [ ] args)
I
in t n _ d isc o s. movimientos;
S y s t e m . o u t . p r i n t ( " N m e r o de d i s c o s : " ) ;
n _ d i s c o s = L e e r . d a t o l n t );
m o v i m i e n t o s = C H a n o i . m o v e r ( n _ d i s e o s , A . ' B ' . C ):
S y ste m .o u t.p rin tln ("\n m o v im ie n to s efectuados: " + movimientos);

Si ejecuta la aplicacin anterior para n_discos = 3, el resultado ser el si


guiente:

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

movimientos efe ctuados: 7

C om o ejercicio se propone realizar el m todo m o ver sin u tilizar recursin.

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

Podem os agrupar los m todos de ordenacin en dos categoras: ordenacin de


m atrices u ordenacin interna (cuando los datos se guardan en m em oria interna) y
ordenacin de ficheros u ordenacin externa (cuando los datos se guardan en me
m oria externa: generalm ente en discos).

En este apartado no se trata de analizar exhaustivam ente todos los m todos de


ordenacin y ver sus prestaciones de eficiencia, rapidez, etc. sino que sim ple
m ente analizam os desde el punto de vista prctico los m todos m s com unes para
ordenacin de m atrices y de ficheros.

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.

V eam os a continuacin el algoritm o correspondiente a este m todo para or


den ar una lista de m enor a m ayor, partiendo de que los datos a ordenar estn al
m acenados en una m atriz de n elem entos:

1. C om param os el prim er elem ento con el segundo, el segundo con el tercero, el


tercero con el cuarto, etc. C uando el resultado de una com paracin sea
m ayor que , se intercam bian los valores de los elem entos com parados. Con
esto conseguim os llevar el v alor m ayor a la posicin n.

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.

4. La ordenacin estar realizada cuando al repetir el isim o proceso de com pa


racin no haya habido ningn intercam bio o, en el peor de los casos, despus
de rep etir el proceso de com paracin descrito n-1 veces.

El seudocdigo para este algoritm o puede ser el siguiente:

< m t o d o o r d e n d r ( m d t r i z "a" d e "n" e l e m e n t o s )>


[ " a " es un m a t r i z c u y o s e l e m e n t o s son a 0. a, .... a.]
n - n-1
D O U H I L E ("a" no e s t o r d e n a d o y n > 0 )
i - 1
D O h/HILE ( i < = n )
IF ( a[i -1] > a [ i ] ) THEN
p e r m u t a r a [ i - l ] con a l i]
CA PTU LO 14: A LG O RITM O S 5 9 3

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:

while ( s && ( - - n m e r o _ d e _ e l e m e n t o s >0))


I
s = f a l s e : // no p e r m u t a c i n
f o r ( i = 1; i < = n m e r o _ d e _ e l e m e n t o s : i + + )
// e l e l e m e n t o ( i - 1 ) e s m a y o r que el ( i ) ?
i f ( m [ i - 1 ] > m[ i ] )
I
// p e r m u t a r l o s elementos ( i -1) e (i)
a u x = m[ i - 1 ] ;
m[i -1] = m[ i ];
m[ i ] = a u x ;
s = t r u e : // p e r m u t a c i n
)

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:

while ( s && ( - - n m e r o _ d e _ e l e m e n t o s > 0))


I
s = f a l s e : // n o p e r m u t a c i n
f o r (i = 1 : i <= nm ero_de_elementos: i+ +)
// e l e l e m e n t o ( i - 1 ) e s m a y o r q u e e l ( i ) ?
594 JA V A : C U R SO D E PROGRAM A CIN

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.

C uando se analiza un m todo d e ordenacin, hay que determ inar cuntas


com paraciones e intercam bios se realizan para el caso m s favorable, para el caso
m edio y para el caso m s desfavorable.

En el m todo de la burbuja se realizan (n -l)(n /2 )= (n 2-n)/2 com paraciones en


el caso m s desfavorable, donde n es el nm ero de elem entos a ordenar. P ara el
caso m s favorable (la lista est ordenada) el nm ero de intercam bios es 0. Para el
caso m edio es 3 (n 2-n)/4; hay tres intercam bios por cada elem ento desordenado. Y
para el caso m enos favorable, el nm ero de intercam bios es 3(n -n)/2. El anlisis
m atem tico que conduce a estos valores, queda fuera del propsito de este libro.
El tiem po de ejecucin es un m ltiplo de n2 y est directam ente relacionado con el
nm ero de com paraciones y de intercam bios.

La siguiente aplicacin ordena una m atriz d o u b le y otra de tipo S trin g utili


zando el m todo ordenar de la clase CM atriz.

public class Test


I
public static void m a in ( S t r in g [] args)
I
// M a t r i z n u m r i c a
double[] m - 13.2.1.5.41;
CMatriz.ordenar(m);
f o r ( i n t i = 0: i < m . l e n g t h ; i + + )
System.out.p r i n t (m [ i ] + " ");
S y s t e m . o u t . p r i n t l n ( ):

// 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:

El seudocdigo para este algoritm o puede ser el siguiente:

< m t o d o i n s e r c i n t m a t r i z "a" d e "r" e l e m e n t o s ) >


[ a " es un m a t r i z c u y o s e l e m e n t o s s o n a0 . a a n.]
i - 1
DO UH1LE ( i < n )
x a [i]
i n s e rt ar x e n la p o s i c i n c o r r e c t a e n t r e a 0 y a t
E N DDO
END <insercin>

La program acin de este algoritm o, para el caso concreto de ordenar num ri


cam ente una lista de valores, es la siguiente:

public static void insercion(double[] m)


I
i n t i . k, n_elementos = m .length:
d o u b l e x:
596 JA V A : C U R S O D E P R O G R A M A C I N

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

A nlisis del m todo de insercin directa:

com paraciones intercam bios


caso m s fa vo ra b le n-1 2 (n -l)
caso m edio (n 2 +n-2)/4 (n 2 + 9 n -10)/4
caso m enos favorable (n2 + n )/2 -1 (n 2 +3n-4)/2

Para el m todo de insercin, el tiem po de ejecucin es funcin de n2 y est


directam ente relacionado con el nm ero de com paraciones y de intercam bios.

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:

1. Se selecciona un valor perteneciente al rango de valores de la m atriz. Este


valor se puede escoger aleatoriam ente o haciendo la m edia de un pequeo
conjunto de valores tom ados de la m atriz. El valor ptim o sera la m ediana (el
valor que es m enor o igual que los valores correspondientes a la m itad de los
elem entos de la m atriz y m ayor o igual que los valores correspondientes a la
otra m itad). N o obstante, incluso en el peor de los casos (el valor escogido
est en un extrem o), quicksort funciona correctam ente.

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

El proceso descrito es esencialm ente recursivo. Segn lo expuesto, el seudo-


cdigo para este algoritm o puede ser el siguiente;

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

A continuacin se m uestra una versin de este algoritm o, que selecciona el


elem ento m edio de la m atriz para proceder a dividirla en dos partes. Esto resulta
fcil de im plem entar, aunque no siem pre da lugar a una buena eleccin. A pesar
de ello, funciona correctam ente.

public static void q u ic k s o r t ( S t r in g [ ] m)


I
qs(m. 0. m . l e n g t h - 1);
1

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

while ( m[ i z q ] . c o m p r e l o ( m i t a d ) < 0 && i z q < s u p ) izq++:


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

no seran necesarias. En cam bio, si el valor m itad es un valor no coincidente con


un elem ento de la lista, pero que est dentro del rango de valores al que pertene
cen los elem entos de la m ism a, esas condiciones son necesarias para evitar q ue se
puedan sobrepasar los lm ites de los ndices de la m atriz.

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:

w hile ( m[ i z q ] < m i t a d && izq < sup) izq++;


w hile ( m i t a d < m [ d e r ] && der > i n f ) d e r - - ;

En el m todo quicksort, en el caso m s favorable, esto es, cada vez se selec


ciona la m ediana obtenindose dos particiones iguales, se realizan n.log n com pa
raciones y n/.log n intercam bios, donde n es el nm ero de elem entos a ordenar;
en el caso m edio, el rendim iento es inferior al caso ptim o en un factor de 2.log 2;
y en el caso m enos favorable, esto es, cada vez se selecciona el valor m ayor obte
nindose una particin de n-1 elem entos y otra de un elem ento, el rendim iento es
del orden de n.n= n2. C on el fin de m ejorar el caso m enos favorable, se sugiere
elegir, cada vez, un valor aleatoriam ente o un valor que sea la m ediana de un pe
queo conjunto de valores tom ados de la m atriz.

El m todo qs sin utilizar la recursin puede desarrollarse de la form a si


guiente:

public static void q u ic k s o rt N R fS t rin g [] m)


I
qs NR ( m, 0. m.length - 1);
I

// 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:

public class CDatos


1
// A t r i b u t o s
p r i v a t e i n t i n f , sup;
// M t o d o s
public CDatostint i. int s) // c o n s t r u c t o r con p a r m e t r o s
(
inf - i ;
sup - s ;
600 JA V A : C U R S O D E P R O G R A M A C I N

public int obtenerlnfO


I
return inf;
1

public int obtenerSupO


I
return sup;

Comparacin de los mtodos expuestos


Si m edim os los tiem pos consum idos p o r los m todos de ordenacin estudiados
anteriorm ente, observarem os que el m todo de la burbuja es el peor de los m to
dos; el m todo de insercin directa m ejora considerablem ente y el m todo qui-
cksort es el m s rpido y m ejor m todo de ordenacin de m atrices con diferencia.

BSQUEDA DE DATOS

El objetivo de ordenar un conjunto de objetos es, generalm ente, facilitar la bs


queda de uno o m s elem entos pertenecientes a un conjunto, aunque es posible
realizar dicha bsqueda sin que el conjunto d e objetos est ordenado, pero esto
trae com o consecuencia un m ayor tiem po de proceso.

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.

El seudocdigo para este m todo de bsqueda puede ser el siguiente:

< m t o d o b s q u e d a _ S ( m a t r i z a. val or q u e q u e r e m o s b u s c a r ) >


i - 0
DO U H I LE ( no encont ra d o )
IF ( va lo r = a [ i ] )
encontrado
ENDIF
i = 1+1
FNDDO
END <bsqueda_S>
C A PTU LO 14: A LG O RITM O S 6 0 1

C om o ejercicio, escribir el cdigo correspondiente a un m todo que perm ita


buscar un valor previam ente ledo, en un matriz.

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.

El seudocdigo para este algoritm o puede ser el siguiente:

< m t o d o b s q u e d a B i n l m a t r i z a. valo r q u e q u e r e m o s b u s c a r )>


D O U H I L E ( e x i s t a un i n t e r v a l o d o n d e b u s c a r )
x e l e m e n t o m i t a d del i n t e r v a l o d e b s q u e d a
IF ( v a l o r > x ) THEN
b u s c a r "valor" en la s e g u n d a m i t a d del i n t e r v a l o de b s q u e d a
E LSE
b u s c a r " v al or " e n la p r i m e r a m i t a d del i n t e r v a l o de b s q u e d a
ENDIF
ENDDO
IF ( se e n c o n t r v a l o r ) THEN
r e t o r n a r su ndice
ELSE
r e t o r n a r -1
ENDIF
END <bsquedaBin>

A continuacin se m uestra el cdigo correspondiente a este m todo.

public static int bsquedaBin(double[] m, d o u b l e v)


I
// El m t od o b s q u e d a B i n d e v u e l v e como r e s u l t a d o l a p o s i c i n
// d e l v a l o r . S i e l v a l o r no s e l o c a l i z a d e v u e l v e - 1 .

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;

En el algoritm o de B oyer y M oore la com paracin se realiza de derecha a iz


quierda, em pezando desde el principio del texto. Es decir, se em pieza com parando
el ltim o carcter de la cadena que se busca con el correspondiente carcter en el
texto donde se busca; si los caracteres no coinciden, la cadena que se busca se
desplaza hacia la derecha un nm ero de caracteres igual al valor indicado p o r la
entrada en la tabla delta correspondiente al carcter del texto que no coincide. Si
CA PTU LO 14: A LG O RITM O S 6 0 3

el carcter no aparece en la cadena que se busca, su valor delta es la longitud de la


cadena que se busca.

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 ,

d e lta [ ' c '] - 3


d e lta [' i ' ] = 2
d e l t a [* e ] = 1
d e lta tn ] - 0

El resto de las entradas valen 4 (longitud de la cadena). Segn esto, la cadena


que se busca se desplaza cuatro posiciones a la derecha (el espacio en blanco no
aparece en la cadena que se busca).

Texto: Ms v a l e un y a que cien despus s e har


C a de n a a buscar: cien

A hora, n no coincide con e\ luego la cadena se desplaza una posicin a la d e


recha {e tiene un valor asociado de uno).

Texto: Ms v a l e un y a que cien despus s e har


C a de n a a b u s c a r : cien

n no coincide con espacio', se desplaza la cadena cuatro posiciones a la dere


cha.

Texto: Ms vale un y a que cien despus se har


C a de n a a b u s c a r : cien

n no coincide con y; se desplaza la cadena cuatro posiciones a la derecha.

Texto: Ms v a l e .r y a que c i e n d e s p u s se har


C a de n a a buscar: cien
604 JA VA: C U R SO D E PROGRAM A CIN

n no coincide con ; se desplaza la cadena cuatro posiciones a la derecha.

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

n no coincide con /; se desplaza la cadena dos posiciones a la derecha.

Texto: Ms vale un y a que c i e n d e s p u s s e har


C aden a a buscar: cien

T odos los caracteres de la cadena coinciden con los correspondientes caracte


res en el texto. P ara encontrar la cadena se han necesitado slo 7+3 com paracio
nes (7 hasta que se dio la coincidencia del carcter c\ ms 3 para verificar que
coincidan los 3 caracteres restantes). El algoritm o directo habra realizado 20+3
com paraciones, que en el peor de los casos, seran i * longC adB uscar, donde i es
la posicin m s a la izquierda de la prim era ocurrencia de la cadena a buscar en el
texto (20 en el ejem plo anterior, suponiendo que la prim era posicin es la 1) y
longC adB uscar es la longitud de la cadena a buscar (4 en el ejem plo anterior). En
cam bio, el algoritm o B o y e r y M oore em pleara k * (i + longC adB uscar) com para
ciones, donde k < 1.

El algoritm o B oyer y M oore es m s rpido porque tiene inform acin sobre la


cadena que se busca, en la tabla delta. El carcter que ha causado la no coinciden
cia en el texto indica cm o m over la cadena respecto del texto. Si el carcter no
coincidente en el texto no existe en la cadena, sta puede m overse sin problem as a
la derecha un nm ero de caracteres igual a su longitud, pues es un gasto de tiem po
com parar la cadena con un carcter que ella no contiene. C uando el carcter no
coincidente en el texto est presente en la cadena, el valor delta para ese carcter
alinea la ocurrencia m s a la derecha de ese carcter en la cadena, con el carcter
en el texto.

A continuacin se m uestra el cdigo correspondiente al algoritm o B oyer y


M oore. El m todo buscarC adena es el que realiza el proceso descrito. E ste m to
do devuelve la posicin de la cadena en el texto o -1 si la cadena no se encuentra
(la prim era posicin es la 0).

public s t a t ic int buscarCadena( S t r in g stexto, String scadena)


I
// B u s c a r una " c a d e n a " en un " t e x t o
c h a r [ ] t e x t o = s t e x t o . t o C h a r A r r a y ( ):
c h a r [ ] cadena = s c a d e n a . t o C h a r A r r a y ( );

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

ORDENACIN DE FICHEROS EN DISCO


Para ordenar un fichero, dependiendo del tam ao del m ism o, podrem os proceder
de alguna de las dos form as siguientes. Si el fichero es pequeo, tiene pocos re
gistros, se puede copiar en m em oria en una m atriz y utilizando las tcnicas vistas
anteriorm ente, ordenam os dicha m atriz y a continuacin copiam os la m atriz orde
nada de nuevo en el fichero. Sin em bargo, m uchos ficheros son dem asiado gran
des y no cabran en una m atriz en m em oria, por lo que para ordenarlos
recurrirem os a tcnicas que acten sobre el propio fichero.
606 JA V A : C U R S O D F P R O G R A M A C I N

Ordenacin de ficheros. Acceso secuencial


El siguiente program a desarrolla un algoritm o de ordenacin de un fichero utili
zando el acceso secuencial, denom inado m ezcla natural. La secuencia inicial de
los elem entos viene dada en el fichero c y se utilizan dos ficheros auxiliares de
nom inados a y b. C ada pasada consiste en una fa s e de distribucin que reparte
equitativam ente los tram os ordenados del fichero c sobre los ficheros a y b. y una
fa s e que m ezcla los tram os de los ficheros a y b sobre el fichero c.

Este proceso se ilustra en el ejem plo siguiente. Partim os de un fichero c. Con


el fin de ilustrar el m todo de m ezcla natural, separarem os los tram os ordenados
en los ficheros por un guin ( - ) .

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.

Segn lo expuesto, el algoritm o de ordenacin m ezcla natural podra ser as:

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

La estructura de la aplicacin que perm ita ordenar un fichero utilizando el al


goritm o descrito puede ser de la form a siguiente:

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):

public static int d is t r ib u ir F il e fuente. F i l e destinoA,


File d e st in o B ) throws IOException
I
// D i s t r i b u i r l o s t r a m o s o r d e n a d o s de fu en te e n t r e
II d e s t i n o A y d e s t i n o B

public static int m ezclarFile fuenteA, F i l e fu enteB,


File destino) th rows IO E x c e p tio n
I
// F u s i o n a r o r d e n a d a m e n t e los t r a m o s de d e s t i n o A y d e s t i n o B
/ / e n fuente
608 JA V A: C U R SO DE PROGRAM A CIN

public s t a t ic void m a in (S trin g [] args)


I
f i l e n o m b r e F i c h e r o = new F i 1e ( a r g s [ 0 ] ) :
mezclaNatura1(nom breFichero);

La aplicacin com pleta y com entada se m uestra a continuacin.

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 u x - n u ll: fc.closeO : fa .closeO : fb.closeO ;


return nro_tramos;
I II d i s t r i b u i r

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

S trin g UneaDeFa. UneaDeFb. 11 n e a D e F a _ a n t , 1 1 n e a D e F b _ a n t ;


i n t n r o _ t r a m o s = 1;

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

else if (lineaDeFa = nuil)


I
f e . w r i t e ( 1 i n e a D e F b ) : f e . ne wLi n e ( );
w h i l e ( ( U n e a D e F b = f b. r e a d L i ne( ) ) != n u i l )
(
fc.w rite(lneaDeFb); fc.new LineO:

fc.close(); fa.closeO ; fb.closet):


return nro_tramos:
) // de m e z c l a r

public static void m a in ( S t r in g [ ] args)


I
// m a i n d e b e r e c i b i r un p a r m e t r o : e l f i c h e r o a o r d e n a r ,
i f ( a r g s . 1 e n g t h ! = 1)
S y s t e m . e r r . p r i n t l n t " S i n t a x i s : java CMezclaNatural " +
" < n o m b r e _ f i c h e r o > " ):
el se
1
File n o m b r e F i c h e r o = new F i 1e ( a r g s [ 0 ] >:
try
I
// A s e g u r a r s e de q u e " n o m b r e F i c h e r o " e x i s t e y s e pu ede l e e r
i f ( n o m b r e F i c h e r o . e x i s t s ) || ! n o m b r e 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 " N o e x i s t e e l f i c h e r o +
nom breFichero);
i f ( n o m b r e F ic h e r o . c a n R e a d ( ))
t h r o w new I O E x c e p t i o n ( " E l f i c h e r o " + n o m b r e F i c h e r o +
" no s e p u e d e 1e e r " );
m e z c l a N a t u r a l ( n o m b r e F i c h e r o ) ; // r e a l i z a r l a o r d e n a c i n
// M o s t r a r e l c o n t e n i d o d e l f i c h e r o
char resp:
S y s t e m . o u t . p r i n t ( " D e s e a v e r el c o n t e n i d o del f i c h e r o ? s /n : " ) :
r e s p = L e e r . c a r c t e r ( ) : L e e r . 1 i m p i a r ( ):
i f ( resp == ' s )
1
// A b r i r un f l u j o de e n t r a d a d e s d e n o m b r e F i c h e r o
// 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 n e a a l n e a .
F i 1e 1n p u t S t r e a m f i s = new F i 1 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 ) :
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 ):
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 ) :

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

El flujo B u ffe r e d R e a d e r (B u fF e re d ln p u tS tre a m cuando tratem os con bytes


en lugar de con caracteres; ver el captulo 5) es uno de los m s eficientes. Se deri
va de R e a d e r y aade un b uffer que acta com o una m em oria interm edia desde la
que el program a obtendr los datos. C om o su tam ao, generalm ente, es bastante
m s grande que el tam ao del bloque fsico asociado con el dispositivo desde el
cual se obtiene la inform acin, el nm ero de accesos a este dispositivo por parte
de la aplicacin dism inuir, ya que el b uffer que se llen cuando la aplicacin
realiz una operacin de lectura, no necesitar volverse a llenar m ientras la apli
cacin no procese los datos alm acenados en el m ism o. R esum iendo, la utilizacin
de un b u ffer repercute en una m ejora de la velocidad de ejecucin y adem s, de
sacopla el tam ao de las unidades de inform acin que requiere el program a, del
tam ao de las unidades de inform acin asociadas con el dispositivo.

De la clase B u ffe re d R e a d e r. cabe destacar los m todos: r e a d L in e que per


m ite leer una lnea de texto sin alm acenar el carcter delim itador de la m ism a
(norm alm ente \n, \r, o \r\n), m a r k que perm ite poner una m arca en la posicin
actual del flujo y reset que perm ite reanudar la lectura desde la m arca m s re
ciente.

A nlogam ente B u ffe r e d W r ite r (B u ffe r e d O u tp u tS tr e a m ) tam bin aade un


buffer que no ser volcado al dispositivo asociado con el flujo hasta que no est
lleno, dism inuyendo el nm ero de accesos al dispositivo, lo que repercute en una
m ejora de la velocidad de ejecucin, adem s de desacoplar el tam ao de las uni
dades de inform acin que requiere el program a, del tam ao de las unidades de
inform acin asociadas con el dispositivo.

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

Ordenacin de ficheros. Acceso aleatorio


El acceso aleatorio a un fichero, a diferencia del secuencial, perm ite ordenar la
inform acin contenida en el m ism o sin tener que copiarla sobre otro fichero, para
lo cual aplicarem os un proceso anlogo al aplicado a las m atrices, lo que sim plifi
ca enorm em ente el proceso ordenacin. Esto quiere decir que los m todos ex
puestos para ordenar m atrices, pueden ser aplicados tam bin para ordenar ficheros
utilizando el acceso aleatorio.

C om o ejem plo, vam os a aadir ' la clase C ListaTfnos de la aplicacin reali


zada en el apartado U n ejem plo de acceso aleatorio a un fichero del captulo 12,
un m todo denom inado quicksort para ordenar el fichero lista de telfonos en-
capsulado p o r la m ism a, en el que cada registro estaba form ado p o r los campos:
nom bre, direccin y telfono. L a ordenacin del fichero la realizarem os por el
cam po nom bre, de tipo alfabtico, em pleando el m todo quicksort explicado ante
riorm ente en este m ism o captulo.

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

public C L ista T fn o stF ile fichero) th rows IO E x c e p tio n


I
// . . .

public void cerrar!) th rows IOException I fes.closeO ; I

public int longitud!) I return nregs; } // nmero de r e g i s t r o s

p u b lic boolean p o n e rV a lo rE n ( i n t i, CPersona ob je to )


th rows IO E x c e p tio n
1
// E s c r i b i r o b j e t o en e l r e g i s t r o de l a posicin i
I

p u b lic CPersona valorEn! int i ) throws IOException


I
// O b t e n e r los d a t o s del registro i
C A PTU LO 14: ALGORITM OS 6 1 5

public void aadir(CPersona obj) th rows IOException

// A a d i r un r e g i s t r o al final del fichero

public boolean el i m i n a r d o n g tel) th rows IOException

// E l i m i n a r e l registro e s p e c if i c a d o por tel

public int buscarString str, int pos) throws IOException

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

private void q s i n t inf, int sup) th rows IOException


I
in t izq = in f, d e r = sup:
S t r i n g mitad:

// 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 quicksort realiza la ordenacin de los nregs registros del fichero


vinculado con el flujo fe s . Para ello invoca al m todo recursivo qs.

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.

El m todo cam po es llam ado p o r qs (quicksort) cada vez que es necesario


obtener el cam po nom bre, utilizado para realizar la ordenacin, de un registro.

C om o ejercicio, puede aadir al m en presentado por la aplicacin Test a la


que nos hem os referido anteriorm ente, que creaba una lista de telfonos a partir de
la clase C ListaTfnos, una opcin m s, ordenar, que perm ita o rdenar 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 " ) :
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.

Por lo n g itud d e bsqueda se entiende el nm ero de accesos que es necesario


efectuar sobre una m atriz para encontrar el elem ento deseado.
C A PTU LO 14: ALGORITM OS 6 1 7

Este m todo de bsqueda perm ite, com o operaciones bsicas, adem s de la


bsqueda de un elem ento, insertar un nuevo elem ento y elim inar un elem ento
existente.

Matrices hash

Una m atriz producto de la aplicacin de un algoritm o hash se denom ina matriz


hash y son las m atrices que se utilizan con m ayor frecuencia en los procesos don
de se requiere un acceso rpido a los datos. G rficam ente estas m atrices tienen la
siguiente forma:

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)

C onociendo la posicin, tenem os acceso al contenido. El m iem bro contenido


puede albergar directam ente la inform acin, o bien una referencia a dicha infor
m acin, cuando sta sea m uy extensa. El acceso, tal cual lo hem os definido, reci
be el nom bre de acceso directo.

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:

i = fa (cla ve) = fa ( clave 2)

El m todo hash est basado en esta tcnica; el acceso a la m atriz es directo a


travs del nm ero i y cuando se produce una colisin (dos claves diferentes dan
un m ism o nm ero i) este elem ento se busca en una zona denom inada rea d e d es
bordam iento.

Mtodo hash abierto


ste es uno de los m todos m s utilizados. El algoritm o para acceder a un ele
m ento de la m atriz de longitud L, es el siguiente:

1. Se calcula /' = fa (cla ve).

2. Si la posicin i de la m atriz est libre, se inserta la clave y el contenido. Si no


est libre y la clave es la m ism a, error: clave duplicada . Si no est libre y la
clave es diferente, increm entam os i en una unidad y repetim os el proceso des
crito en este punto 2. C om o ejem plo, vea la tabla siguiente:

Clve Contenido

5040

3721

688 : 4007

3900
c

6375

En la figura, se observa que se quiere insertar la clave 6383. S upongam os que


aplicando la funcin de acceso, obtenem os un v alor 3\ esto es:

i = fa (6 3 8 3 ) = 3

C om o la posicin 3 est ocupada y la clave es diferente, tenem os que incre


m entar i y volver de nuevo al punto 2 del algoritm o.
CA PTU LO 14: A LG O RITM O S 6 1 9

L a longitud m edia de bsqueda en una m atriz hash abierta viene dada p o r la


expresin:

accesos = (2-k)/(2-2k)

siendo k igual al nm ero de elem entos existentes en la m atriz dividido p o r L. Por


ejem plo, si existen 60 elem entos en una m atriz de longitud L = 100 , el nm ero m e
dio de accesos para localizar un elem ento ser:

accesos = (2-60/100)/(2-2*60/100) = 1,75

En el m todo de bsqueda binaria, el nm ero de accesos viene dado p o r el


v alor log 2 N , siendo N el nm ero de elem entos de la m atriz.

Para red u cir al m xim o el nm ero de colisiones y, com o consecuencia, obte


ner una longitud m edia de bsqueda baja, es im portante eleg ir bien la funcin de
acceso. U na fu n ci n de acceso o fu n ci n hash bastante utilizada y q u e proporcio
na una distribucin de las claves uniform e y aleatoria es la fu n ci n m ita d d el c u a
drado q ue dice: dada una clave C, se eleva al cuadrado (C 2) y se cogen n bits del
m edio, siendo 2" <= L '\ Por ejem plo, supongam os:

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

O tra funcin de acceso m uy utilizada es la fu n c i n m dulo (resto de una divi


sin entera):

i = m dulo(clave/L)

C uando se utilice esta funcin es im portante elegir un nm ero prim o p ara L,


con la finalidad de que el nm ero de colisiones sea pequeo. Esta funcin es lle
vada a cabo en Jav a p o r m edio del operador %.

Mtodo hash con desbordamiento

U na alternativa al m todo anterior es la de disponer de otra m atriz separada, para


insertar las claves que producen colisin, denom inada m atriz de desbordam iento,
en la que se alm acenan todas estas claves de form a consecutiva.
620 JA VA: C U R SO DE PROGRAM A CIN

Clave Contenido Clave Contenido

5040 JT 2039 0

2039-+ 3722 6383 1


^ /
2
2 /
6383-*' 4007 3 /

O tra form a alternativa m s norm al es organizar una lista encadenada p o r cada


posicin de la m atriz donde se produzca una colisin.

Clave Contenido R Clave Contenido R

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:

M to d o_____________S ig n ificad o ______________________________________ ______


C H ashAbierto Es el constructor; est sobrecargado d os veces, una sin pa
rm etros, que crea una m atriz de 101 elem entos, y otra con
un parm etro, que especifica el nm ero de elem entos. Ini
cialm ente todas los elem entos alm acenan el valor nuil.
nm eroD eE lem entos M todo que devuelve el nm ero de elem entos de la m atriz.
nm eroP rim o M todo que devuelve un nm ero prim o a partir de un n
m ero pasado com o argum ento. C om o vam os a utilizar la
funcin de acceso m dulo es im portante elegir un nm ero
prim o com o longitud de la m atriz, con la finalidad de que
el nm ero de colisiones sea pequeo.
fa Se trata de un m todo abstracto con la intencin de redefi-
nirlo en una clase derivada y escribir la funcin de acceso
en funcin de los datos m anipulados.
com parar M todo que debe ser redefinido por el usuario en una sub
clase para perm itir com parar las claves de dos objetos de
los referenciados por la m atriz. D ebe de devolver un entero
indicando el resultado de la com paracin (0 para ==).
622 JA V A : C U R S O D E P R O G R A M A C I N

ha shln M todo hash abierto para aadir un elem ento a la m atriz.


N o devuelve nada.
hashO ut M todo hash abierto para buscar un objeto con una clave
determ inada. Si se encuentra, devuelve una referencia de
_____________________ tipo O b je c t al m ism o; en otro caso devuelve nuil.

A continuacin se presenta el cdigo correspondiente a la definicin de la cla


se C H ashA bierto:

//////////////////////////////////////////////////////////////////
// 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 :

public CHashAbierto(int nmeroDeElementos)


I
if ( n m e r o D e E l e m e n t o s < 1)
n m e r o D e E l e m e n t o s = 1 01;
el se
n m e r o D e E l e m e n t o s = n m e r o P r i m o ( n m e r o D e E l e m e n t o s );
m a t r i z h a s h = new C A I u m n o f n m e r o D e E l e m e n t o s ] :

public int nmeroDeElementos() I r e t u r n m a t r i z h a s h . 1e n g t h ; )

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

public Object h ash 0u t(0b je ct x)


I
624 J A V A : C U R S O D E P R O G R A M A C I 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;

Un ejemplo de una matriz hash


C om o ya hem os indicado, para utilizar esta clase tenem os que derivar otra de ella
y redefinir los m todos f a y com parar en funcin de la inform acin encapsulada
por los objetos de datos que deseem os m anipular. P or ejem plo, supongam os que
deseam os c o n stm ir una m atriz hash de objetos d e la clase C A lum no:

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

public CAlumno(String nom. int ma t )

no mb r e = nom;
m a t r i c u l a = mat;

public void asignarN om bretString nom)

no mb r e - nom;

public String obtenerNombre()

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

public int fa(0bject obj)


(
r e t u r n ( i n t ) ( ( C A I u m n o ) o b j ) . o b t e n e r M a t r i c u l a ( ) % n m e r o D e E l e me n t o s ( ):
I
626 JA V A : C U R S O D E P R O G R A M A C I N

public int comparar(Object o b jl, Object obj2)


I
if ( ( ( C A Iu m n o ) o b j 1 ) . o b t e n e r M a t r l c u l a () ==
( (CA Iu m no )o b j 2 ) . o b t e n e r M a t r l c u l a ( ) )
r e t u r n 0;
else
r e t u r n 1;

//////////////////////////////////////////////////////////////////

O bserve que para definir la funcin de acceso m dulo (% ) necesitam os utili


zar un valor num rico. Esto no q uiere decir que la clave tenga que ser num rica,
com o sucede en nuestro ejem plo, sino que puede ser alfanum rica. C uando se tra
baje con claves alfanum ricas o alfabticas, p o r ejem plo nom bre, antes de aplicar
la funcin de acceso es necesario convertir dicha clave en un v alor num rico utili
zando un algoritm o adecuado.

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

C om o alternativa, la biblioteca de Java proporciona en su paquete ja v a .u til


las clases H a sh S et, H a sh M a p y H a sh T a b le que proporcionan conjuntos de datos
que no perm iten duplicados y que utilizan algoritm os hash para el alm acena
m iento de los datos y para su posterior acceso.

EJERCICIOS RESUELTOS
1. C om parar las dos siguientes versiones del m todo bsqueda binaria e indicar cul
de ellas es m s eficaz.

public static int b s q u e d a B i n l ( d o u b l e [ ] m. d o u b l e v )


I
// El m t o d o b s q u e d a B i n d e v u e l v e como r e s u l t a d o l a p o s i c i n
// d e l v a l o r . S i e l v a l o r no s e l o c a l i z a d e v u e l v e - 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
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;

public static int bsquedaBin2(double[] m. d o u b l e v )


(
// El m t od o b s q u e d a B i n d e v u e l v e como r e s u l t a d o l a p o s i c i n
// d e l v a l o r . S i e l v a l o r no s e l o c a l i z a d e v u e l v e - 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;

w h i1e ( i n f < sup );

if ( m [ i n f ] = = v)
return in f;
else
r e t u r n -1;
Ii

En cada iteracin, en am bos casos, se divide en partes iguales el intervalo en


tre los ndices i n f y sup. P or ello, el nm ero necesario de com paraciones es com o
m ucho log 2 n , siendo n el nm ero de elem entos de la m atriz. H asta aqu el com
portam iento de am bas versiones es el m ism o, pero qu pasa con la condicin de
la sentencia w h ile? Se observa que en la prim era versin dicha sentencia realiza
dos com paraciones frente a una que realiza en la segunda versin, lo que se trad u
cir en un m ayor tiem po de ejecucin, resultando, por tanto, ser m s eficiente la
versin segunda.
CA PTU LO 14: ALGORITM OS 6 2 9

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

public static int bsquedaBin2(double[] m, d o u b l e v)


I
// V e r s i n 2

public static void m a in (S trin g [] args)


I
d o u b l e a = new d o u b l e [ 1 0 0 0 0 0 ] :
long t i . n = a .length:
int i :
for (i = 0 ; i < n ; i++)
a[ i ] = i+ 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 .

El program a com pleto se m uestra a continuacin:

import j a v a .uti 1 .*;


//////////////////////////////////////////////////////////////////
II C a l c u l a r l o s c e n t r o s n u m r i c o s e n t r e 1 y n.
//
public c la ss Test
I
// M t o d o de b s q u e d a b i n a r i a
//
// en: c e n t r o n u m rico
// ( 1 a c n - 1 ) en ( c n + 1 a m i t a d )
II s u m a _ g r u p o l = suma d e l o s v a l o r e s desde 1 a cn-1
// s u m a _ g r u p o 2 = suma de l o s v a l o r e s d es de cn+1 a mit ad
//
// El m t o d o d e v u e l v e como r e s u l t a d o e l v a l o r m i t a d .
// S i en no e s un c e n t r o n u m r i c o d e v u e l v e un v a l o r 0.
//
public static long b sq u e d a B in d o n g en, l o n g n)
I
if (en < = 0 || n < = 0 ) return 0;

long suma_grupol = ((cn-1) * ((cn-1) + 1)) / 2;


lo ng suma_grupo2 = 0:
l o n g m i t a d = 0;

long i n f = cn+1: // l i m i t e i n f e r i o r del g r u p o 2


long sup = n; // l i m i t e s u p e r i o r del g r u p o 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 ) ;

if (suma_grupo2 = = sum a_gru po l)


r e t u r n mitad;
el se
r e t u r n 0;

public static void m a in (S trin g [] args)


I
long n; // c e n t r o s n u m r i c o s e n t r e 1 y n
long en; // p o s i b l e c e n t r o n u m r i c o
long 1 i m _ s u p _ g r u p o 2 ; // l i m i t e s u p e r i o r d e l g r u p o 2

S y s t e m . o u t . p r in t ( " C e n t r o s numricos entre 1 y ");


n - L e e r . d a t o L o n g );
S y s t e m . o u t . p r i n t l n ( );
f o r ( e n = 3 ; en < n ; c n + + )
I
1 im_sup_grupo2 = b s q u e d a B in ( c n . n);
i f ( 1 i m _ s u p _ g r u p o 2 ! - 0)
S y s t e m . o u t . p r i n t n ( c n + " es c e n t r o n u m r i c o de 1 a +
( c n - 1 ) + " y " + (cn+1) + " a " +
1im _sup_grupo2):

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.

2. M odificar la aplicacin lista de telfonos expuesta en el apartado O rdenacin


de ficheros. A cceso aleatorio" de este m ism o captulo, para que el m todo elim i
na r de la clase C ListaT fnos utilice el algoritm o de bsqueda binaria, lo que exigi
r q ue los registros del fichero estn clasificados.
632 JA V A : C U R SO DE PROGRAM A CIN

3. A adir a la clase C ListaTfnos de la aplicacin realizada en el apartado O rdena


cin de ficheros. A cceso aleatorio de este m ism o captulo, un m todo denom ina
do insercin que perm ita o rdenar el fichero lista de telfonos encapsulado por la
m ism a, en orden descendente por el cam po nom bre.

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.

6. E scribir una aplicacin que perm ita:

a) C rear un fichero con la inform acin de elem entos del tipo:

public class CAl u mno


I
// A t r i b u t o s
p rivate in t m atricula:
p r i v a t e S t r i n g nombre:
p r i v a t e do u b le nota:

// M t o d o s
// . . .
I

b) A lm acenar los registros en el fichero utilizando el m todo hash abierto.

c) O btener un registro p o r el nm ero de m atrcula utilizando el m todo hash


abierto.
CAPTULO 15
F.J. CebaHos/RA -MA

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.

El concepto central de cualquier sistem a operativo es el de proceso. C ualquier


ordenador hoy en d a es capaz de hacer varias cosas sim ultneam ente; por ejem
plo, puede estar im prim iendo un docum ento p o r la im presora y ejecutando un
program a del usuario. Esto requiere que la U C P (unidad central de proceso) alter
ne de un program a a otro en m uy cortos espacios de tiem po, lo que conocem os
com o tiem po com partido. De esta form a, todos los program as, incluyendo los que
com ponen el sistem a operativo, que tengan que ejecutarse sim ultneam ente
(m ultiprogram acin) se organizan en varios procesos secuenciales.

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

su propio espacio de direcciones,


su m em oria
sus variables,
ficheros abiertos,
procesos hijo,
contador de program a, registros, pila, seales, sem foros, etc.

Lo anterior, es equivalente a decir que cada proceso tiene su propia U CP vir


tual, lo que nos perm ite com prender m ejor cm o un sistem a puede ejecutar varios
procesos sim ultneam ente, aunque la realidad sea que la U C P alterna entre esos
procesos.

Segn lo expuesto, sera un erro r confundir un program a con un proceso. Para


evitar este posible m alentendido, considere el siguiente ejem plo: cuando instala
m os un ju eg o en nuestro ordenador lo hacem os siguiendo las instrucciones ad
juntas. En este caso, las instrucciones seran el program a, la actividad que hay que
desarrollar para realizar la instalacin (leer las instrucciones, introducir el CD-
ROM , etc.) el proceso y nosotros la UCP. Si m ientras estam os desarrollando esta
actividad, alguien solicita nuestra colaboracin para otra cosa, registram os el
punto en el que nos encontram os y acudim os a resolver lo propuesto. En este ca
so, la U C P alterna de un proceso a otro.

De lo anterior se deduce que un proceso puede estar en ejecucin (est utili


zando la UCP), preparado (est detenido tem poralm ente para que se ejecute otro
proceso) o bloqueado (no se puede ejecutar debido a que ocurri algn evento al
que hay que responder adecuadam ente). Entre estos tres estados son posibles, c o
mo m uestra la figura siguiente, cuatro transiciones:

P re p a ra d o

^ lo q u e a d ^ J

^ E n eje cu c i n

Si un proceso en ejecucin no puede continuar, p asa al estado de bloqueado o


tam bin, si puede continuar y el planificador decide que ya ha sido ejecutado el
tiem po suficiente, pasa al estado de preparado. Si el proceso est bloqueado pasa
r a preparado cuando se d el evento externo por el que se bloque y si est p r e
pa ra d o , pasa a ejecucin cuando el planificador lo decida porque los dem s
procesos ya han tenido su parte de tiem po de UCP.
CA PTU LO 15: H II.O S 6 3 5

En la U C P puede haber varios program as con varios procesos ejecutndose


concurrentem ente. En este caso se utilizan distintos m ecanism os para la sincroni
zacin y com unicacin entre procesos. T ales conceptos son parte del estudio de
sistem as operativos.

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 egn se ha expuesto en el apartado anterior, en un sistem a operativo tradi


cional, cada proceso tiene un espacio de direcciones y un nico hilo de control.
Por ejem plo, considere un program a que incluya la siguiente secuencia de opera
ciones para actualizar el saldo de una cuenta bancaria cuando se efecta un nuevo
ingreso:

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 ):

Este m odelo de program acin, en el que se ejecuta un solo hilo, es en el que


estam os acostum brados a trabajar habitualm ente. Pero, continuando con el ejem
plo anterior, piense en un banco real; en l, varios cajeros pueden actuar sim ult
neam ente. E jecutar el m ism o program a por cada uno de los cajeros tiene un coste
elevado (recuerde los recursos que necesita). En cam bio, si el program a perm itie
ra lanzar un hilo p o r cada peticin de un cajero para actualizar una cuenta, esta
ram os en el caso de m ltiples hilos ejecutndose concurrentem ente (m ulti-
threading). E sta caracterstica ya es una realidad en los sistem as operativos m o
dernos de hoy y com o consecuencia contem plada en los lenguajes de program a
cin actuales.

C om o ya hem os indicado, cada hilo se ejecuta en form a estrictam ente secuen-


cial y tiene su propia pila, el estado de los registros de la U C P y su propio conta
d o r de program a. En cam bio, com parten el m ism o espacio de direcciones, lo que
significa com partir tam bin las m ism as variables globales, el m ism o conjunto de
ficheros abiertos, procesos hijos (no hilos hijo), seales, sem foros, etc.

E ntonces qu ventajas aporta un hilo respecto a un proceso? L os hilos com


parten un espacio de m em oria, el cdigo y los recursos, p o r lo que el lanzam iento
636 J A V A : C U R S O D E P R O G R A M A C I N

y la ejecucin de un hilo es m ucho m s econm ica que el lanzam iento y la ejecu


cin de un proceso. P or otra parte, m uchos problem as pueden ser resueltos m ejor
con m ltiples hilos; y si no, piense cm o escribira un program a con un solo hilo
de control para m ostrar anim acin, sonido, visualizar docum entos y traer ficheros
de Internet, al m ism o tiem po. No obstante, habr situaciones en las que la m ejor
solucin para ayudar en el trabajo sea crear un nuevo proceso (proceso hijo).

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.

R esum iendo, sabem os que en la U C P puede haber varios program as con va


rios procesos ejecutndose concurrentem ente, habilidad que se denom ina m ultita-
rea, y a su vez, un proceso puede crear varios hilos y ejecutarlos de form a
concurrente, lo que se traduce bsicam ente en una m ultitarea dentro de m ultitarea:
el usuario sabe que puede ejecutar varias aplicaciones sim ultneam ente, y el pro
gram ador sabe que cada aplicacin puede ejecutar varios hilos a la vez.

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

En ejecucin. El hilo est activo y le ha sido asignada la U C P (slo los hilos


activos, preparados, pueden ser ejecutados).
B loqueado. El hilo espera que otro elim ine el bloqueo. Un hilo bloqueado
puede estar:
0 D orm ido. El hilo est bloqueado durante una cantidad de tiem po determ i
nada. despus de la cual despertar y pasar al estado preparado.
0 Esperando. El hilo est esperando a que ocurra alguna cosa: un m ensaje
n o tify , una operacin de E/S o adquirir la propiedad de un m todo sin
cronizado. C uando ocurra, pasar al estado preparado.
M uerto. El hilo ha finalizado (est m uerto) pero todava no ha sido recogido
por su padre. Los hilos m uertos no pueden alcanzar ningn otro estado.

O bservar que en la figura no se m uestran los estados nuevo y m uerto ya que


no son estados de transicin durante la vida del hilo; esto es, no se puede transitar
al estado nuevo ni desde el estado m uerto.

La transicin entre estados est controlada p o r un planificador: parte del ker-


nel encargada de que todos los hilos que esperan ejecutarse tenga su porcin de
tiem po de UCP. Si un hilo en ejecucin no puede continuar, pasar al estado blo
queado', o tam bin, si puede continuar y el planificador decide que ya ha sido eje
cutado el tiem po suficiente, pasar al estado preparado. Si el proceso est
bloqueado pasar a preparado cuando se d el evento p o r el que espera; por
ejem plo, puede estar esperando a que otro hilo elim ine el bloqueo, o bien si est
dorm ido, esperar a que pase el tiem po por el que fue enviado a este estado para
ser activado; y si est preparado, pasar a ejecucin cuando el planificador lo de
cida porque los dem s hilos ya han tenido su parte de tiem po de UCP.

Cundo se debe crear un hilo


Segn lo expuesto anteriorm ente, cada vez que se crea un proceso, el sistem a ope
rativo crea un hilo prim ario. Para m uchos procesos ste es el nico hilo necesario.
Sin em bargo, un proceso puede crear otros hilos para ayudarse en su trabajo, utili
zando la U C P al m xim o posible. Por ejem plo, supongam os el diseo de una apli
cacin procesador de texto Sera acertado crear un hilo separado para m anipular
cualquier tarea de im presin? Esto perm itira al usuario continuar utilizando la
aplicacin m ientras se est im prim iendo. En cam bio, qu suceder si los datos
del docum ento cam bian m ientras se im prim e? ste es un problem a que habra que
resolver, quizs creando un fichero tem poral que contenga los datos a im prim ir.

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.

Cmo se crea 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 .

La clase T h re a d . que im plem enta la interfaz R u n n a b le , de form a resum ida,


est definida as:

public c la ss Thread exten ds O b je ct implements Runnable


I
// A t r i b u t o s
s t a t i c i n t MAX_PRIORITY;
// P r i o r i d a d mxi ma q u e un h i l o p u e d e t e n e r .
s t a t i c i n t MI N P R 1 0 R I T Y ;
// P r i o r i d a d m n i m a q u e un h i l o p u e d e t e n e r ,
s t a t i c i n t NORM_PR10 R I T Y ;
// P r i o r i d a d a s i g n a d a p o r o m i s i n a un h i l o .

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

boolean isDaem onO


// V e r i f i c a s i e s t e h i l o e s un d e m o n i o . S e da e s t e no mb r e a
// un h i l o que s e e j e c u t a en s e g u n d o p l a n o , r e a l i z a n d o una
// o p e r a c i n e s p e c f i c a en t i e m p o s p r e d e f i n i d o s , o b i e n en
// r e s p u e s t a a c i e r t o s e v e n t o s ,
boolean i s I n t e r r u p t e d )
// V e r i f i c a s i e s t e h i l o ha s i d o i n t e r r u m p i d o ,
v o i d j o i n ( [ m ? /isegundosl. nanosegundos]])
// E s p e r a i n d e f i n i d a m e n t e o e l t i e m p o e s p e c i f i c a d o , a que e s t e
// h i l o t e r m i n e ( a q u e m u e r a ) .
M ___________________
// C o n t i e n e e l c d i g o q u e s e e j e c u t a r c u a n d o e l h i l o p a s e
// al e s t a d o de e j e c u c i n . P o r o m i s i n n o h a c e n a d a ,
v o i d s e t O a e m o n b o o l e a n on)
II D e f i n e e s t e h i l o como un d e m o n i o o como un h i l o de u s u a r i o ,
v o i d s e t N a m e ( S t r i n g nombre)
II C am b i a e l no mb r e de e s t e h i l o ,
v o i d s e t P r i o r i t y ( i n t nuevaPrioridad)
II C a m b i a l a p r i o r i d a d d e e s t e h i l o . P o r o m i s i n e s n o rm a l
II ( N 0 R M _ P R I 0 R I T Y ) .
s t a t i c v o i d s l e e p d o n g mi 1 i s e g u n d o s [ . i n t n a n o s e g u n d o s ] )
II E n v a e s t e h i l o a d o r m i r p o r e l t i e m p o e s p e c i f i c a d o .

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

U na clase que im plem ente la interfaz K u n n a b le tiene que sobreescribir el


m todo ru n aportado por sta, de ah que T h r e a d proporcione este m todo aun
que no haga nada. El m todo r u n contendr el cdigo que debe ejecutar el hilo.

Los m todos stop, suspend, resu m e y r u n F in a liz e r s O n E x it incluidos en


versiones anteriores al j d k l .2 han sido desaprobados porque son intrnsecam ente
inseguros. Para m s detalles vea la ayuda sum inistrada por Sun.
640 JA V A : C U R SO D E PROGRAM A CIN

Hilo derivado de Thread

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:

public class ContadorAdelante extends Thread


I
p u b l i c C o n t a d o r A d e l a n t e ( S t r i n g nombre) // c o n s t r u c t o r
I
i f ( n o mb r e ! = n u i l ) setName(nombre);
s t a r t O ; // e l h i l o e j e c u t a s u p r o p i o m t od o r u n
I
public ContadorAdelante() ( th is(nu ll): I // c o n s t r u c t o r

public void run()


I
for (in t i = 1: i <- 1000: i++)
I
System .out.print(getNam e() + " " + i + " \ r ):
I
S y s t e m . o u t . p r i n t l n ( ):

La clase ContaclorAdelante es una subclase de T h re a d y sobreescribe el m


todo r u n heredado. Lo que hace este m todo es escribir el nom bre del hilo segui
do de un contador de 1 a 1000.

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:

public class Test


I
public static void m a in (S trin g [] args)
I
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 + " ) ;
C A PTU LO 15: HILOS 6 4 1

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.

Lo que no se debe de hacer es llam ar directam ente al m todo ru n ; esto eje


cutara el cdigo de este m todo sin que intervenga el planificador. Q uiere esto
d ecir que es el m todo sta rt el que registra el hilo en el planificador de hilos.

Hilo asociado con una clase

C uando sea necesario que un hilo ejecute el m todo r u n de un objeto de cualquier


otra clase que no est derivada de T h re a d . los pasos a seguir son los siguientes:

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 .

Por ejem plo, la siguiente clase im plem enta la interfaz R u n n a b le y sobrees-


cribe el m todo r u n proporcionado p o r sta:

public class ContadorAtras implements Runnable


I
p r i v a t e Thread c u e n t a A t r s ;
p u b l i c C o n t a d o r A t r a s S t r i n g nombre) // c o n s t r u c t o r
I
c u e n t a A t r s = new T h r e a d t h i s ) ; // o b j e t o de l a c l a s e T hr e a d
i f ( n o mb r e ! = n u i l ) c u e n t a A t r s . s e t N a m e ( n o m b r e ) :
c u e n t a A t r s . s t a r t ( ) ; // e l h i l o e j e c u t a e l m t o d o r u n de
1 // C o n t a d o r A t r a s
642 JA V A: C U R SO DE PRO G R A M A CI N

public ContadorAtras() I th is(n u ll); I // c o n s t r u c t o r

pu b lic void run()


I
for (in t i = 1000; i > 0; i - -)
I
S y s t e m . o u t . p r i n t t " \ t \ t " + c u e n t a A t r s . g e t N a me C ) + " " + i + \ r " ) :
I
System .out.pri n t l n ();

L a clase ContadorAtras no se deriva de T h re a d . Sin em bargo, tiene un m to


do r u n proporcionado por la interfaz R u n n a b le . Por ello, cualquier objeto Conta
dorAtras puede ser pasado com o argum ento cuando se invoque al constructor de
la clase T h re a d cuya sintaxis es:

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:

public class Test


I
public static void m a in (S trin g [] args)
I
ContadorAtras o b j C u e n t a A t r s = new C o n t a d o r A t r a s ( " C o n t a d o r - " );

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.

C om o ejercicio, pruebe a ejecutar la aplicacin siguiente y podr observar


com o los dos hilos, cuentaAdelante y cuentaAtrs, se ejecutan sim ultneam ente.

public class Test


I
public static void m a in ( S trin g [] args)
I
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 + " ) :
C o n t a d o r A t r a s o b j C u e n t a A t r s - new C o n t a d o r A t r a s ! " C o n t a d o r - * ) ;

C uando ejecute la aplicacin anterior, el sistem a lanza la ejecucin del hilo


prim ario (hilo padre) el cual, al ejecutarse, lanza la ejecucin del hilo cuentaAde
lante y la ejecucin del hilo cuentaAtrs, finalizando as la ejecucin de m a in ; no
obstante, este m todo no retom ar hasta que no hayan finalizado los hilos hijo;
esto es, el hilo prim ario no term ina m ientras no term inen sus hilos hijo.

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):

Si un hilo es un demonio, entonces cualquier hilo que el cree ser autom ti


cam ente un demonio.

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

public void run{)


I
c h a r bi p = ' \u0007 ;
w hile (true)
I
try
I
s l e e p ( l O O O ) ; // 1 s e g u n d o
1
catch ( In te r r u p te d E x c e p tio n e) 11
S y s t e m . o u t .pri n t ( b i p ) :

//////////////////////////////////////////////////////////////////

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 C o n ta d o rA d e la n te tS trin g nombreHilo)


I
setNametnom breHilo):
s t a r t ):

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

La siguiente aplicacin inicia un dem onio de la clase CDemonio expuesta


anteriorm ente y un hilo de la clase ContadorAdelante. M ientras este hilo m uestra
646 JA V A : C U R S O D E P R O G R A M A C I N

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

A un hilo en ejecucin se le puede enviar un m ensaje yield para que se m ueva al


estado preparado y ceda as la U C P a otros hilos que estn com pitiendo por ella
(hilos que estn en el estado preparado). Si el planificador observa que no hay
ningn hilo esperando por la U C P, perm itir que el hilo que iba a ceder la UCP
contine ejecutndose.

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

Si en la entrada estndar hay un byte disponible la sentencia anterior se eje


cuta satisfactoriam ente y la ejecucin del m todo que la contiene contina. Sin
em bargo, si no hay un b yte disponible, read tiene que esperar hasta q ue haya uno.
648 JA V A: CU R SO DE PROGRAM A CIN

Si el hilo que ejecuta read se m antuviera en el estado de ejecucin, la U C P que


dara ocupada y no se podra realizar nada ms. En general, si un m todo necesita
esperar una cantidad de tiem po indeterm inada hasta que la ocurrencia que lo de
tiene tenga lugar, el hilo en ejecucin debe salir de este estado. T odos los mtodos
Jav a que perm iten leer datos se com portan de esta form a. Un hilo que gentilm ente
abandona el estado de ejecucin hasta que se d la ocurrencia que lo detiene se
dice que est bloqueado.

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

preparado. Pasar a ejecucin cuando el planificador lo indique. Esto significa


que una llam ada a sleep bloquear un hilo por un tiem po superior al especificado.

La clase T h re a d proporciona tam bin un m todo in te rru p t. C uando un hilo


dorm ido recibe este m ensaje, pasa autom ticam ente al estado preparado, y cuan
do pase a ejecucin, ejecutar su m anejador In te rru p te d E x c e p tio n .

Esperando

El m todo w a it m ueve un hilo en ejecucin al estado esperando y el m todo noti-


fy m ueve un hilo que est esperando al estado preparado-, n o tify A ll m ueve todos
los hilos q ue estn esperando al estado preparado. Estos m todos, que verem os
m s adelante con m s detalle, se utilizan para sincronizar hilos.

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.

Segn lo expuesto, la m quina Java no reem plazar el hilo actual en ejecucin


por otro hilo de la m ism a prioridad. En otras palabras, la m quina Java no aplica
una planificacin por cuantos (tim e-slice cuanto o rodaja de tiem po : tiem po
m xim o que un hilo puede retener la UCP; esta planificacin da lugar a un siste
m a no determ inista), aunque la im plem entacin del sistem a de hilos que subyace
en la clase T h re a d puede soportar cuantos. Por lo tanto, no escribir cdigo que
dependa de cuantos porque com o se indica a continuacin, en unas m quinas
virtuales puede funcionar (en W indow s y M acintosh) y en otras no (en Solaris).

Despus de lo dicho, sera bueno al program ar que nuestros hilos cedieran


voluntariam ente el control algunas veces. Un hilo dado puede renunciar a su dere
cho de ejecutarse para ceder el control a otro de la m isma prioridad llam ando al
m todo yield. Un intento de ceder la U C P a hilos de m enor prioridad se ignorar.

La poltica de planificacin p o r prioridades expuesta, puede verse en algn


m om ento alterada por el planificador. Por ejem plo, el planificador de hilos puede
elegir para su ejecucin a un hilo de m enor prioridad para evitar que quede com
pletam ente bloqueado porque no pueda progresar p o r falta de los recursos necesa
rios para ello (puede m orir p o r falta de recursos: inanicin - starvation). Por esta
razn, la exactitud de los algoritm os program ados no debe basarse en la prioridad
de los hilos.

Qu ocurre con los hilos que tengan igual prioridad?

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:

un hilo de prioridad m s alta ha alcanzado el estado de preparado-,


cede la UCP, o su m todo r u n finaliza;
se supera el cuanto (quantum): tiem po m xim o que un hilo puede retener la
UCP. E sta tercera condicin slo es aplicable en sistem as que soporten la pla
nificacin por cuantos. En este aspecto, la especificacin Java da m ucha li
bertad. C ada m quina virtual im plem enta com o quiere este agujero en la
definicin, cum pliendo perfectam ente el estndar. P or ejem plo, las platafor
m as W indow s 9x/N T/2000 y M acintosh adm iten planificacin por cuantos
para hilos con la m ism a prioridad; en cam bio, Solaris planifica por coopera
cin, es decir, los hilos deben ceder voluntariam ente la UCP.
C A PTU LO 15: H ILOS 6 5 1

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.

Segn lo expuesto cm o perm itir la ejecucin de hilos con prioridad infe


rior? La respuesta est en saber que m uchos hilos del sistem a son detenidos de
vez en cuando, por m otivos diferentes. As, cuando todos los hilos de prioridad 10
estn detenidos, el sistem a asigna cuantos a los hilos preparados de prioridad 9.
U n razonam iento anlogo nos conduce a pensar que los hilos de prioridad 8 slo
pueden ejecutarse cuando los hilos d e prioridades 10 y 9 estn detenidos. Parece
entonces, que los procesos de prioridad 1 nunca se ejecutarn, o que se ejecutarn
de tarde en tarde. Pero, la verdad es que no es as. La m ayora de los hilos consu
men su tiem po durm iendo, lo que perm ite la ejecucin de los hilos de prioridades
bajas con una frecuencia, probablem ente, un poco inferior.

Asignar prioridades a los hilos


C uando se crea un hilo Java, ste hereda su prioridad del hilo que lo crea. No
obstante, es posible aum entar o dism inuir esta prioridad. Para m odificar la priori
dad de un hilo utilice el m todo setP rio rity:

h i l o . s e t P r i o r i t y (nuevaPrioridad) ;

La siguiente tabla m uestra las constantes correspondientes a las prioridades


definidas en la clase T h re ad :

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

Para obten er la prioridad que tiene un hilo utilice el m todo ge tP riority:

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.

T hread-1. P-2 2410 T h re a d -2 . P - 3 465771

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:

public c la ss Contador extends Thread


I
p u b lic in t cuenta:
p r i v a t e d o u b l e suma - 0:

public void run()


1
for (cuenta - 0: cuenta < 500000; cuenta++)
I
// R e a l i z a r a l g u n o s c l c u l o s
suma + M a t h . r a n d o m ( ):

// 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 class Cuentas extends i., c a d


I
private sta t ic int nCuentas:
private Contador[] cuenta:

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

publi c void run( )


I
int i :
b o o l e a n h a y a H i 1o s V i v o s :

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

La aplicacin Test que m uestre los resultados perseguidos puede ser la si


guiente:

public class Test


I
public static void m a in (S trin g [] args)
I
i n t n C u e n t a s = 2 : // n me r o de c o n t a d o r e s
// C r e a r y l a n z a r e l h i l o C u e n t a s
C u e n t a s h i l o C u a n t a s = new C u e n t a s ( n C u e n t a s ) ;
h i 1o C u a n t a s . s t a r t ( ):

En este ejem plo que acabam os de realizar, la poltica de planificacin es por


derecho de prioridad.

Q u pasar si elim inam os la sentencia sleep(nM ilisegundos)? Pues que la


poltica de planificacin seguida se ve alterada por el planificador para evitar que
el hilo de m ayor prioridad se apodere de la U C P (hilo egosta); prubelo (evitar
starvatiori). Sistem as com o W indow s 9x/N T /2000 pelean contra los hilos egos
tas con la estrategia de asignar la U C P p o r cuantos (tim e-slicing).

Q u sucede si asignam os a todos los hilos contador la m ism a prioridad? En


esta situacin, el planificador elegir el siguiente para ejecucin segn el m odelo
round-robn y en el caso de W indow s asignar, adem s, la U C P por cuantos.

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.

C uando un hilo se pone a dorm ir (se bloquea), no entra en la planificacin del


sistem a; esto es, el planificador no le asigna tiem po de U C P y, por consiguiente,
detiene su ejecucin.

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:

datos: m atriz de tipo dou b le.


ind: ndice del siguiente elem ento vaco.
tam a o : nm ero de elem entos de la m atriz.

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

C D atos: es el constructor de la clase. C rea la m atriz con n elem entos, valor


que se pasa com o argum ento, o con 10 si el valor pasado no es vlido; tam
bin inicia tam ao con el nm ero de elem entos.
obtener, d evuelve el valor de un determ inado elem ento.
asignar, asigna un valor a un determ inado elem ento.
c lcu lo s; obtiene el siguiente valor a alm acenar en la m atriz. R ecibe com o a r
gum ento el nom bre del hilo en ejecucin y devuelve el ndice del siguiente
elem ento vaco.

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

p u b lic double obtener(int i)


I
r e t u r n d a t o i ]:

public void a sig n a rd o u b le x, int i)


I
da t o C i ] = x ;

public int clculos(String hilo)


I
i f ( i n d > - t a ma o ) r e t u r n t a ma o :
double x = M a th .ra n d o m ():
S y s t e m . o u t . p r i n t l n h i l o + " muestra " + ind);
a s ig n a rx , ind):
ind++:
r e t u r n ind:

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:

public class CAdquirirDatos exten ds Thread


I
p r i v a t e C O a t o s m; // o b j e t o p a r a a l m a c e n a r l o s d a t o s
p u b l i c C A d q u i r i r D a t o s ( C D a t o s m d a t o s ) // c o n s t r u c t o r
1
m - mdatos:
I

public void run()


I
int i - 0;

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

En la aplicacin anterior observam os que m a in crea el objeto datos donde el


hilo A d q u ir rD atos_0 alm acenar los datos. Si ejecuta esta aplicacin el resultado
ser el siguiente:

Thread-0 tom la muestra 0


Thread-0 tom la muestra l
Thread-0 tom la muestra 2
Thread-0 tom la muestra 3
Thread-0 tom la muestra 4
Thread-0 tom la muestra 5
Thread-0 tom la muestra 6
Thread-0 tom la muestra 7
658 JA VA: C U R S O DB PROGRAM A CIN

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:

public class Test


I
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 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 ( ) :

A hora el m todo m a in de la aplicacin Test lanza dos hilos: adquir rD atos_0


y a d q u irirD a to s_l. C uando se lanza un hilo, el retom o al proceso padre es inm e
diato. P o r eso podem os suponer que la ejecucin del hilo A d q u irirD a to s_ l se ini
cia paralelam ente a la de adquirirD atos_0. Si ahora ejecutam os la aplicacin, el
resultado obtenido ser sim ilar al siguiente:

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)

A nalicem os los resultados. C uando se ejecut slo un hilo, la m atriz se llen


totalm ente sin problem as; esto es, no faltaron m uestras, tam poco se perdieron por
realizar alm acenam ientos consecutivos en el m ism o elem ento y no hubo accesos a
elem entos fuera de los lm ites establecidos (el nm ero de m uestra coincide con el
CA PTU LO 15: HILOS 6 5 9

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.

En sistem as que soporten la planificacin por cuantos, un hilo en ejecucin


puede ser interrum pido despus de cualquier lnea del m todo siguiente; por
ejem plo, supongam os segn el cdigo siguiente que uno de los hilos se interrum
pe despus de la lnea 6; no se increm ent ind. Si esto ocurre, cuando se ejecute el
otro hilo, alm acenar la m uestra adquirida en el ltim o elem ento utilizado; y si
suponem os que este hilo es interrum pido despus de la lnea 7, se increm enta el
ndice, cuando se ejecute de nuevo el hilo que se interrum pi en la lnea 6, volve
r a increm entar el ndice dejando un elem ento vaco.

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.

Crear una 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.

Y cm o se crea una seccin crtica? La form a m s sencilla de crear una sec


cin crtica es agrupando el cdigo definido com o crtico en un m todo declarado
s y n c h ro n iz e d (sincronizado).

En el ejem plo anterior, la seccin de cdigo crtica es el m todo clculos.


Esto quiere decir que un hilo no debe acceder a clculos cuando otro hilo lo est
ejecutando, para lo cual, el m todo clculos de la clase C D atos debe ser declarado
sy n ch ro n ized :
660 J A V A : C U R S O D E P R O G R A M A C I N

public class CDatos


I
II...
p u b lic synchronized int c lc u lo s(S trin g hilo)
I
i f ( i n d > = t a ma o ) r e t u r n ta mao:
d o u b l e 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 ( h i 1 o + " tom l a m u e s t r a " + ind);
a sig n a r(x , ind);
i nd++;
return ind;
I
I

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.

m o n ito r d isp on ible

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

Las secciones de cdigo sincronizadas, llam adas secciones crticas, denotan


que el acceso a ellas es crtico para el xito de la ejecucin de los hilos del pro
gram a. Por ello, en ocasiones, nos referim os a las secciones crticas com o opera
ciones atm icas, significando que ellas representan para cualquier hilo una
operacin que debe ejecutarse de una sola vez.

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:

public class CAdquirirDatos extends Thread


I
private C D a t o s m; // o b j e t o p a r a a l m a c e n a r l o s d a t o s

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:

public void run()


I
d o u b l e x:
do

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++:

while (m .ind < m.tamao):

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.

Lo que no se debe hacer es lo que se m uestra a continuacin, ya que si el b u


cle w hile pertenece a la seccin crtica, el planificador no podr bloquear el hilo
hasta que no term ine de ejecutarse y por lo tanto, no podr asignar tiem po de UCP
al otro hilo. C uando el bucle w hile finalice, la m atriz ya estar llena, lo que supo
ne que el bucle w hile para el otro hilo nunca se ejecutar.

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

En general es m ejor aplicar la sincronizacin a nivel del m todo que a un blo


que de cdigo. La prim era tcnica facilita m s el diseo orientado a objetos y
proporciona un cdigo m s fcil de interpretar y p o r lo tanto, m s fcil de depurar
y de m antener.

M onitor reentrante

Supongam os que en alguna ocasin necesitam os que un m todo sincronizado ten


ga que llam ar a otro m todo tam bin sincronizado de la m ism a clase. P or ejem
plo, para facilitar la com prensin de lo que se trata de explicar, vam os a suponer
que el m todo asig n a r tam bin est sincronizado:

public c la ss CDatos
I
II ...

public synchronized void asignardouble x, int i)


I
datofi] = x :
)

public synchronized int clculos(String hilo)


I
i f ( i n d > = t a m a o ) r e t u r n t a ma o :
d o u b l e x = M a t h . r a n d o m ( ):
S y s t e m . o u t . p r i n t l n ( h i l o + " tom l a muestra " + ind);
asignartx, ind);
i nd++;
re tu rn ind;

L a clase C D atos contiene ahora dos m todos sincronizados: asignar y clcu


los. El segundo llam a al prim ero. C uando un hilo trata de ejecutar el m todo cl
culos prim ero tom a el control del m onitor del objeto C D atos. A continuacin
ejecuta este m todo, el cual llam a al m todo asignar. C om o a signar est tambin
sincronizado, el hilo intenta adquirir otra vez el control del m onitor del objeto
CD atos. Parece lgico que el hilo debe bloquearse asim ism o puesto que trata de
adquirir un m onitor que l m ism o debe ceder, cosa q u e no puede hacer hasta que
no finalice la ejecucin d e clculos. En cam bio no sucede as p o r qu?
C A PTU LO 15: HILOS 6 6 3

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.

Utilizar wait y notify

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.

Supongam os la clase C M ensaje segn se m uestra a continuacin:

public class CMensaje


I
private S t r in g textoMensaje;
private i n t nmeroMensaje:

public synchronized void alm acenar(int nmsj)


1
nmeroMensaje = n m s j :
// 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 :
textoMensaje = "mensaje":
1

public synchronized String obtenerO


1
// C omp on er e l m e n s a j e b a j o un d e t e r m i n a d o f o r m a t o
S t r i n g mensaje;
mensaje = t e x to M e n s a j e + " / / " + nmeroMensaje:
r e t u r n mensaje;

Se ha considerado que los m todos alm acenar y obtener son operaciones


atm icas, significando que para cualquier hilo deben ejecutarse de una sola vez;
dicho de otra form a, se han definido com o secciones crticas.
664 JA V A : C U R S O D E P R O G R A M A C I N

En el ejem plo expuesto, estam os pensando en un sistem a que tendr un pro


ductor de m ensajes (m ensajes de aviso, de error, etc.) para generar y alm acenar
los m ensajes producidos (slo se recuerda el ltim o m ensaje) y un consum idor de
m ensajes que m ostrar al usuario el texto de cada m ensaje que se produzca. T anto
el productor com o el consum idor sern hilos que se suponen estn alertas para de
sem pear su funcin cuando sea requerida.

public c la ss Productor extends Thread


I
p r i v a t e CMensaje mensaje: // l t i m o m e n s a j e p r o d u c i d o
// C u a n d o s e p r o d u c e un m e n s a j e , e l p r o d u c t o r
// a l m a c e n a e l t e x t o en s u m i e m b r o " m e n s a j e "

public class Consumidor extends Thread


I
p r i v a t e CMensaje mensaje: // m e n s a j e a m o s t r a r
// C ua n d o s e ha p r o d u c i d o un m e n s a j e , e l c o n s u m i d o r
// l o o b t i e n e de s u miembro " m e n s a j e " y l o m u e st ra
)

C om pletem os el cdigo del productor. La clase P roductor tiene un construc


tor que inicia el atributo m ensaje con el objeto C M ensaje pasado com o argum en
to; este m ism o objeto ser el que utilice el consum idor para m ostrar el ltim o
m ensaje producido. C om o se puede observar, sta es una form a sencilla de hacer
que dos o m s hilos com partan datos. A sim ism o, sobreescribe el m todo r u n para
alm acenar el m ensaje que se produzca en el objeto C M ensaje; este m todo sim ula
que cada m seg s m ilisegundos, valor generado aleatoriam ente para cada m ensaje,
se produce el m ensaje de nm ero nm eroM sj, valor generado tam bin aleatoria
mente. El hilo perm anece dorm ido y despierta cada vez que se produce un m en
saje. Segn lo expuesto, una aproxim acin a la im plem entacin de esta clase
puede ser la siguiente:

public class Productor extends Thread


I
private CMensaje mensaje: // l t i m o m e n s a j e p r o d u c i d o

public ProductorCMensaje c) // c o n s t r u c t o r
I
m e n s a j e = c:

public void run()


I
i n t nmeroMsj: // n mero de m e n s a j e
w hile (true)
CA PTU LO 15: H ILOS 6 6 5

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 )

C om pletem os a continuacin el cdigo del consum idor. L a clase C onsum idor


tiene un constructor que inicia el atributo m ensaje con el objeto C M ensaje que
com parte con el productor. A sim ism o, sobreescribe el m todo ru n para obtener el
m ensaje alm acenado en el objeto m ensaje y m ostrarlo. S egn esto, la im plem en-
tacin de esta clase puede ser la siguiente:

public class Consum idor exten ds Thread


1
p r i v a t e CMensaje mensaje: // m e n s a j e a m o s t r a r

p u b lic ConsumidorCMensaje c) // c o n s t r u c t o r
I
m en sa j e = c:

public void run)


(
S t r i ng m s j ;

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:

Consumidor Thread-1 obtuvo: n u i l #0


Productor Thread-0 almacena: mensaje #15
Consumidor Thread-1 obtuvo: mensaje #15
Consumidor Thread-1 obtuvo: mensaje #15
Consumidor Thread-1 obtuvo: mensaje #15
Consumidor Thread-1 obtuvo: mensaje #15
Productor Thread-0 almacena: mensaje #19
Consumidor Thread-1 obtuvo: mensaje #19
Consumidor Thread-1 obtuvo: mensaje #19

Un anlisis sencillo nos conduce a la conclusin de que independientem ente


de que los m todos se hayan definido com o secciones crticas, no existe una sin
cronizacin entre el productor y el consum idor. El consum idor m uestra el ltim o
m ensaje producido cada vez que el planificador le asigna tiem po de U C P, en lugar
de hacerlo nica y exclusivam ente cada vez que se produzca un m ensaje.

Para conseguir la sincronizacin deseada, el m onitor asociado con el objeto


C M ensaje tiene que auxiliarse de los m todos w a it y notify. La siguiente figura
m uestra las transiciones de estados cuando intervienen estos m todos:

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

D ijim os q ue en Java, cada objeto tiene un m onitor. El m onitor controla el


acceso al cdigo sincronizado del objeto; en otras palabras, a la seccin crtica. Y
segn hem os visto, un objeto C M ensaje presenta dos secciones crticas. Pues bien,
el m todo no tify despierta slo un hilo de los que estn esperando por ese m oni
tor. Esto es, si hay varios hilos esperando, se elige uno arbitrariam ente. El hilo
despertado com petir de la m anera habitual con el resto de los hilos que estn en
el estado prep a ra do , p o r adquirir la UCP. S egn lo expuesto, el m todo notify
slo puede ser llam ado p o r un hilo que haya adquirido el control del monitor.

Un hilo se pone a esperar p o r el m onitor de un determ inado objeto invocando


al m todo wait. A dem s, el hilo cede el control del m onitor.

v o i d w a i t ( O ? / isegu nd os . n a n o s e g u n d o s ] ] )

El m todo w ait enva al hilo actualm ente en ejecucin al estado de espera,


hasta que otro hilo, el que tiene el control del m onitor, invoque al m todo notify,
n o tify A Il o in te rru p t, o bien hasta que transcurra el tiem po especificado. C uando
el hilo se pone a dorm ir, cede el control slo del m onitor q ue controla el acceso al
cdigo sincronizado del objeto que lo ha invocado, lo que perm itir a otro hilo
que est esperando por l, adquirirlo; esto es, cualquier otro objeto actualm ente
controlado p o r el hilo que se pone a dorm ir perm anecer bloqueado m ientras ste
est dorm ido.

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.

Lo anteriorm ente expuesto conduce a la conclusin de que los m todos wait,


notify, n o tify A Il e in te rru p t, deben ser invocados desde cdigo sincronizado.

A plicando la teora expuesta vam os a continuacin a sincronizar los hilos


productor y consum idor del ejem plo que estam os desarrollando. Para ello, hay
que tener presente que no se puede m ostrar un m ensaje que an no se ha generado
(por supuesto, los m ensajes se m uestran una sola vez) y no se puede alm acenar un
m ensaje, si an no se ha m ostrado el ltim o generado.
668 J A V A : C U R S O D E P R O G R A M A C I N

Entonces, aadirem os a la clase C M ensaje un atributo disponible de tipo


b o o lean , que valga false cuando no haya ningn m ensaje que m ostrar, y tr u e en
caso contrario.

public class CMensaje


(
private S trin g textoMensaje;
private in t nmeroMensaje;
private boolean d i s p o n i b l e - f a l s e :

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.

public synchronized void almacenar( in t nms j )


I
while ( d isp o n ib le == true)
1
// El l t i m o m e n s a j e a n no ha s i d o m o s t r a d o
try
I
wa i t ( ) : // e l hilo s e p o n e a d o r m i r y c ed e e l monitor
I
catch ( In te rru p te d E x c e p tio n e) I |
I
nmeroMensaje = n m s j :
II 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 el m e n s a j e en una t a b l a
II de m e n s a j e s : r e s u l t a d o :
textoMensaje = "mensaje":
d isp o n ib le = true;
n o t i f y A l 1( ):
I

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 synchronized String obtenerO


I
while (disponible == fa ls e )
I
// No h a y m e n s a j e
try
(
w aitO ; // e l hilo s e pone a d o r m i r y cede el monitor
I
catch ( InterruptedException e) I )
I
di spo ni b le = fa 1 s e ;
noti f y A l1();
// C o mp on e r e l m e n s a j e b a j o un d e t e r m i n a d o - f o r ma t o
S t r i n g mensaje;
m e n s a j e = t e x t o M e n s a j e + " II" + n m e r o M e n s a j e :
r e t u r n mensaje:
I

U na vez m odificados los m todos alm acenar y o btener de la clase C M ensaje,


ejecute de nuevo la aplicacin Test. O bservar que ahora los resultados s son los
esperados:

Productor Thread-0 almacena: mensaje 117 4


C o n s um i d o r Thread-1 obtuvo: mensaje #74
Productor Thread-0 almacena: mensaje #17
Consumidor Thread-1 obtuvo: mensaje # 17
Productor Thread-0 almacena: mensaje # 85
Consumidor Thread-1 obtuvo: mensaje #85
Productor Thread-0 almacena: mensaje #3
C o n s um i d o r Thread-1 obtuvo: mensaje #3
Productor Thread-0 almacena: mensaje #91
C o n s um i d o r Thread-1 obtuvo: mensaje #91

P or qu los mtodos alm acenar y obtener utilizan un bucle?

A ntes de proceder a la explicacin, aada m s consum idores y observar los re


sultados. Por ejem plo:

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:

1. if (disponible = false) II a n t e s : w hile (disponible = false)


2. I
3. try
4. I
5. w aitO ; // e l hilo s e po ne a d o r m i r y c e d e e l monitor
6 . )
7. catch ( InterruptedException e) ( )
8. 1
9. d i s p o n i b l e = fa 1s e :
10. n o t if y A l1():
11 . S t r i ng m e n s a j e ;
12. mensaje = t e x to M e n s a j e + " # " + nmeroMensaje:
13 . r e t u r n mensaje;

C om pile y ejecute de nuevo la aplicacin. C om pare los resultados con los


obtenidos anteriorm ente Q u ha ocurrido?

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

El peligro de utilizar una sentencia if en lugar de w hile es que algunas veces


el hilo que adquiere el control del m onitor, Thread-2, ejecuta la lnea 1 y supo
niendo que la condicin es cierta se pone a esperar, adem s de ced er el monitor.
M s tarde, otro hilo adquiere el m onitor, Thread-1, suponiendo que la condicin
es falsa ejecuta la lnea 10 y despierta a los hilos que esperan por este monitor.
Los hilos en el estado preparado com piten por la U C P. S upongam os que el pla
nificador se la adjudica al hilo original, Thread-2-, ste continuar donde lo dej, a
p artir de la lnea 5, independientem ente del estado del m onitor. El resultado es
que retorna el m ism o m ensaje que Thread-1. U tilizando una sentencia w h ile en
lugar de if, cuando Thread-2 contine donde lo dej, a partir de la lnea 5, volver
a ejecu tar la lnea 1 y se pondr de nuevo a esperar p o r ser la condicin cierta.

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.

P ara la m ayora de los program adores Java, la m ejor de evitar el interbloqueo


es prevenirlo, m ejor que probar y detectarlo. En cualquier caso, cualquiera de las
tcnicas existentes para m anejar los interbloqueos se sale fuera del objetivo de
este captulo.

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

P or ejem plo, la siguiente aplicacin obtiene una referencia al grupo actual


(grupo predefinido) al cual pertenece el hilo actual (en este caso el hilo prim ario)
y la alm acena en consum idores.

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

C m o se aaden los hilos a un grupo? Pues utilizando alguno d e los cons


tructores q ue la clase T h re a d proporciona para ello. P or ejem plo:

T h r e a d (T h r e a d G r o u p grupo, S t r in g nom breH ilo)

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:

public c la ss Consumidor extends Thread


I
p r i v a t e CMensaje mensaje: // m e n s a j e a m o s t r a r

p u b l i c Consum ido rtC M e nsa je msj, ThreadGroup grupo, String n o mbr e )


I
s u p e r g r u p o , nombre):
mensaje = m s j :
)

public void run()


C A P T U L O 15: H IL O S 6 7 3

Se puede observar que el constructor de la clase C onsum idor invoca al cons


tructor de su clase base (T h r e a d ) pasndole com o argum ento el grupo al cual se
quiere aadir el hilo, el cual est referenciado por this. y el nom bre del hilo.

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.

Hilo re c e p to r IjjH Flujo d e c a ra c te re s H ilo e m is o r

1
lpi
P ip e d R e a d e r P ip e d W rite r

Java proporciona las clases P ip e d R e a d e r y P ip e d W r ite r (y sus hom logas


para bytes, P ip e d ln p u tS tre a m y P ip e d O u tp u tS tr e a m ) para trabajar con tuberas
a travs de las cuales circularn flujos de caracteres. La prim era representa el ex
trem o de la tubera del cual un hilo obtiene los datos y la segunda el extrem o de la
tubera p o r el cual un hilo enva los datos al otro. Por lo tanto, estas clases traba
jan conjuntam ente para proporcionar un flujo de datos a travs de una tubera de
form a m uy sim ilar a com o una tubera real proporciona un flujo de agua; en sta.
674 JA V A: C U R S O DE PROGRAM A CIN

si se cerrara un extrem o se interrum pira el flujo. Esto m ism o ocurre con los flujos
que denom inam os tuberas.

Para crear la estructura de la figura anterior, prim ero crearam os un extrem o


de la tubera (extrem o sobre el que trabajar el em isor) y despus el otro conecta
d o al anterior para form ar la tubera (extrem o sobre el que trabajar el receptor).
El cdigo necesario para realizar lo expuesto es el siguiente:

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:

C on tuberas, la salida de un proceso se conecta directam ente a la entrada del


siguiente, segn m uestra la figura siguiente:

D ejam os este problem a para que lo resuelva el lector. N osotros vam os a re


solver uno m s breve que m uestre sim plem ente cm o se utilizan las tuberas. Un
hilo productor produce m ensajes que pasa a travs de una tubera a otro hilo con
sum idor para que los m uestre en pantalla. La figura siguiente resum e lo expuesto:

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

Se puede observar que el m todo m a in crea una tubera em isor-receptor. A


continuacin crea el hilo p ro d u c to rl y le pasa com o argum ento el extrem o de la
tubera por el cual debe de enviar los m ensajes al hilo consum idor. D espus crea
el hilo co n su m id o rl y le pasa com o argum ento el extrem o de la tubera por el cual
debe obten er los m ensajes enviados por el hilo productor. Finalm ente, lanza los
dos hilos para su ejecucin.

M ostram os a continuacin la clase correspondiente al hilo productor. Esta


clase tiene un atributo em isor, que referenciar el extrem o de la tubera p o r lo que
se enviarn los m ensajes al hilo consum idor. Este atributo ser establecido por el
constructor de la clase.

Para en v iar m ensajes al consum idor, el m todo r u n del productor crea un


flujo (flujoS) de la clase P r in t W r it e r hacia el extrem o em isor. E ste flujo perm iti
r utilizar el m todo p rn tln , que P ip e d W r ite r no tiene, para enviar los m ensajes
por la tubera. L a generacin de los m ensajes se sim ula igual que hicim os en la
versin de la aplicacin productor consum idor anterior. En este caso, por tratarse
de una tubera, los m ensajes producidos son enviados por la m ism a y puestos en
cola m ientras el consum idor los va recuperando.

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

private PrintW riter flu joS = nuil:

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

public synchronized void almacenarMensajet)


I
i n t nmeroMsj: // n me r o de m e n s a j e
S t r i n g t e x t o M e n s a j e : // t e x t o m e n s a j e

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 :

p u b lic ConsumidorPipedReader re) // c o n s t r u c t o r


I
r e c e p t o r = r e :
f l u j o E - new B u f f e r e d R e a d e r ( r e c e p t o r );
I

public void run()


1
w hile (true)
I
o b t e n e r M e n s a j e ( ):

public synchronized void obtenerMensaje()

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 ):

catch (lOException ignorada) I)

protected void f i n a l i z e (> throws lOException


I
if ( f l u j o E != n u i l ) I f l u j o E . c l o s e ( ): f l u j o E = n u i l ; 1
if ( r e c e p t o r != n u i l ) ( r e c e p t o r . c l o s e ( ): r e c e p t o r = n u i l : I
678 JA V A : C U R S O D E P R O G R A M A C I N

ESPERA ACTIVA Y PASIVA


C uando se disea un hilo, lgicam ente no slo pensam os en el trabajo que tiene
que desem pear, sino en cm o su trabajo puede verse afectado p o r otros hilos. De
ah el estudio de la sincronizacin de hilos. P ero no es m enos im portante pensar
cm o tiene que com portarse el hilo com o unidad individual de ejecucin; esto es,
ponindonos en el caso de que durante espacios m s o m enos cortos, su ejecucin
no va a ser interferida p o r otros hilos. Si esto es as, los objetos de sincronizacin
no sern requeridos por otros hilos y puede haber tiem po suficiente para que el
hilo finalice su trabajo a la espera de que se den otros eventos que lo requieran de
nuevo. En un caso com o ste, la espera debe ser pasiva y no activa; es decir, no
debe co n su m ir tiem po de UCP.

E n general un hilo realiza una espera pasiva ponindose l m ism o a dorm ir


porque cuando est durm iendo, no entra en la planificacin del sistem a operativo;
esto es, el sistem a operativo no le asigna tiem po de U C P y, por consiguiente, de
tiene su ejecucin. T anto w a it com o sleep ponen un hilo a dorm ir; en el prim er
caso, para despertado hay que invocar a no tify o notifyA ll, o bien esperar a que
transcurra el tiem po si se especific, y en el segundo caso despierta cuando trans
curra el tiem po especificado.

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.

La figura anterior m uestra un esquem a del problem a del p ro d u cto r y el con


sum idor. Para un correcta sincronizacin entre los hilos, el productor deber blo-
C A P T U L O 15: HILOS 6 7 9

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.

El cdigo correspondiente a esta clase se m uestra a continuacin:

//////////////////////////////////////////////////////////////////
// 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:

public CMatriz int n)


I
i f ( n < 1 ) n = 10;
m = new i n t [ n ] :
elem entosVacos = m.length;
e l e m e n t o s L l e n o s = 0:

public synchronized v o i d a l m a c e n a r i n t num)


I
// E s p e r a r a q u e h a y a e l e m e n t o s v a c o s
w h i le ( e le m e n t o s V a c o s = = 0)
1
try
I
wait(): // e l hilo s e po ne a d o r m i r y c e d e e l monitor
680 J A V A : C U R S O D E P R O G R A M A C I N

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

public synchronized int obtenerO


I
II E s p e r a r a q u e h a y a e l e m e n t o s llenos
w hile (elementosLlenos = 0)
I
try
I
w ait{); // e l hilo s e pone a d o r m i r y cede el monitor
I
catch (In terruptedExce ption e) I )
I
elementosVac os++;
e l e m e n t o s L l e n o s - -;
S yste m .o ut.p r i n t ( " v a c i o s : + elem entosVacos + ", llenos: " +
elementosLlenos + " \r"):
i n t num = m [indCons];
i n d C o n s = ( i n d C o n s + 1) % m . l e n g t h ;
noti f y A l1();
r e t u r n num;

//////////////////////////////////////////////////////////////////

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

vacos de la m atriz. P or lo tanto, el contador de elem entosLlenos debe valer ini


cialm ente cero y el de elem entosV acos debe valer m .length.

C uando un hilo necesita un recurso de un tipo particular, decrem enta el con


tador del sem foro correspondiente, y cuando lo libera lo increm enta. Por ejem
plo, cuando el productor quiere alm acenar un dato necesita el recurso elem entos
vacos , de tal form a que cada vez q ue lo adquiere lo decrem enta; cuando llegue a
cero im plica sem foro en rojo indicando que el recurso elem entos vacos" est
ocupado. Lgicam ente decrem entar elem entosV acos im plica increm entar ele
m entosLlenos.

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

El cdigo anterior, que pertenece al hilo productor, decrem enta el contador


del sem foro elem entosV acos, inserta un dato en el siguiente elem ento vaco de
la m atriz y, lgicam ente, increm enta el contador del sem foro elem entosLlenos.
Si el contador de elem entosV acos fuera cero, el hilo productor pasara al estado
bloqueado hasta que el hilo consum idor extraiga uno o m s datos y, p o r consi
guiente, increm ente elem entosVacos. Un razonam iento anlogo haram os para el
consum idor.

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 ) :

public void term inar()


I
continuar = false;

//////////////////////////////////////////////////////////////////

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;

public void run()


I
i n t n me r o :
w hile (continuar)
I
n mero - m a t r i z . o b t e n e r ( ) ;
/ / System .out.p r in t ln ( "C o n s u m id o r + getNamet) +
// " obtuvo: n me r o " + n m e r o ) :
I
I
CA PTU LO 15: HILOS 6 8 3

p u b lic void te rm inar)


I
continuar = false:
I
I
//////////////////////////////////////////////////////////////////

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 ):

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 ] para c o n t i n u a r y " ) :


S y s t e m . o u t . p r i n t l n ( " v u e l v a a p u l s a r [ E n t r a r ] para 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
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

com o resultado el nom bre de los m todos de ordenacin colocados de m s rpido


a m enos rpido.

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.

5. G rabar el resultado obtenido en el punto 4 en otro fichero. D espus, visualizar


el fichero para com probar el resultado obtenido.
A PN D IC E F
F.J.Cebalos/RA-MA

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

atributos (continuacin) m anipular, 173


de la clase, 78 C ardL ayout, 731
iniciar, 255 cast, 51
static, 289 catch, 95; 403
AudioClip, 716 ceil, 115
available, 114 CGI, 703
aw t.7 1 0 ; 723 ciclo de vida, 646
clase, 25. 253
abstracta, 92; 330
B anidada, 381
barra de direcciones, 695 annim a, 384
barra de estado, mensajes, 718 aplicacin, 30
biblioteca de clases, 15 A pplet, 707
bin. 10 A rrays, 233
binarySearch, 233 base. 329
bit, 4 B ufferedlnputStream . 98
bloque, 72 B ufferedReader. 99; 613
bloque de finalizacin, 405 B ufferedW riter, 613
bloqueado, 637 C alendar. 263
boolean, 27; 43; 103 CArboIBinB, 555
BorderLayout, 731 C A rbolBinE, 559
borrar los elem entos de una lista, 504 C lass. 97
borrar nodo, 553 C olor, 713
borrar un elem ento de una lista, 503 crear, 26
BoxLayout, 731 D atalnputStream , 442
Boyer y M oore, 602 D ataO utputStream , 441
break, 131; 146 Date, 74; 232
BufferedlnputStream , 98 D ateForm at, 232
BufferedReader, 99; 613 de un objeto, 97
B ufferedW riter, 613 D ecim alForm at, 226
burbuja, 592 dentro de un m todo, 383
buscar nodo, 550 derivada, 329
buscar un elem ento en una lista, 504 derivada de otra ya existente, 429
buscar un elem ento en una m atriz, 299 E O FException, 404
bsqueda binaria, 233; 601 Error, 413
bsqueda de cadenas, 602 E xcepcin, 400
bsqueda secuencial, 600 FieldPosition, 228
byte, f , 41; 103 File. 434
FilelnputStream . 433
FileOutputStream , 430
c FileReader, 439
cadenas de caracteres, 175 FileW riter, 438
concatenar, 46 final, 268
leer y escribir, 176 Font. 713
Calendar, 263 Form at, 226
campo, 420 genrica, 509
capacity, 187 G raphics, 708
capas de servicios de la red, 689 G regorianCalendar, 263
carcter siguiente en el flujo de entrada, 427 H ttpServlet, 738
caracteres, 38 InputStream . 93
\r\n , 112
InputStream Reader, 99
disponibles en un flujo, 114 interna, 382
IO Exception, 400
A PN D IC E F: N D IC E 7 7 1

clase (continuacin) C olor. 713


JA pplet, 734 C ollection, 566
JButton, 727 com entario, 47
JComboBox, 727 com pareTo, 182
JCheckBox. 727 com pareToIgnoreC ase, 183
JFram e, 724 com pilacin, 14
JLabel, 727 com pilador, 6
JO ptionPane, 727 com pilador J1T, 8
JRadioB utton. 727 com plejos, 326
JScrolIBar, 727 com ponente S w in g , 726
JTextA rea. 727 com portam iento, 27
JTextField. 727 concat, 182
L eer. 106; 415 concatenar, 46
LinkedList, 519 constante simblica, 48
lista lineal sim plem ente enlazada, 505 constructor, 34; 74, 269
Lcale. 228 constructor copia, 276
M ath, 114 constructor de la superclase, invocar, 345
M essageForm at. 233 constructor de una subclase, 345
M ethod, 97 constructor por om isin, 270; 272
N umberFormat, 226 consulta dinm ica, 371
O bject, 92; 97; 168; 235; 287; 509; 758 contador, 174
O bjectlnputStream , 451 contenedores, 729
O bjectO utputStream . 450 de nivel interm edio, 730
OutOfMemoryErTor. 413 de nivel superior, 730
OutputStream , 94 continu, 146
PrintStream . 100 control de acceso a una clase, 265
PrintW riter. 102 control el acceso, 336
pblica, guardar, 67 conversin, 51
PushbackReader. 425 de cadenas a nm eros, 191
Random , 241 explcita en subclases, 359; 511
Reader. 93 im plcita en subclases, 357
Runtim eException, 400 copiar una matriz num rica, 217
Sim pleD ateForm at, 231 correo electrnico, 692
String. 27; 181 eos, 115
StringBuffer, 186 CR, 112
System . 69 crear un objeto, 73
Thread, 638 crear un paquete, 304
Throw abie. 95; 399 crear una clase, 26
TreeM ap. 567 crear una nueva excepcin, 408
TreeSet, 566 CRLF. 112
W riter, 94 cuanto, 650
clases con ficheros, 480 currentTim eM illis, 629
clases Hash..., 567 char, 42
clases para tipos primitivos, 103 Character, 103
class, 26; 97 CharA rrayR eader, 423
CLA SSPA TH , 110; 305 CharA rrayW riter, 423
CListaLinealSE, 512; 523; 534 charA t. 185; 189
clone. 168;218
cise. 425; 432; 458
cdigos de bytes, 7
D
cola, 529 D atalnput, 442
colecciones de objetos, 566 D atalnputStream , 442
colector de basura, 83 DataO utput, 441
772 JA VA : C U R SO DE PROGRAM A CIN

D ataOuipulStream . 441 estructuras dinm icas, 495


Date. 74; 232 etiquetas, 147
DateFormat, 232 eventos. 727
DecimalFormat. 226 excepcin
declaracin, 70 atrapar, 403
declarar las excepciones. 407 declarar. 406
definicin de un m todo, 72 lanzar. 402
definir una subclase, 338 manejar, 401
delete, 188:436 utilizar, 413
dem onio, 643 excepciones, 95; 397
depuracin, 16 crear, 408
destroy, 709 explcitas. 400
destructor. 34; 276 im plcitas, 400
destructor en una subclase, 347 Excepcin, 400
direccin de Internet, 691 exists, 435
direccin IP. 691 exp, 115
diseo, adm inistradores. 730 expresiones booleanas, 54
dispositivo de salida, 26 expresin, 51
dispositivos estndar. 472 extcheck, 10
DNS, 690 extends, 335; 372
d o ... while, 139 extranet, 689
doG et, 739
dom inio, 690
doPost. 739
F
double. 43; 103 fecha/hora. 263
doubleV alue, 104 fichero, 420
draw lm age, 715 leer lneas de texto, 477
draw String, 721 fichero tem poral, 471
FieldPosition, 228
E File. 434
FilelnputStream , 433
ejecucin, 14; 637 FileOutputStream , 430
elim inar un elem ento de una m atriz. 298 FileReader, 439
else if, 126 FileW riter, 438
e-m ail, 692 filtros, 441
encapsulacin, 77 fill. 234
encapsulam iento, 33 fin de fichero, 110
endsW ith, 184 final. 48; 268
enfocado, 728 finalize. 237
enlaces, 699 finalize en una subclase, 347
ensam blador, 4 finally, 405
entorno de desarrollo integrado, 11; 16 float. 42; 103
EOFException, 404 floatV alue. 104
equals, 168; 234; 236; 287 floor. 115
err, 96 F low Layout, 731
Error, 400 flujo, 91; 421
escuchadores de eventos, 727 limpiar, 427
estados de un hilo, 636 flujos
estados de un proceso, 634 de bytes, 430
estructura de una aplicacin grfica, 724 de caracteres, 437
estructura else if, 126 d e datos, 440
estructura interna, 255 estndar, 96
estructuras abstractas de datos. 496 flush, 102
A PN D IC E F: NDICE 7 7 3

foco, 728 m ltiple, 34; 335; 379


FocusListener, 728 simple, 33; 335
Font. 713 hilo. 635
for. 142 est vivo?, 647
Form al, 226 creado, 641
formato, 225 crear, 641
alineacin, 228 egosta. 654
para fechas y horas, 2 3 1 prioridad, 651
para mensajes, 233 term inar, 644
sm bolos, 226 hilos
FTP. 6 9 1 .6 9 3 cooperantes, 655
fuentes. 713 espera activa. 678
espera pasiva, 678
estados, 636
G independientes, 654
garbage col lector, 279 sincronizar, 655
ge, 279 hipertexto, 699
G ET, 739 HTM L, 695
getBytes, 186 etiquetas, 696
getClass, 97 H ttpServlet, 738
getC odeB ase, 715
getContentPane, 730
I
getCrossPlatform LookA ndFeelClassN am e, 731
getC urrencylnstance, 227 identificadores, 46
getD atelnstance, 232 lEEErem ainder, 115
getD ocum entBase, 715 if, 121
getEndlndex, 228 if anidados, 124
getlm age, 715 im agen en un applet, 714
getM essage, 403 im genes en un docum ento HTM L, 701
getM ethods, 97 im plem entacin de una clase. 259
getN am e, 97 im plem ents, 374
getN um berlnstance, 227 import. 69
getRarameter, 712 in. 96
getPercentlnstance, 227 indexOf, 185
getPriority, 651 iniciador esttico, 293
getSystem LookA ndFeelClassN am e, 731 init, 708; 739
getTim e. 242 inorden, 544
getTim elnstance, 232 InputStream , 93
G opher, 691 InputStream Reader, 99
grficos en un docum ento HTM L. 701 insercin. 595
Graphics, 708 insert, 187
G regorianCalendar, 263 insertar nodo. 5 5 1
G ridBagLayout, 7 3 1 insertar un elem ento en una lista, 500
G ridLayout, 731 instanceof, 530
grupos de noticias, 693 instancia, 25
int. 41
Integer. 103
H
interfaces, 372
Hanoi, 589 grficas, 723
hash. 616 mltiples, 381
H ash..., 567 interfaz, 34; 256; 269
herencia, 33; 329; 331 A udioClip, 716
D atalnput, 442
774 JA V A . C U R SO DE PROGRAM ACIN

interfaz (continuacin) JLabel. 727


DataOutput. 441 JO ptionPane. 727
definicin. 371 JRadioB utton, 727
para qu sirve, 380 jre, 11; 649
pblica. 77 JScrollB ar. 727
Runnable. 639; 641 JSP, 737
Serializable, 449 JSW D K, 742
SingleThreadM odel, 740 JTextA rea, 727
tipo de datos, 378 JTextField. 727
utilizar, 374
vs. clase abstracta, 377
K
intem , 240
Internet. 688 kem el, 636
Internet Explorer. 694 K eyListener, 728
intrprete.6
interrupt, 667
intranet, 689 L
intValue. 104 lang, 69
invocar a un mtodo redefinido. 359 lanzar una excepcin, 402
IOException, 95; 400 lastlndexO f. 185
isAlive. 647 leer, 104
ISAPI. 704 leer lneas de texto, 477
isDirectory, 436 leer una lnea de texto, 99; 428
isFile. 436 Leer, clase. 415
isNaN. 206 length, 168; 184; 187
ItcmListener, 728 lenguaje m quina, 5
lenguajes de alto nivel, 5
J LF, 112
lib. 11
JA pplet, 730; 734 lim piar un flujo, 427
jar. 10 LinkedList. 519
Java, 7; 10 List, 566
Java 2D, 723 lista circular, 522
Java Runtime Environm ent, 649 lista circular doblem ente enlazada, 534
java.io. 89; 421 lista doblem ente enlazada, 533
java.lang. 69; 89 lista lineal sim plem ente enlazada, 496
java.tcxt. 226 lista lineal sim plem ente enlazada, 496
java.til. 74; 228 lista lineal, recorrer, 504
javac. 10 listas lineales. 496
javadoc. 10 literal. 43
javah, 10 de cadena de caracteres. 45
j a v a p .10 de un solo carcter, 45
javax.servlet. 738 entero. 44
JB utton, 727 real, 44
JC om boBox, 727 Lcale, 228
JC heckB ox, 727 log, 115
jdb, 10 long. 41; 103
JD ialog, 730 longitud de una m atriz, 168
JDK, 10; 759 longValue. 104
jerarqua de clases, 329; 336; 350 loop, 716
J F C .723 L P T I.4 7 2
JFratne. 724
JIT. 8; 11
A P N D IC E F: N D IC E 775

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

a un tipo primitivo, 219 setLayout, 731


final, 268 setLength, 187
referencias a subclases, 356 setLookA ndFeel, 731
referencias y objetos String, 238 setPriority, 651
reflexin, 98 short, 41; 103
registro, 420 show Status, 718
repaint, 708; 719 Sim pleD ateForm at, 231
replace, 185; 188 sin, 115
representacin interna, 269 sincronizacin d e hilos, 655
reset, 613 exclusin mutua, 663
resultado, 72 secciones crticas, 655
return, 73 SingleThreadM odel, 740
reverse, 188 sistem a de nom bres de dom inio, 690
rint, 115 skip, 114
r\n, 112 sleep, 667
round, 115 S M T P . 692
round-robin. 650 sobrecarga de m todos. 262
run, 640 sobrecarga del operador +, 309
Runnable, 639; 641 sonido en un applet. 716
Runtim eException, 400 sonido en una aplicacin, 717
sort, 235
sqrt, 115
s start, 641; 708
saltar n caracteres en un flujo, 114 startsW ith, 184
seccin crtica, 659 starvation, 650; 654
secciones criticas, 655 static, 48; 78; 289; 290
secuencia de escape, 39 static iniciador, 293
seguridad en los applets, 722 stop, 708; 716
sentencia stream, 421
break, 146 String, 27; 90; 181
com puesta, 72 String, constructor, 181
continu, 146 StringBuffer, 186
de asignacin, 90 subclase, 329; 335
d o ... while, 139 subdom inio, 690
for, 142 subproceso, 635
if, 121 substring, 185; 189
im port, 69 super, 339; 342; 344; 345
return, 73 superclase, 329
sim ple, 7 i directa, 354
sw itch, 129 indirecta. 354
while. 133 Sw ing, 723
seriacin, 449 switch, 129
Serializable, 449 synchronized. 659
servidor de nom bres, 691 System, 13; 26; 69
servidor de servlets, 742 System.err, 96
servidor W eb de Java, 742 System .in, 96
servlet, 737 System .out, 96
ejecutar, 743
estructura, 738 T
Set. 566
setColor. 713 tan. 115
setCharAt, 189 TCP/IP, 689
setFont, 713 T elnet, 692
778 J A V A : C U R S O D E P R O G R A M A C I N

this. 266; 344


Thread. 638
u
throw. 402 U IM anager, 731
Throw able. 95; 399 Unicode. 38; 42
throws. 407 unread. 425
tiem po de ejecucin. 629 update. 708
tim e-slice, 650 URL. 699
tipo URL de la carpeta, 715
boolean, 43 USENET. 692; 693
byte, 41 UTF-8, 441
char. 42 Util. 74
double, 43
float, 42
int, 41
V
long, 41 valueO f. 104; 186
referenciado, 80 variable. 49
short, 41 CLA SSPA TH . 110
String, 90 iniciar, 50
tipos primitivos, 40 local, 86
tipos referenciados, 43 m iem bro de una clase, 86
toCharA rray, 186 void. 28; 72
toDegrees, 115
toLow erCase, 184
toRadians, 115 w
torres de H anoi, 589
wait. 663; 667
toString, 104; 182; 189; 237 W eb. 693
toU pperCase. 184 w hile. 133
TreeM ap. 567
w hile, do. o for anidados, 136
TreeSet, 566 w indow Closing, 725
trim, 184
W indow Listener, 728
try. 95; 403
W orld W ide W eb. 692; 693
try ... catch, 148
w ritc, 94; 431; 613
W riter, 94
w riteU TF. 463
W W W , 692; 693
N ota del escaneador

E scaneado en ab ril del 2005 en Toledo (Espaa)


D iscu lp en la calidad, ya que el libro est m u y tocado y es de la biblioteca.

E ste libro es m u y bueno, es de Jav ier C eballos, si te gusta, p o r favor, c m p ra te lo !.


A hora m ism o cuesta 42 euros.

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.

E spero que este libro os sirva para algo.

Você também pode gostar