Aprendiendo Java(x)
Transcript of Aprendiendo Java(x)
1
Aprendiendo Java 1
y 2
Programación 3
Orientada a 4
Objetos 5
Gustavo Guillermo Pérez 6
www.compunauta.com 7 [email protected] 8
*Hasta que esta leyenda no desaparezca el 9 libro no ha sido terminado, revisar: 10
http://compunauta.com/forums/linux/programa11
cion/java/ebook.html 12
para las actualizaciones diarias o semanales y 13
para descargar el código de los ejemplos. 14
ESTE LIBRO ES LIBRE Y GRATUITO, 15 CONSIDERA HACER UNA PEQUEÑA 16 DONACIÓN EN LA WEB INDICADA 17
ARRIBA. 18
*Para navegar el Índice con Adobe Acrobat 19
Reader, abrir favoritos o bookmarks 20 Ultima actualización, lunes 11 de febrero de 21
2008 22
Prólogo 23
2
Este libro se hizo con la idea de proveer a mis 24
alumnos y cursos un material didáctico con 25
qué 26 trabajar (también es útil para profesores y 27
otros cursos) y al mismo tiempo dar una idea 28
concisa de lo 29 que significan los objetos en Java. La 30
programación orientada a objetos en Java no 31 es tratada y enfocada 32
en muchos textos tutoriales, manuales o libros 33
sobre el tema y considero que es la etapa 34 inicial del 35
aprendizaje donde se falla en muchos cursos 36 respecto a Java. Por otro lado los estudiantes 37
que recién se 38
inician en la programación, no podrán ir muy 39 lejos si no se les inculca los conceptos 40
básicos, entonces 41
este material no avanzara de lleno sobre la 42 programación orientada a objetos, sino hasta 43
que los 44
conceptos de programación básicos, como 45 tomas de decisión, bucles, variables etc, estén 46
fijados lo 47 suficiente. 48
Java es un lenguaje muy útil debido a la 49
opción multiplataforma que provee (desde PC, 50 Linux, 51
Windows, hasta MAC, teléfonos, pocket PCs, 52
etc.) y veremos en el transcurso de este texto 53 como se 54
3
puede optimizar la ejecución de una aplicación 55
Java para que se aproxime a la ejecución de 56
un binario 57 nativo como los que se compilan con gcc. 58 Por lo tanto suponer que el alumno posee 59
conocimientos avanzados de programación 60 orientada a 61
objetos o de otros lenguajes de programación 62 no siempre suele ser la mejor opción, en este 63
libro 64
dejaremos en claro que el lenguaje de 65 programación Java tiene sus operadores 66
matemáticos básicos y 67 tipos de datos básicos sin importar que estos 68 mismos existan o no en otros lenguajes de 69
programación. 70 Este libro se distribuye bajo la licencia GNU 71
GPL v2, con la excepción que está prohibido 72
hacer 73 impresiones modificadas del texto, si alguien 74
tiene una sugerencia o una modificación para 75
sugerir, 76 puede enviar al correo electrónico indicado la 77 información, para una futura actualización o 78
corrección. 79
Las sugerencias son bienvenidas. 80
I. TEMAS INTRODUCTORIOS 81
La Máquina Virtual de Java (JVM, 82
Java Virtual Machine) 83
La máquina virtual de Java se denomina al 84 procesador o entorno virtual que se utiliza 85
para 86
4
interpretar los bytecodes de los binarios de 87
Java, ya que como sabemos Java se hizo 88
para correr en 89 cualquier plataforma sin recompilar los 90
binarios. De esta manera este entorno virtual 91
se puede obtener 92 para nuestra arquitectura y sistema operativo 93
sin modificaciones a nuestro programa original 94 (esto no es 95
cierto si utilizamos una mala dinámica de 96
programación). 97 Podemos entonces generar un binario y este 98
podrá Correr en Linux, MAC OSX, FreeBSD, 99 Solaris, o Windows, y para las arquitecturas 100 disponibles en las que podamos obtener la 101
JVM, como ser 102 AMD64, SPARC, PIV, etc. etc. 103
La máquina virtual de Java ha tenido la 104
característica de ser un entorno de ejecución 105 pesado en 106
términos de recursos del procesador y 107
memoria, que por medio de una 108 administración rigurosa del 109
sistema operativo estos podrían llegar a ser 110 insuficientes y las aplicaciones ejecutarse de 111
manera muy 112
lenta. Esto no es cierto en la actualidad, 113 existen alternativas a la JVM provista por Sun 114
Microsystems 115
que permiten una velocidad comparable a una 116 aplicación compilada en C++ nativa en la 117
arquitectura, un 118
5
ejemplo de esto es Kaffe, Kaffe 119
(www.kaffe.org) es una máquina de Java 120
OpenSource que puede 121 compilarse sin mayores modificaciones en 122 nuestra arquitectura necesaria y correrá 123
increíblemente más 124 rápida que la distribución estándar de JVM de 125
Sun Microsystems y consumirá muchos 126 menos recursos. 127
Kit de desarrollo y Entorno de 128
ejecución (JDK, JRE) 129
El Kit de desarrollo conocido como JDK (Java 130
Development Kit) provee de un compilador, un 131 mecanismo para comprimir un proyecto en un 132
solo archivo de tipo JAR (que es compatible 133 con ZIP) y 134
un entorno de ejecución para nuestros 135
binarios. 136
Cuando nuestro proyecto terminado se 137 prepara para distribuir, no es necesario tener 138
el compilador 139 y la mayoría de las herramientas que se 140 proveen en el JDK, entonces podemos 141
prescindir de dicho JDK 142
y utilizar el entorno de ejecución que es más 143
pequeño en cuestiones sólo de espacio en 144 disco. Este JRE 145
(Java Runtime Environment) también puede 146
redistribuirse sin problemas de licencias. 147 En las plataformas basadas en Linux, existen 148
mejores herramientas de desarrollo y por 149
supuesto en 150
6
casi todas las distribuciones de Linux, se 151
encuentra disponible Kit de desarrollo o JDK. 152
Así como 153 recomendamos Kaffe como JVM para 154
proyectos avanzados o de alto rendimiento, 155
recomendamos Jikes 156 como compilador de ByteCodes para Java, 157
Jikes no es interpretado como el compilador 158 proporcionado 159
en el JDK de Sun Microsystems. 160
Comandos que inician el JDK, JRE 161
Comando Descripción 162 java Inicia el entorno de ejecución recibiendo como 163
argumento el nombre del binario ejecutable 164 en formato ByteCodes sin la extensión de archivo .class 165
que identifica de manera visual un 166 binario java. Este comando es parte de JDK y JRE 167 javac Inicia el compilador Java recibiendo como 168
argumento todos los archivos de código fuente 169 cuya terminación es .java incluida dicha extensión. Este 170
comando no es parte de JRE. 171 jar Por medio de este comando iniciamos el 172
empaquetador de clases y archivos de Java que nos 173 permiten fabricar un único archivo contenedor de 174
nuestras aplicaciones, multimedia y 175 gráficos. Este comando es parte sólo de JDK. 176
Salida por pantalla de los comandos 177
del JDK, JRE 178
Si abrimos una consola de comandos, y 179
ejecutamos estos comandos podremos 180
detectar la versión 181 del entorno de ejecución y las órdenes de 182
entrada que estos soportan. 183
7
En Linux, podemos abrir una XTerm, 184
buscando el menú ejecutar y escribiendo 185 xterm. En 186
Windows, podemos hacerlo abriendo el 187 diálogo ejecutar y escribiendo command o 188
cmd dependiendo si 189
el sistema es basado en NT o 9X. 190 gus@gusgus ~ $ java 191
Usage: java [-options] class [args...] 192 (to execute a class) 193
or java [-options] -jar jarfile [args...] 194 (to execute a jar file) 195 where options include: 196
-client to select the "client" VM 197 -server to select the "server" VM 198
-hotspot is a synonym for the "client" VM 199 [deprecated] 200
The default VM is client. 201 -cp <class search path of directories and 202
zip/jar files> 203 -classpath <class search path of 204 directories and zip/jar files> 205
A : separated list of directories, JAR 206 archives, 207
and ZIP archives to search for class 208 files. 209
-D<name>=<value> 210 set a system property 211
-verbose[:class|gc|jni] 212 enable verbose output 213
-version print product version and exit 214 -version:<value> 215
require the specified version to run 216 -showversion print product version and 217
continue 218 -jre-restrict-search | -jre-no-restrict-219
search 220
8
include/exclude user private JREs in the 221 version search 222
-? -help print this help message 223 -X print help on non-standard options 224 -ea[:<packagename>...|:<classname>] 225
-226 enableassertions[:<packagename>...|:<clas227
sname>] 228 enable assertions 229
-da[:<packagename>...|:<classname>] 230 -231
disableassertions[:<packagename>...|:<cla232 ssname>] 233
disable assertions 234 -esa | -enablesystemassertions 235
enable system assertions 236 -dsa | -disablesystemassertions 237
disable system assertions 238 gus@gusgus ~ $ java -version 239
java version "1.4.2-02" 240 Java(TM) 2 Runtime Environment, Standard 241
Edition (build Blackdown-1.4.2-02) 242 Java HotSpot(TM) Client VM (build 243 Blackdown-1.4.2-02, mixed mode) 244
gus@gusgus ~ $ 245 Usando Kaffe y Jikes 246
gus@gusgus ~ $ java -version 247 java full version "kaffe-1.4.2" 248
kaffe VM "1.1.6" 249 Copyright (c) 1996-2005 Kaffe.org project 250
contributors (please see 251 the source code for a full list of 252 contributors). All rights reserved. 253 Portions Copyright (c) 1996-2002 254 Transvirtual Technologies, Inc. 255
The Kaffe virtual machine is free 256 software, licensed under the terms of 257
the GNU General Public License. Kaffe.org 258 is a an independent, free software 259
9
community project, not directly 260 affiliated with Transvirtual 261
Technologies, 262 Inc. Kaffe is a Trademark of Transvirtual 263
Technologies, Inc. Kaffe comes 264 with ABSOLUTELY NO WARRANTY. 265
Engine: Just-in-time v3 Version: 1.1.6 266 Java Version: 1.4 267
Heap defaults: minimum size: 5 MB, 268 maximum size: unlimited 269
Stack default size: 256 KB 270 gus@gusgus ~ $ javac 271
Usage: javac <options> <source files> 272 where possible options include: 273 -g Generate all debugging info 274
-g:none Generate no debugging info 275 -g:{lines,vars,source} Generate only some 276
debugging info 277 -nowarn Generate no warnings 278
-verbose Output messages about what the 279 compiler is doing 280
-deprecation Output source locations 281 where deprecated APIs are 282
used 283 -classpath <path> Specify where to find 284
user class files 285 -sourcepath <path> Specify where to find 286
input source files 287 -bootclasspath <path> Override location 288
of bootstrap class files 289 -extdirs <dirs> Override location of 290
installed extensions 291 -d <directory> Specify where to place 292
generated class files 293 -encoding <encoding> Specify character 294
encoding used by source files 295 -source <release> Provide source 296
compatibility with specified release 297 -target <release> Generate class files 298
for specific VM version 299
10
-help Print a synopsis of standard 300 options 301
gus@gusgus ~ $ 302 gus@gusgus ~ $ jar 303
Sintaxis: jar {ctxu}[vfm0Mi] [archivo-304 jar] [archivo-manifest] [-C dir] 305
archivos ... 306 Opciones: 307
-c crear nuevo contenedor 308 -t mostrar contenido de contenedor 309
-x extraer archivos nombrados (o todos) 310 del contenedor 311
-u actualizar contenedor existente 312 -v generar salida detallada en salida 313
estándar 314 -f especificar nombre de archivo 315
contenedor 316 -m incluir información de manifest del 317
archivo manifest especificado 318 -0 solo almacenar; no utilizar compresión 319
ZIP 320 -M no crear un archivo manifest para las 321
entradas 322 -i generar información de índice para los 323
archivos jar especificados 324 -C cambiar al directorio especificado e 325
incluir el archivo siguiente 326 Si alguno de los archivos es un 327
directorio, se procesará de forma 328 recursiva. 329
Se deben especificar los nombres del 330 archivo manifest y del archivo contenedor 331 en el mismo orden en que se especifiquen 332
los indicadores 'm' y 'f'. 333 Ejemplo 1: para archivar dos archivos de 334
clase en un contenedor llamado 335 classes.jar: 336
jar cvf classes.jar Foo.class Bar.class 337 Ejemplo 2: utilizar un archivo manifest 338
existente, 'mymanifest', y archivar todos 339
11
los 340 archivos del directorio foo/ en 341
'classes.jar': 342 jar cvfm classes.jar mymanifest -C foo/ . 343
gus@gusgus ~ $ 344
Programación Orientada a Objetos 345
con Java 346
Como es sabido hay muchos lenguajes de 347 programación orientada a objetos POO que 348
tienen 349
muchas similitudes entre si, pero 350 puntualmente nos enfocaremos en Java, 351
utilizaremos para tal efecto un 352
modelo de fábrica de objetos, para introducir 353 los términos clase, objeto, método, propiedad, 354
estático, 355
dinámico, donde la fábrica de objetos será el 356
entorno de ejecución o JRE. 357 Ilustración 1: La fábrica de Objetos dentro de JRE 358
Descripción Empírica del 359
funcionamiento del entorno JRE 360
Como podemos ver en la imagen anterior la 361 fábrica de objetos utiliza memoria del sistema 362
para 363
fabricar los objetos, pero para fabricarlos 364 necesita la información pregrabada llamada 365
clases, las clases 366
son las que almacenan las propiedades y 367 métodos que contendrá un objeto. Un objeto 368
cambiará sus 369
propiedades o las propiedades de otros 370 objetos por medio de los métodos. Los 371
métodos que sólo pueden 372
12
ejecutarse cuando el objeto existe, son los 373
denominados dinámicos, y los métodos que 374
pertenecen a la 375 clase son denominados estáticos, porque 376
pueden ser llamados sin necesidad de la 377
existencia de un 378 objeto. 379
En el ejemplo tenemos dos objetos, Reloj y 380
Lámpara los cuales tienen métodos Cuerda e 381
Interruptor, que son los que cambiaran el 382 estado de las propiedades Hora e Iluminando. 383
La clase reloj, 384 podría tener un método estático llamado 385
poner_en_hora, para ajustar todos los relojes 386 fabricados. El 387
programa en ejecución inicia en un método 388 estático ya que no existen inicialmente objetos 389
en nuestro 390 programa, este método se llama main que se 391
define como: 392 static int main(String[] args){ 393
..... 394 } 395
Donde args es un vector o arreglo 396
unidimensional que contendrá los argumentos 397 que hayan sido 398
pasados al comando java después de las 399 órdenes y el nombre de la clase principal que 400
alojará este 401 método. El entorno de ejecución o la JVM 402
fabricará objetos de sistema que podrán ser 403 utilizados 404
13
llamando a métodos estáticos de clases 405
pertenecientes a la biblioteca de java. 406
RAM 407
Objeto 408
JVM Lámpara 409
Clase 410
Reloj 411
Clase 412
Lamp 413
Objeto 414
Reloj 415
Propiedad 416
Hora 417
Propiedad 418
Ilumina 419
Método 420
Interruptor 421
Método Cuerda 422
Programa en Ejecución 423
Nota: Java provee una documentación 424 completa en inglés de toda la biblioteca 425
incluida en 426
la versión de JRE o JDK, una buena 427
práctica es no utilizar las más avanzadas y 428
complejas funciones de la API (Application 429 Programing Interface) ya que al querer 430
14
iniciar nuestro programa en una versión 431
anterior que no tenga una biblioteca 432
actualizada, se pueden producir problemas 433 de métodos faltantes. 434
Herencia soportada por Java 435
Java no soporta herencia múltiple, es decir no 436 podemos fabricar un objeto más complejo con 437
dos 438 diferentes más simples, sino que sólo 439
podremos heredar objetos nuevos de un sólo 440
objeto padre, que 441 proveerá los métodos y propiedades básicas 442
que serán extendidas y/o ampliadas por el 443 nuevo objeto. Es 444
decir no podríamos tener un objeto Lámpara 445
Reloj que derive del objeto Lámpara y del 446 objeto Reloj, 447
sino que tendríamos que usar otros 448
mecanismos para proporcionar esa 449
funcionalidad, interfaces y 450 alojamiento de objetos. 451
Esto podría comprenderse como: 452
• Interfaces: Permiten que sean 453
implementadas por objetos para adquirir 454 comportamiento, pero el 455
comportamiento no es provisto por la interfaz, 456 sino que el programador debe proporcionar 457
una 458
manera eficaz de construir los métodos 459
definidos en dicha interfaz uno por uno. 460 Pueden 461
15
implementarse varias interfaces al mismo 462
tiempo, en todos los casos es necesario 463
codificar 464 funciones o métodos. 465
• Alojamiento: Podemos pensar que al objeto 466
Lámpara le insertamos en su interior un objeto 467 Reloj 468
entonces podemos llamar a los métodos del 469 Reloj que está en la Lámpara, esto lo veremos 470
más 471 adelante en algunos ejemplos. Ya no sería la 472 Lámpara Reloj, pero sería una Lámpara con 473
Reloj. 474
• Herencia: Nos permite crear un objeto nuevo 475 en base a uno existente, es una nueva clase 476
de 477 objeto, puede utilizar el alojamiento de otros 478
objetos como propiedades para adquirir 479
funcionalidad. 480
Tipos de datos Básicos 481
En todos los lenguajes de programación 482 existen tipos de datos básicos con los que se 483
realizarán las 484
operaciones matemáticas básicas y las 485 operaciones booleanas de verdadero o falso. 486
Tipo de Datos Alcance o Rango 487 int de -2147483648 a 2147483647 (4bytes ) 488
byte de -128 a 127 (1Byete) 489
short de -32768 a 32767 (2Bytes) 490
long de -9223372036854775808 a 491 9223372036854775807 (8Bytes) 492
16
char de '\u0000' a '\uffff', ambos incluidos que 493
es lo mismo que de 0 a 65535, 1 letra 494
boolean 0 o 1 (1bit) 495 float 4Bytes, punto flotante 496
double 8Bytes, punto flotante 497
String No es un tipo de datos básico, es un 498 objeto básico, con propiedades y métodos, 499
pero el lenguaje Java permite definir un nuevo 500 objeto con el delimitador (“), por 501
lo que podemos concatenar (unir) texto 502
utilizando el operador (+) con los 503 nombres de los objetos de tipo String y los 504
trozos de texto delimitados con (“). 505 Tabla 1: Tipos de datos básicos 506
Operadores y Delimitadores Básicos 507 Operador Datos Acción 508
+ String Une texto (concatenador). 509 número Suma. 510
- número invierte el signo del número. 511 número Resta. 512
* número Multiplica y tiene prioridad sobre la suma y 513 resta. 514
/ número Divide y tiene prioridad sobre la suma y resta. 515
% número Devuelve el resto de la división del operador 516 derecho por el izquierdo. 517
! booleano El operador NOT booleano. 518 ~ número Invierte bit por bit el operando de la derecha 519
& entero o 520 booleano 521
El operador AND, booleano bit por bit del elemento a la 522 izquierda contra el de la 523
derecha. 524 && Cualquier El operador AND condicional. 525
| entero o 526
17
booleano 527 El operador OR, booleano bit por bit del elemento a la 528
izquierda contra el de la 529 derecha. 530
|| Cualquier El operador OR condicional. 531
<< número Desplaza los bits hacia la izquierda la 532 cantidad de la derecha. 533
>> número Desplaza los bits hacia la derecha la 534 cantidad de la derecha. 535
>>> número Desplaza bits hacia la derecha pero no 536 conserva el signo. 537
== Cualquier El operador condicional de igualdad, 538 devuelve verdadero si derecha e izquierda es 539
lo mismo. 540 < Básicos Menor que, devuelve verdadero si izquierda 541
es menor que derecha. 542 <= Básicos Menor o igual que, devuelve verdadero si 543
izquierda es menor o igual que derecha. 544 > Básicos Mayor que, devuelve verdadero si izquierda 545
es mayor que derecha. 546 >= Básicos Mayor o igual que, devuelve verdadero si 547
izquierda es mayor o igual que derecha. 548 = Cualquier Asigna al elemento de la izquierda, el de la 549
derecha. 550 (op)= Básicos Hace la operación op [+,-,*,/.etc..] entre 551
los dos operandos y el resultado lo guarda 552 en el de la izquierda. 553
var++ Básicos Incrementa en uno la variable var. 554
var-- Básicos Decrementa en uno la variable var. 555 . objetos Separa los nombres de los objetos o 556 propiedades o métodos o nombres y jerarquía 557
de clases. 558 (int) tipo de datos 559
Convierte un tipo de datos a entero, si reemplazamos 560 int por una clase de objetos, 561
18
podemos siempre y cuando sea correcto convertir al 562 tipo de datos indicado entre 563
paréntesis. 564 ; Cualquier Termina una línea de orden. 565
, Cualquier Separa argumentos de un método o 566 función. 567
// Cualquier Empieza una línea de comentario. 568 /* */ Cualquier Delimitan un trozo de texto como 569
comentario. 570 /** */ Cualquier Delimitan un trozo de texto como 571
documentación para JavaDoc 572 Operador Datos Acción 573
{} Cualquier Delimitan un bloque de código de una 574 estructura de datos. 575
( ) Cualquier Asocia una operación teniendo prioridad, 576 o en caso de un método agrupa los 577 argumentos separados por comas. 578
Tabla 2: Operadores Básicos 579
Nombres de variables y funciones. 580
En Java los nombres de las variables y las 581
funciones siguen ciertas reglas, por ejemplo 582 las 583
variables se acostumbra a nombrarlas con 584 todas sus letras en minúsculas, las funciones 585
con la primer 586 palabra que la identifica en minúsculas y las 587
palabras siguientes con la primer letra en 588
mayúsculas y los 589 nombres de las Clases de objetos con la 590
primer letra de cada palabra que la define en 591
mayúsculas. 592
Ejemplos: 593 Variables 594 int soles=3; 595
19
char salir='q'; 596 Funciones: 597
public static int redondearPromedio(int[] valores){ 598 ... 599 } 600
Clases: 601 public class RelojAtomico{ 602
.... 603 } 604
II. Codificación Inicial y 605
Estructuras de Datos 606
Nota: En este capítulo veremos como 607 codificar y compilar el primer programa, a 608
continuación emplearemos los operadores 609 y tipos de datos básicos y por último 610
veremos las estructuras de datos básicas 611 soportadas por Java. 612
El primer programa 613
Suponemos que nuestro sistema operativo ya 614
tiene instalado el kit de desarrollo (JDK) y 615
procedemos a abrir un editor de texto de 616
nuestro gusto. En KDE, podemos abrir kwrite 617 en otros sistemas 618
busquemos block de notas u otro editor como 619 EditPlus, de todas maneras cualquier editor 620
estará bien. 621
Dentro del editor de textos escribiremos lo 622 siguiente: 623
public class HolaMundo { 624 public static void main(String[] args) { 625
System.out.println("Hola, mi primer programa"); 626 } 627 } 628
20
El archivo debe guardarse como 629 HolaMundo.java respetando las mayúsculas y 630
minúsculas, 631 necesitamos compilar el programa para 632 obtener el binario con extensión class, 633
entonces procedemos a 634 llamar al compilador con una consola de 635
comandos para poder después usar la JVM 636 (comando java) 637
para correr el programa, pero para trabajar 638
mejor haremos una carpeta donde 639 guardaremos los ejemplos, 640
para los que usen Windows háganla en la 641 unidad c:\ y nómbrenla ejemplos, para los que 642
usamos un 643
sistema mejor, en nuestra carpeta de usuario 644 y la llamamos ejemplos también sólo que en 645
minúsculas. 646 gus@gusgus ~ $ cd ejemplos 647
gus@gusgus ~/ejemplos $ javac 648 HolaMundo.java 649
gus@gusgus ~/ejemplos $ java HolaMundo 650 Hola, mi primer programa 651 gus@gusgus ~/ejemplos $ 652
Nota: Más adelante veremos como utilizar 653
un editor basado en Java para practicar 654 este 655
curso, antes de explicar línea por línea del 656 programa, es necesario introducir un tema 657
que será utilizado con mucha frecuencia, 658 estos son los paquetes, los cuales darán el 659
concepto de Clase Pública. 660
Paquetes 661
21
En el ejemplo anterior hemos omitido una 662
parte esencial de la programación en el 663
lenguaje Java, 664 estos son los Paquetes, se utilizan para 665
diferenciar una clase respecto de otras con el 666
mismo nombre, si 667 nos ponemos a pensar sobre la cantidad de 668
nombres diferentes de clases que podemos 669 poner a los tipos 670
de objetos en nuestros programas es infinita, 671
pero dos programadores diferentes pueden 672 llegar a usar dos 673
veces el mismo nombre para una misma 674 clase, de esta manera podemos hacer que 675
sólo las clases de 676
objetos que haremos visibles a otros 677 programadores o que ejecutarán el 678
componente principal del 679
programa (el método estático main) sean 680 públicas. 681
Las clases de objetos que no queramos hacer 682
visibles a otros componentes de nuestro 683 proyecto, 684
entonces se podrán declarar como privadas, 685 de esa manera sólo una clase de objetos que 686
pertenezca al 687
grupo de clases podrá acceder a las demás 688 privadas. 689
Los paquetes suelen tener un nombre 690
especial referente al de la organización que 691 realiza el 692
22
proyecto, esto es una sugerencia, en realidad 693
se puede utilizar casi cualquier nombre, así 694
que por 695 ejemplo si nuestra empresa es compunauta, y 696 el nombre de dominio de los servicios que se 697
proporcionan 698 en Internet es compunauta.com, entonces 699
nuestro paquete podría llamarse 700 com.compunauta y a su vez si 701
tenemos un subproyecto, este podríamos 702
nombrarlo como 703 com.compunauta.aprendiendojava, sólo 704
tengamos en cuenta que es el orden inverso 705 de como aparecería en Internet. Usamos 706
puntos para separar 707
los nombres y tenemos cuidado respecto de 708 las mayúsculas y minúsculas. 709
Nota: El lenguaje Java es sensible a las 710
mayúsculas y minúsculas, es decir si 711 tenemos el 712
nombre del paquete 713
com.compunauta.aprendiendojava no será 714 lo mismo si lo 715
escribimos como 716 com.compunauta.AprendiendoJava. De la 717
misma manera no es lo 718
mismo HolaMundo que holamundo. 719
Palabras clave o reservadas 720
Las palabras clave o reservadas son aquellas 721
que definen o se combinan con una definición 722 de 723
23
datos de una variable o propiedad, clase de 724 objetos o métodos, por ejemplo class es una 725
palabra clave y 726 nos indica que a continuación pondremos el 727
nombre a la clase de objeto que vamos a 728
crear, si queremos 729 que dicha clase pueda ser accedida desde 730
dentro o fuera de nuestro paquete de clases 731 de objetos, 732
entonces la definiremos como public (pública), 733
donde esta es otra palabra clave. 734 A veces las palabras claves son palabras 735
reservadas, por ejemplo goto es una palabra 736
clave 737 reservada en Java, ya que no tenemos 738
permitido saltar a una línea en particular de 739 nuestro programa, 740
tenemos que trabajar con llamadas a 741
funciones y otras maneras de codificación. 742 Tipos de datos 743
Definen tipos de datos que devolverán los 744
métodos o los tipos de datos que definirán una 745 propiedad básica. Estos ya los habíamos visto 746
anteriormente pero ahora los describiremos 747 por el espacio 748
que ocupan en memoria. 749 Palabra Clave Significado 750
boolean Valores Booleanos (1bit*) 751 byte 1Byte, número entero (8bits) 752 short 2Bytes, número entero 753 int 4Bytes, número entero 754 long 8Bytes, número entero 755 char 2Bytes, (short) 1Caracter 756
24
float 4Bytes, punto flotante. 757 double 8Bytes, punto flotante, doble precisión 758
void Cuando no hay nada que devolver 759 null Tipo de datos Nulo, vacío, cualquier operación 760
sobre null produce un error. 761 Tabla 3: Palabras claves - Tipos de datos 762
Permisos y declaración de clases, 763 propiedades o métodos. 764
Definen los permisos a un método o clase de 765
objetos, haciendo visible u oculto un método 766
propiedad o clase a otras clases de objetos u 767
otros objetos que quieran accederlas. 768 Palabra clave Significado 769
public Para una clase, que es accesible desde cualquier 770 parte, para un método, que es 771
accesible por cualquier método que pueda acceder a la 772 clase de objetos. Para que 773
una clase que deriva de otra tiene que ser pública la 774 clase de objetos padre para 775
poder ser accecible. 776 private Sólo se permite a la misma clase de objetos 777
acceder a sus propiedades o métodos. 778 protected Sólo se permite al paquete acceder a esta 779
clase. 780 package Define a que paquete pertenece una clase. 781
import Define que paquetes usaremos, para no escribir 782 el nombre completo de la clase a la 783
que hacemos referencia como: 784 com.compunauta.aprendiendojava.HolaMundo 785
class Inicia la declaración de una Clase (tipo de datos). 786 new Instancia un objeto, crea un objeto partiendo de 787
una clase en particular. 788 Tabla 4: Palabras clave - Permisos y Declaraciones 789
Bucles y tomas de decisión 790
Se utilizan para el control de bucles y tomas 791 de decisión en un programa, se utilizan 792
paréntesis () 793
25
para encerrar las condiciones, y llaves {} para 794
los bloques de datos 795 Palabra clave Significado 796
if (condicion){ 797 .... 798
} else { 799 .... 800 } 801
Ejecuta el bloque separado por {} siempre y cuando se 802 cumpla la condición, 803
acompañada a esta estructura existe else (sinó) que es 804 para el caso contrario a la 805
condición, sin tener que evaluar la condición negada. 806 for (inicial;condición;repetición){ 807
.... 808 } 809
Se ejecuta la sentencia inicial, y si se cumple la 810 condición se ejecuta el código en el 811
interior de la llaves, una vez que se termina se ejecuta 812 la repetición y se vuelve a 813
comparar la condición, mientras la condición sea cierta 814 el bloque encerrado entre 815
llaves se seguirá ejecutando. 816 while (condición){ 817
.... 818 } 819
Mientras se cumpla la condición entre paréntesis, se 820 ejecuta el código en el interior 821 de {} de manera infinita hasta. 822
switch (varieblenumérica){ 823 case num1: 824
..... 825 break; 826
case num2: 827 ..... 828
break; 829 default: 830
} 831
26
La sentencia switch es un tanto compleja y 832 probabilísticamente poco usada ya que 833
no puede usarse con objetos y las comparaciones son 834 primitivas, en algunos trozos 835
o segmentos de código es crucial para optimizar la 836 velocidad de nuestro programa, 837
de acuerdo al contenido de la variable numérica se 838 ejecuta la sentencia case que 839
coincida, cada bloque de código debe terminar con 840 break, ya que en caso contrario 841
se seguirá ejecutando la siguiente cláusula case, existe 842 una opción default que es 843
para cuando ninguno de los casos resulta ser el 844 correcto. 845
do{ 846 ... 847
}while(condición); 848 El bloque dentro de la palabra clave do, se ejecutará al 849
menos una vez y si la 850 condición de while se cumple, se repetirá mientras sea 851
cierta. 852 break Interrumpe un bloque y se ejecuta la siguiente 853
línea fuera de él. 854 continue Interrumpe el resto del código del bloque y 855
vuelve a empezar con la siguiente 856 iteración. 857
return Interrumpe el método entero y devuelve el tipo 858 de datos de la derecha al punto 859
donde se llamó a la función. 860 Tabla 5: Palabras Clave - Control de Flujos, tomas de 861
decisión 862 Reservadas 863
Palabra clave Significado 864 goto Palabra reservada en el lenguaje de programación 865
Java, no puede utilizarse pero el 866 compilador en ciertas ocasiones es capaz de generar 867
un comportamiento similar en 868 las optimizaciones, de tal manera que los binarios si 869
podrían estar utilizando este 870
27
tipo de salto a una etiqueta. 871 const Palabra reservada que no es utilizada por el 872
momento en Java. 873 Tabla 6: Palabras clave – Reservadas 874
Excepciones, control de errores 875
En casi todos los lenguajes de programación 876 existen mecanismos para actuar según 877
sucedan 878
errores de cualquier tipo, desde accesos al 879 disco hasta división por cero, los cuales de no 880
ser 881 manipulados por nuestro programa tendrán el 882
comportamiento por defecto de la máquina 883
virtual de java, 884 que es reportarlos como excepciones y 885
terminar el programa. 886 Palabra clave Significado 887
throws Indica que tipo de excepciones lanzará este 888 método en caso de errores, es útil para 889
que los métodos que llaman a este que lanzará una 890 excepción en caso de errores, se 891
vean obligados a tratar esa situación. 892 throw Transfiere el control de errores al manejador de 893
excepciones. 894 try{ 895 ... 896
}catch(tipo excepcion){ 897 ... 898
}finally{ 899 ... 900 } 901
Esta es la estructura de un manejador de excepciones 902 o control de errores, try inicia 903
el bloque de código que será manejado en caso de 904 errores, la sentencia catch indica 905
el tipo de excepción que se capturará, esta última 906 puede repetirse para hacer cosas 907
28
diferentes de acuerdo por ejemplo si el problema fue 908 una división por cero o un 909
error de acceso de disco. La sentencia finally se 910 ejecutará de todas maneras al salir 911
del código. 912 Si una excepción no es capturada por el listado de 913
cláusulas catch, entonces es 914 probable que la JVM inicie el reporte y la salida de la 915
instancia completa de la 916 JVM, interrumpiendo todos los hilos de ejecución. 917
Tabla 7: Palabras clave - Control de errores 918
Secuencias de escape 919
Las secuencias de escape son aquellas 920 combinaciones de caracteres que nos 921
permiten insertar un 922 caracter especial que no es posible tipear con 923
el teclado estándar o que no es posible utilizar 924 porque 925
denota un trozo de texto, por ejemplo las 926
comillas dobles en el ejemplo hola mundo que 927
están dentro de 928 la función println. 929
System.out.println("Hola, mi primer programa"); 930 Si quisiéramos incluir las comillas dobles en la 931
ejecución deberíamos incluirlas con una 932
secuencia 933 de escape, para ello se utiliza la barra 934
invertida \ seguida de las comillas dobles \”. 935 System.out.println("\”Hola, mi primer programa\”"); 936
De esa manera el compilador entiende que el 937
trozo de texto contendrá las comillas dobles, 938
pero 939
29
que pasaría si quisiéramos escribir el caracter 940
\ que en algún sistema operativo distinto de 941
Linux podría 942 significar división de directorios o carpetas, 943
bueno para esto usaríamos una \ seguida de 944
otra \, es decir \\ 945 para insertar el caracter \. 946
System.out.println("Hola, mi primer programa, está en 947 c:\\"); 948
Aquí hay una lista de las secuencias de 949
escape más usadas y una breve explicación 950 de su utilidad, 951
ya que Java soporta Unicode, una 952
representación extensa de lo que es un 953 caracter que permite inclusión 954
de varios idiomas. 955 Secuencia Significado 956
\b Retroceder un espacio (backspace) 957 \t Tabulador Horizontal, sirve para alinear texto en la 958
salida estándar de datos cuando 959 es una terminal o consola de comandos. 960
\n Salto de línea, es el caracter usado incluso en las 961 viejas impresoras que necesitaban 962
avanzar de línea para escribir en el próximo renglón. 963 \r Retorno de carro, es el caracter que devuelve el 964
cursor o el cabezal de la imprezora 965 al inicio del renglón, Linux, usa \n para un nuevo 966
renglón en los archivos de texto, 967 Windows utiliza una combinación \n\r. 968
\” Insertan las comillas dobles 969 \' Insertan la coma simple. 970
\\ Insertan la misma barra invertida que usamos como 971 escape. 972
\DDD Las tres D son dígitos y representan un caracter 973 en su versión octal. 974
30
\uDDDD Las cuatro D son dígitos y representan un 975 caracter unicode en hexadecimal. 976
Concatenación y conversiones a 977
texto 978
La concatenación de texto se denomina a la 979
unión de trozos o fragmentos de textos y 980 comúnmente 981
se utiliza la conversión de números o de 982 objetos a su representación en texto, Java 983
convierte 984
automáticamente los tipos de datos básicos a 985 texto antes de unirlos y llama por cada objeto 986
al método 987 especial toString() para realizar la conversión 988 de objetos nuestros o de la biblioteca de la 989
JVM. 990 Veamos un ejemplo: 991
1. public class SumaSimple { 992 2. public static void main(String[] args) { 993
3. int a=1; 994 4. System.out.println("el valor de a="+a); 995
5. a=a+10; 996 6. System.out.println("ahora sumándole 10 es a="+a); 997
7. } 998 8. } 999
En la línea 1, definimos el nombre de la clase, 1000 que es pública y se llama SumaSimple, en la 1001
segunda línea definimos el método estático 1002 main que es el que la JVM ejecutará para 1003
iniciar nuestros 1004 programas. 1005
Nota: El arreglo o vector args se utiliza 1006 para recibir todas las órdenes de la JVM, 1007
los 1008
31
vectores en Java son objetos que tienen 1009
propiedades. 1010
En la línea 3, se define una variable de tipo 1011 entero llamada “a” que inicialmente guardará 1012
un 1 1013
positivo, la 4ta línea ejecuta el método 1014 println(String line) que pertenece al objeto out 1015
que a su vez es 1016 propiedad del objeto System, tener un objeto 1017
de salida, se imprimirá en pantalla el trozo de 1018 texto “el 1019
valor de a=” seguido del valor (el contenido de 1020
a). 1021 En la línea 5, al contenido de la variable a, le 1022 agregamos el resultado de sumar a+10, eso 1023
no tiene 1024 que dar un total de 11 que se verá reflejado en 1025
la línea 6, cuando volvemos a llamar al 1026 método println 1027
del objeto out que pertenece al objeto System. 1028
En las líneas 7 y 8 se cierran las llaves que 1029
iniciaron los bloques de código del método 1030 main o la 1031
declaración de la clase SumaSimple. 1032
Nota: Sólo como comentario lo que en 1033
realidad el compilador está haciendo al 1034
llamar a 1035 println, es concatenar texto, para ello es 1036
necesario convertir el número en texto, 1037
internamente el compilador estará 1038 llamando a una clase que es parte de la 1039
biblioteca 1040
32
cuyo nombre es Integer y posee un método 1041
toString() que convertirá el número, a su 1042
vez, el trozo de texto pertenecerá a la 1043 propiedad de un objeto String el cual tiene 1044
un 1045
método concat() que es el encargado de 1046 producir un nuevo objeto igual a la suma 1047
de 1048 los dos trozos de texto. 1049
El ejemplo podría escribirse así: 1050 1. public class SumaSimple2 { 1051
2. public static void main(String[] args) { 1052 3. int a=1; 1053
4. System.out.println("el valor de 1054 a=".concat(Integer.toString(a))); 1055
5. a=a+10; 1056 6. System.out.println("ahora sumándole 10 es 1057
a=".concat(Integer.toString(a))); 1058 7. } 1059 8. } 1060
Donde se ha reemplazado la concatenación 1061 del compilador por su equivalente, 1062
recordemos que no es 1063 necesario hacer esto, vemos que después de 1064
las comillas dobles encontramos un punto, 1065 eso es porque de 1066
esa manera se representa un objeto String, 1067
cualquier trozo de texto entre comillas dobles 1068 es un objeto 1069
String y tiene propiedades y el punto separa 1070
objetos de otros objetos, propiedades o 1071 métodos. 1072
33
Nota: Las líneas que no empiezan con 1073
número representan la continuación de la 1074
anterior 1075 que por cuestiones de espacio no entra en 1076
la misma línea, esa representación es la 1077
misma que en muchos editores de código, 1078 al guardarse estos archivos se guardarán 1079
como una única línea, sin importar cuantos 1080 renglones sean necesarios para ver todo 1081
su contenido. 1082
En ambos casos la salida por pantalla será la 1083 misma y la siguiente: 1084
gus@gusgus ~ $ cd ejemplos 1085 gus@gusgus ~/ejemplos $ javac 1086
SumaSimple.java 1087 gus@gusgus ~/ejemplos $ java SumaSimple 1088
el valor de a=1 1089 ahora sumándole 10 es a=11 1090
gus@gusgus ~/ejemplos $ javac 1091 SumaSimple2.java 1092
gus@gusgus ~/ejemplos $ java SumaSimple2 1093 el valor de a=1 1094
ahora sumándole 10 es a=11 1095 gus@gusgus ~/ejemplos $ 1096
Salida por pantalla y entrada por 1097
teclado 1098
Para los siguientes ejemplos ya tenemos casi 1099 todo discutido, excepto que por cuestiones 1100
educativas sería interesante que el programa 1101
no solo contenga los valores que interactuarán 1102
almacenados, sino que también sea posible 1103 preguntar al usuario. 1104
System.out 1105
34
El objeto System es parte de la biblioteca de 1106
Java y es instanciado o fabricado al iniciar la 1107
JVM 1108 mucho antes que se comience a ejecutar 1109
nuestro programa. Este almacena 3 objetos, 1110 son out, in y err. 1111
El objeto out es del tipo o clase Printstream 1112
que tiene las siguientes propiedades y 1113 métodos 1114
importantes, no listaremos todos: 1115
Resumen de Métodos 1116
boolean checkError() 1117
Envía todo el buffer y devuelve verdadero si 1118 hay error o falso. 1119
void close() 1120 Cierra el flujo de datos 1121
void flush() 1122
Envía todo el buffer. 1123
void print(boolean b) 1124 Imprime una variable booleana 1125
void print(char c) 1126
Imprime un caracter. 1127 void print(char[] s) 1128
Imprime un arreglo de caracteres. 1129 void print(double d) 1130
Imprime un numero de tipo double. 1131
void print(float f) 1132 Imprime un número de punto flotante. 1133
void print(int i) 1134 Imprime un entero. 1135
void print(long l) 1136 Imprime un entero largo. 1137
35
void print(Object obj) 1138
Imprime un objeto, invocando su función 1139
toString() 1140 void print(String s) 1141
Imprime un objeto de tipo String 1142
void println() 1143 Imprime una separador de nueva línea. 1144
void println(boolean x) 1145 Imprime un valor booleano y termina la línea. 1146
void println(char x) 1147
Imprime un caracter y termina la línea. 1148 void println(char[] x) 1149
Imprime un arreglo de caracteres y termina la 1150 línea. 1151
void println(double x) 1152
Imprime un número de precisión doble y 1153 termina la línea. 1154
void println(float x) 1155
Imprime un número de punto flotante y 1156 termina la línea. 1157
void println(int x) 1158
Imprime un entero y termina la línea. 1159 void println(long x) 1160
Imprime un entero largo y termina la línea. 1161 void println(Object x) 1162
Imprime un objeto invocando su método 1163
toString() y termina la línea. 1164 void println(String x) 1165
Imprime un trozo de texto y termina la línea. 1166 Tabla 8: Resumen de métodos importantes para out. 1167
System.in 1168
36
El objeto in que es una propiedad de System 1169
es de la clase o tipo InputStream, que también 1170
es 1171 parte de la biblioteca de Java. Aquí vemos los 1172
métodos que nos interesan. 1173
Resumen de Métodos 1174
int available() 1175
Devuelve la cantidad de bytes que se pueden 1176
leer (o pasar por alto) desde esta 1177
entrada sin bloquear la próxima llamada a 1178 lectura. 1179
void close() 1180
Cierra esta entrada de datos y libera todos los 1181 recursos asociados. 1182
abstract 1183 int 1184
read() 1185
Lee el próximo byte de datos desde la 1186
entrada, espera por los datos. 1187
int read(byte[] b) 1188 Lee de la entrada los bytes que llenan el 1189
arreglo b, devuelve la cantidad de bytes que 1190
se almacenaron. 1191
int read(byte[] b, int off, int len) 1192 Lee hasta len bytes de datos adentro del 1193
arreglo de bytes b empezando en off. 1194 long skip(long n) 1195
Salta y destrulle los n caracteres de datos. 1196 Tabla 9: Resumen de métodos importantes del tipo de 1197
objetos in. 1198
System.err 1199
37
Este objeto es del mismo tipo que out 1200
(Printstream) y tiene las mismas propiedades, 1201
en los 1202 sistemas operativos derivados de Unix como 1203 ser Linux, existe mucho la diferencia entre 1204
salida estándar 1205 de datos (System.out) y la salida estándar de 1206
errores (System.err), por ejemplo al imprimir 1207 todos los 1208
carteles de errores en un tipo de salida no 1209
afectaríamos a los resultados, un ejemplo 1210 sería el siguiente: 1211
public class SumaSimple3 { 1212 public static void main(String[] args) { 1213
int a=1; 1214 System.err.println("el valor de a="+a); 1215
System.out.println(a); 1216 a=a+10; 1217
System.err.println("ahora sumándole 10 es a="+a); 1218 System.out.println(a); 1219
} 1220 } 1221
Si este código lo compilamos al ejecutarlo 1222 podemos separar los comentarios de los 1223
valores de a. 1224 gus@gusgus ~ $ cd ejemplos 1225
gus@gusgus ~/ejemplos $ javac 1226 SumaSimple3.java 1227
gus@gusgus ~/ejemplos $ java SumaSimple3 1228 el valor de a=1 1229
1 1230 ahora sumándole 10 es a=11 1231
11 1232 gus@gusgus ~/ejemplos $ java SumaSimple3 1233
> resultados.txt 1234 el valor de a=1 1235
38
ahora sumándole 10 es a=11 1236 gus@gusgus ~/ejemplos $ java SumaSimple3 1237
2> errores.txt 1238 1 1239 11 1240
gus@gusgus ~/ejemplos $ 1241
De esa manera generamos y almacenamos 1242
por separado los errores y los resultados. 1243 Nota: Es muy buena práctica 1244
acostumbrarse a separar los datos de 1245
errores a cada flojo de 1246 datos err y out, ya que si el flujo fuera un 1247
protocolo de comunicación mezclaríamos 1248 los datos con los errores. 1249
System.exit(int cod); 1250
El método estático exit(cod) de la clase 1251
System interrumpe la ejecución total del 1252 programa y 1253
devuelve el control al sistema operativo, es 1254
decir la JVM termina por completo liberando 1255 los recursos. 1256
Un código de salida igual a cero es 1257
considerado como una ejecución satisfactoria 1258 del programa, un 1259
código diferente a este, se considera un error 1260 y sirve para que el sistema operativo u otro 1261
programa que 1262
llame al nuestro sepa de alguna manera que 1263 ocurrió. 1264
Leer líneas de la entrada estándar. 1265
Para leer líneas de la entrada estándar 1266 podemos utilizar una combinación de objetos 1267
de la 1268
39
biblioteca que nos permitirán simplemente 1269
esperar a que el usuario ingrese texto y 1270
presione enter, o 1271 podemos codificar la lectura secuencial de 1272
caracteres uno en uno hasta que se detecte 1273
un salto de línea, 1274 tengamos en cuenta que java es 1275
multiplataforma, y si el sistema operativo no es 1276 Linux, es probable que 1277
se introduzca más de un caracter para el salto 1278
de línea lo cual incrementa la complejidad del 1279 problema. 1280
1. package com.compunauta.aprendiendojava; 1281 2. import java.io.*; 1282
3. public class LeerRenglones { 1283 4. public static void main(String[] args) { 1284
5. BufferedReader br=new BufferedReader(new 1285 InputStreamReader(System.in)); 1286
6. System.out.println("Hola, ingresa tu nombre"); 1287 7. String nombre; 1288
8. try {nombre = br.readLine();} 1289 9. catch (IOException ex) 1290
{ex.printStackTrace();System.exit(-1);} 1291 10. System.out.println("Hola, "+nombre+" ten un buen 1292
día"); 1293 11. System.exit(0);} 1294
12.} 1295 Nota: Queda como ejercicio para el lector 1296
ver los métodos y propiedades de la 1297
documentación de la api proporcionada 1298 por Sun Microsystems (java.sun.com) para 1299
las clases BufferedReader, 1300 InputStreamReader y Exception. 1301
Crear Objetos (de la biblioteca de 1302
Java) 1303
40
En java para crear objetos utilizamos una 1304
palabra clave, new, esta misma crea un objeto 1305
del tipo 1306 indicado a su derecha, repasemos del ejemplo 1307
anterior la siguiente línea: 1308 BufferedReader br=new BufferedReader(new 1309
InputStreamReader(System.in)); 1310 La clase BufferedReader, pertenece a la 1311
biblioteca de Java “java.io” la cual fue 1312
importada antes de la 1313 declaración de la clase LeerRenglones, 1314
InputStreamReader, pertenece a la misma 1315 biblioteca. 1316
Nota: En este punto, estamos utilizando y 1317 creando objetos pertenecientes a la 1318
biblioteca, 1319 como podemos ver la declaración de 1320 nuestra clase LeerRenglones no tiene 1321
propiedades ni métodos dinámicos que 1322
puedan llegar a ser métodos de algún 1323
objeto, 1324
sólo el método estático main que es el que 1325 nos permite iniciar la ejecución de código. 1326
También podríamos haber usado 1327 DataInputStream. 1328
Veamos que significa cada parte de esta 1329 línea, el concepto de “BufferedReader br=” es 1330
una 1331
asignación y una declaración simultánea, 1332 como vimos antes el signo “=” asigna a la 1333
variable u nombre 1334
41
de objeto de la izquierda el contenido de la 1335 derecha. Eso quiere decir que “br” será una 1336
variable que 1337 apuntará a un objeto del tipo BufferedReader, 1338
br no será un objeto, será el nombre con el 1339
que 1340 accederemos al objeto en memoria ram, si en 1341
la siguiente línea repitiéramos otra asignación 1342 a br, es 1343
decir “br=....” sin la declaración porque ya se 1344
sabe que es del tipo BufferedReader, 1345
entonces la variable 1346 br apuntará a otro objeto del tipo 1347
BufferedReader, el anterior sigue existiendo 1348
en memoria, pero será 1349
eliminado en la próxima ejecución del 1350 recolector de basura de la JVM. 1351
Cada vez que se crea un objeto nuevo el 1352
nombre de la clase se utiliza como el de una 1353 función, en 1354
realidad esta función especial es el método 1355
llamado constructor de la clase que es el que 1356 fabricará e 1357
inicializará de acuerdo a las variables que 1358 recibe como argumentos uno nuevo del tipo 1359
de su clase. Esto 1360
lo veremos más adelante, por el momento 1361 sólo haremos mención de que el objeto 1362
BufferedReader, 1363
necesita otro objeto que no es del tipo 1364 InputStream como lo es el objeto System.in, 1365
En cambio necesita 1366
42
uno del tipo InputStreamReader, que es el que 1367
es capaz de transformar un objeto 1368 InputStream, en 1369
InputStreamReader que es requerido para que 1370 el constructor de BufferedReader fabrique un 1371
objeto 1372 BufferedReader, a partir de uno 1373
InputStreamReader. 1374
Nota: Todo este procedimiento tiene el 1375
único fin de tener una variable llamada br 1376
que 1377 apunta a un objeto de tipo BufferedReader 1378
que es capaz de leer líneas desde la 1379 entrada, como lo construimos con la 1380
entrada del teclado, nos leerá los 1381
renglones que 1382 pretendíamos sin codificar la entrada del 1383
salto de línea. 1384
El bloque de control de errores, 1385
try{}catch(){} 1386
Como podemos ver en este ejemplo 1387 utilizamos la estructura de control de errores 1388
que es 1389 obligatoria para esa conversión que hicimos 1390
para poder leer líneas con el método 1391
readLine(), la 1392 estructura try{} encierra entre las llaves el 1393
código que puede producir una excepción (un 1394
error grave) 1395 que debe ser manejado por el bloque 1396
catch(Exception ex){}, en este caso solo 1397
capturamos la excepción 1398
43
que puede surgir y cualquier otra que no sea 1399
IOException no será capturada. 1400 try {nombre = br.readLine();} 1401
catch (IOException ex) {ex.printStackTrace();} 1402 Catch captura un tipo de error dentro del 1403
bloque try{}, y el bloque encerrado entre llaves 1404 ejecutará 1405
código que debería manejar la excepción, en 1406
este caso ignoramos todo tipo de acción que 1407
podríamos 1408 llevar a cabo y usamos la variable ex del tipo 1409
IOException para imprimir en pantalla los 1410
errores con el 1411 método printStackTrace de dicho objeto. 1412
Ejercicios 1413
En esta y todas las secciones de ejercicios 1414 veremos la solución a uno o dos, y el resto 1415
quedarán 1416 para ejercitación del lector, en el material 1417
multimedia que se adjunta con este libro tal 1418 vez se encuentren 1419
otras soluciones a los demás problemas. 1420
2.1. Entrada de Datos y 1421
conversiones. [if, try, catch] 1422
Preguntar el nombre del usuario y su edad, 1423 mostrar cuantos años tendría en una década 1424
más y 1425
clasificar según su edad en A[0-25], B[26-50], 1426
C[51-...]. La salida por pantalla debería ser 1427
algo como la 1428 siguiente: 1429 Nombre:? 1430 Gustavo 1431
44
Edad:?29 1432 Usuario Gustavo de Categoría B, en una 1433
década tendrá 39 años. 1434
Nota: Al preguntar por el nombre el cursor 1435
debe quedar debajo y al preguntar por la 1436 edad 1437
junto, utilizar la estructura try{ }catch(){ } y 1438
los bloques if(){ }. También buscar en la 1439 documentación de la API los métodos 1440
parseInt( ) de la clase Integer. 1441 Solución: 1442
1. package com.compunauta.aprendiendojava; 1443 2. import java.io.*; 1444
3. /** 1445 4. * <p>Título: Aprendiendo Java</p> 1446
5. * <p>Descripción: Ejemplos del Libro Aprendiendo 1447 Java de Compunauta</p> 1448
6. * <p>Copyright: Copyright (c) 2006 1449 www.compunauta.com</p> 1450
7. * <p>Empresa: COMPUNAUTA</p> 1451 8. * @author Gustavo Guillermo Pérez 1452
9. * @version 2006.01.01 1453 10. */ 1454 11. 1455
12.public class Cap2Ej1 { 1456 13. public static void main(String[] args) { 1457
14. //Definimos el objeto br para leer líneas de la 1458 entrada 1459
15. BufferedReader br=new BufferedReader(new 1460 InputStreamReader(System.in)); 1461
16. //Definimos variables nombre, edad y categoría 1462 dándole valores por 1463
defecto 1464 17. String nombre=""; 1465
18. int edad=0; 1466 19. char categoria='A'; 1467
20. //Iniciamos el bloque que podrá producir errores 1468
45
21. try { 1469 22. System.out.println("Nombre:?"); 1470
23. nombre = br.readLine(); 1471 24. System.out.print("Edad:?"); 1472
25. edad=Integer.parseInt(br.readLine());} 1473 26. //capturamos cualquier excepción que se pueda 1474
producir y la reportamos 1475 27. catch (Exception ex) 1476
{ex.printStackTrace(System.err);System.exit(-1);} 1477 28. //Como por defecto la categoría es A, revisamos si 1478
aumentamos a B o C 1479 29. if(edad>25){categoria='B';} 1480 30. if(edad>50){categoria='C';} 1481
31. //Imprimimos en pantalla la respuesta solicitada 1482 32. edad+=10; 1483
33. System.out.println("El usuario "+nombre+" de 1484 categoría "+categoria+" en 1485
una década tendrá "+edad+ " años"); 1486 34. System.exit(0); 1487 35. }//final de main 1488
36.}//final de la clase 1489 Comentarios: 1490
Capturamos Exception, porque pueden 1491
producirse dos tipos de errores, uno el de 1492 IOException, 1493
como vimos en el ejemplo de lectura de 1494 renglones de este capítulo y el otro al ingresar 1495
texto en vez de 1496 un número. Utilizamos System.exit(-1); para 1497
salir del programa inesperadamente. Es 1498
conveniente que el 1499 alumno reemplace la doble creación de 1500
objetos por la de DataInputStream, que para 1501
nuestro caso es el 1502
46
mismo comportamiento, pero tengamos en 1503 cuenta que la función readLine() de 1504
DataInputStream no está 1505
recomendada por los nuevos kits de desarrollo 1506 solo existe por compatibilidad. 1507
2.2 NumberFormatException 1508
while(){} 1509
Basados en el enunciado del ejemplo anterior, 1510 capturar correctamente los errores de entrada 1511
de 1512 datos respecto de los de conversión de texto 1513
en números. Imprimir en pantalla con 1514 printStackTrace, para 1515
el caso de entrada, y avisar al usuario que la 1516
edad no fue ingresada correctamente. 1517 Idea: Utilizar un bloque while para forzar al 1518 usuario a ingresar denuevo su nombre y 1519
edad 1520
si se detecta un error. 1521
2.3 Mezcla de bucles do{} while(); y 1522
for(;;){} 1523
Pedir por teclado el nombre al usuario, y a 1524 continuación solicitar 10 puntuaciones de 1525
supuestos 1526
exámenes, para promediarlos, la salida por 1527
pantalla debería ser algo así: 1528 Nombre?César 1529 Examen 1? 10 1530 Examen 2? 7 1531
Examen 4? 8.5 1532 .... 1533
Examen 10? 9.3 1534 César, tu promedio es de 8.93 1535
47
Nota: Utilizar variables que permitan 1536
almacenar decimales, revisar en la 1537
documentación las 1538 otras Clases que proveen métodos de 1539 conversión con decimales de texto a 1540
números. Y 1541 Buscar en la clase Math, los métodos 1542
estáticos que permitan redondear los 1543 decimales. 1544
Y por supuesto repetir el ingreso de los 1545
Exámenes que que hayan sido ingresados 1546 incorrectamente. 1547
Solución: 1548 1. package com.compunauta.aprendiendojava; 1549
2. import java.io.*; 1550 3. /** 1551
4. * <p>Título: Aprendiendo Java</p> 1552 5. * <p>Descripción: Ejemplos del Libro Aprendiendo 1553
Java de Compunauta</p> 1554 6. * <p>Copyright: Copyright (c) 2006 1555
www.compunauta.com</p> 1556 7. * <p>Empresa: COMPUNAUTA</p> 1557 8. * @author Gustavo Guillermo Pérez 1558
9. * @version 2006.01.01 1559 10. */ 1560 11. 1561
12.public class Cap2Ej3 { 1562 13. public static void main(String[] args) { 1563
14. //Definimos el objeto br para leer líneas de la 1564 entrada 1565
15. BufferedReader br=new BufferedReader(new 1566 InputStreamReader(System.in)); 1567
16. //Definimos variables nombre, error y acumulador 1568 dándole valores por 1569
defecto 1570 17. String nombre=""; 1571
48
18. float acumulador=0; 1572 19. boolean error; 1573
20. //Iniciamos el bloque que podrá producir errores, 1574 sólo para el nombre 1575
21. try { 1576 22. System.out.println("Nombre:?"); 1577
23. nombre = br.readLine();} 1578 24. catch (Exception ex) 1579
{ex.printStackTrace(System.err);} 1580 25. //iniciamos una iteración del 0 al 9 1581
26. for(int i=0;i<10;i++){ 1582 27. error=false; 1583
28. //iniciamos el bloque do{} while(); que se repetirá en 1584 caso de error 1585
29. do{ 1586 30. error=false; 1587
31. //iniciamos el bloque try que podrá dar error de 1588 conversión numérica 1589
32. try{ 1590 33. //ponemos i+1 entre (), caso contrario se 1591
concatenarán como texto 1592 34. System.out.print("Examen "+(i+1)+"? "); 1593
35. acumulador+=Float.parseFloat(br.readLine()); 1594 36. }catch(NumberFormatException 1595
ex){System.out.println("Error, ingresar 1596 denuevo");error=true;} 1597 37. catch(IOException 1598
ex){ex.printStackTrace();System.exit(-1);} 1599 38. }while (error); 1600
39.} 1601 40. //Tenemos lista la suma parcial y calculamos su 1602
promedio. 1603 41. acumulador/=10; 1604
42. //Redondeamos el resultado a dos digitos. 1605 43.acumulador=(float)Math.round(acumulador*100)/1001606
; 1607 44. System.out.println(nombre+", tu promedio es de: 1608
"+acumulador); 1609 45. System.exit(0); 1610
49
46.} 1611 47.} 1612
2.4 Switch Select 1613
Hacer un programa que utilice la estructura 1614 switch() para mostrar una frase de acuerdo a 1615
un 1616 número, pedir por teclado un número del 1 al 1617
10, exigir que no se pase de esos valores, 1618
capturar errores 1619
y repetir hasta que se introduzca el 0 que será 1620
que sale del programa. Las frases inventarlas. 1621
Práctica Complementaria Resuelta 1622
(sin procedimientos, sin arreglos) 1623
Esta práctica se añadió con el objeto de que el 1624 alumno cuente con problemas resueltso para 1625
practicar la sintaxis del lenguaje, están 1626 resueltos y no utilizan bucles ni arreglos (que 1627
los veremos en el 1628
próximo capítulo). 1629
P.C.E1 1630 1. package com.compunauta.aprendiendojava.ex; 1631
2. import java.io.BufferedReader; 1632 3. import java.io.InputStreamReader; 1633
4. import java.io.IOException; 1634 5. 1635
6. /** 1636 7. * <p>Título: Aprendiendo Java</p> 1637
8. * <p>Descripción: Ejemplos del Libro Aprendiendo 1638 Java de Compunauta</p> 1639
9. * <p>Copyright: Copyright (c) 2006 1640 www.compunauta.com</p> 1641
10. * <p>Empresa: [email protected]</p> 1642 11. * @author Julio César Duarte 1643
12. * @version 2006.01.01 1644 13. */ 1645
50
14. 1646 15.public class Comp0Ej1 { 1647
16. /** 1648 17. * Ejercicio1: Un programa que carga por teclado dos 1649
números y obtiene y 1650 18. * muestra la suma de ambos 1651
19. */ 1652 20. 1653
21. public static void main(String[] args) { 1654 22. int numero1 = 0; 1655 23. int numero2 = 0; 1656
24. int resultado; 1657 25. BufferedReader br = new BufferedReader(new 1658
InputStreamReader(System.in)); 1659 26. System.out.print("Ingrese el primer numero: "); 1660
27. try { 1661 28. numero1 = Integer.parseInt(br.readLine()); 1662
29. } 1663 30. catch (IOException e) { 1664
31. e.printStackTrace(System.err); 1665 32. System.out.println("el programa se debe finalizar"); 1666
33. System.exit( -1); 1667 34. } 1668
35. catch (Exception e) { 1669 36. e.printStackTrace(System.err); 1670
37. System.out.println("Error imprevisto"); 1671 38. System.exit( -1); 1672
39. } 1673 40. System.out.print("Ingrese el segundo numero: "); 1674
41. try { 1675 42. numero2 = Integer.parseInt(br.readLine()); 1676
43. } 1677 44. catch (IOException e) { 1678
45. e.printStackTrace(System.err); 1679 46. System.out.println("el programa se debe finalizar"); 1680
47. System.exit( -1); 1681 48. } 1682
49. catch (Exception e) { 1683 50. e.printStackTrace(System.err); 1684
51
51. System.out.println("Error imprevisto"); 1685 52. System.exit( -1); 1686
53. } 1687 54. resultado = numero1 + numero2; 1688
55. System.out.print("El resultado es: " + resultado); 1689 56. } 1690 57. } 1691
P.C.E2 1692 1. package com.compunauta.aprendiendojava.ex; 1693
2. import java.io.BufferedReader; 1694 3. import java.io.InputStreamReader; 1695
4. import java.io.IOException; 1696 5. 1697
6. /** 1698 7. * <p>Título: Aprendiendo Java</p> 1699
8. * <p>Descripción: Ejemplos del Libro Aprendiendo Java de 1700 Compunauta</p> 1701
9. * <p>Copyright: Copyright (c) 2006 1702 www.compunauta.com</p> 1703
10. * <p>Empresa: [email protected]</p> 1704 11. * @author Julio César Duarte 1705
12. * @version 2006.01.01 1706 13. */ 1707 14. 1708 15. 1709
16.public class Comp0Ej2 { 1710 17. /** 1711
18. * Ejercicio2: Un programa que carga por teclado el 1712 nombre de una persona y le 1713
19. * muestra un saludo 1714 20. */ 1715 21. 1716
22. public static void main (String[] args) 1717 23. { 1718
24. String nombre=new String(""); 1719 25. BufferedReader br=new BufferedReader(new 1720
InputStreamReader(System.in)); 1721 26. System.out.print("Ingrese su nombre: "); 1722
27. try 1723 28. { 1724
52
29. nombre=br.readLine(); 1725 30. } 1726
31. catch(IOException e) 1727 32. { 1728
33. e.printStackTrace(System.err); 1729 34. System.out.println("el programa se debe 1730
finalizar"); 1731 35. System.exit(-1); 1732
36. } 1733 37. System.out.println("Hola "+nombre); 1734
38. } 1735 39. } 1736
P.C.E3 1737 1. package com.compunauta.aprendiendojava.ex; 1738
2. import java.io.BufferedReader; 1739 3. import java.io.InputStreamReader; 1740
4. import java.io.IOException; 1741 5. 1742
6. /** 1743 7. * <p>Título: Aprendiendo Java</p> 1744
8. * <p>Descripción: Ejemplos del Libro Aprendiendo 1745 Java de Compunauta</p> 1746
9. * <p>Copyright: Copyright (c) 2006 1747 www.compunauta.com</p> 1748
10. * <p>Empresa: [email protected]</p> 1749 11. * @author Julio César Duarte 1750
12. * @version 2006.01.01 1751 13. */ 1752 14. 1753
15.public class Comp0Ej3 { 1754 16. /** 1755
17. * Ejercicio3: Dado el valor de los tres lados de un 1756 triángulo, calcular el 1757
18. * perímetro 1758 19. */ 1759 20. 1760
21. public static void main(String[] args) { 1761 22. int lado1 = 0; 1762 23. int lado2 = 0; 1763
53
24. int lado3 = 0; 1764 25. int perimetro; 1765
26. BufferedReader br = new BufferedReader(new 1766 InputStreamReader(System.in)); 1767
27. System.out.print("Ingrese el primer lado del 1768 triangulo: "); 1769
28. try { 1770 29. lado1 = Integer.parseInt(br.readLine()); 1771
30. } 1772 31. catch (IOException e) { 1773
32. e.printStackTrace(System.err); 1774 33. System.out.println("el programa se debe finalizar"); 1775
34. System.exit( -1); 1776 35. } 1777
36. catch (Exception e) { 1778 37. e.printStackTrace(System.err); 1779
38. System.out.println("Error imprevisto"); 1780 39. System.exit( -1); 1781
40. } 1782 41. System.out.print("Ingrese el segundo lado del 1783
triangulo: "); 1784 42. try { 1785
43. lado2 = Integer.parseInt(br.readLine()); 1786 44. } 1787
45. catch (IOException e) { 1788 46. e.printStackTrace(System.err); 1789
47. System.out.println("el programa se debe finalizar"); 1790 48. System.exit( -1); 1791
49. } 1792 50. catch (Exception e) { 1793
51. e.printStackTrace(System.err); 1794 52. System.out.println("Error imprevisto"); 1795
53. System.exit( -1); 1796 54. } 1797
55. System.out.print("Ingrese el tercer lado del 1798 triangulo: "); 1799
56. try { 1800 57. lado3 = Integer.parseInt(br.readLine()); 1801
58. } 1802
54
59. catch (IOException e) { 1803 60. e.printStackTrace(System.err); 1804
61. System.out.println("el programa se debe finalizar"); 1805 62. System.exit( -1); 1806
63. } 1807 64. catch (Exception e) { 1808
65. e.printStackTrace(System.err); 1809 66. System.out.println("Error imprevisto"); 1810
67. System.exit( -1); 1811 68. } 1812
69. perimetro = lado1 + lado2 + lado3; 1813 70. System.out.println("El Perimetro del triangulo es: " + 1814
perimetro); 1815 71. } 1816 72.} 1817
P.C.E4 1818 1. package com.compunauta.aprendiendojava.ex; 1819
2. import java.io.BufferedReader; 1820 3. import java.io.InputStreamReader; 1821
4. import java.io.IOException; 1822 5. 1823 6. 1824
7. /** 1825 8. * <p>Título: Aprendiendo Java</p> 1826
9. * <p>Descripción: Ejemplos del Libro Aprendiendo 1827 Java de Compunauta</p> 1828
10. * <p>Copyright: Copyright (c) 2006 1829 www.compunauta.com</p> 1830
11. * <p>Empresa: [email protected]</p> 1831 12. * @author Julio César Duarte 1832
13. * @version 2006.01.01 1833 14. */ 1834 15. 1835 16. 1836
17.public class Comp0Ej4 { 1837 18. /** 1838
19. * Ejercicio4: Se conocen dos números. Determinar y 1839 mostrar el mayor 1840
20. */ 1841
55
21. public static void main(String[] args) { 1842 22. int numero1 = 0; 1843 23. int numero2 = 0; 1844
24. BufferedReader br = new BufferedReader(new 1845 InputStreamReader(System.in)); 1846
25. System.out.print("Ingrese el primer numero: "); 1847 26. try { 1848
27. numero1 = Integer.parseInt(br.readLine()); 1849 28. } 1850
29. catch (IOException e) { 1851 30. e.printStackTrace(System.err); 1852
31. System.out.println("el programa se debe finalizar"); 1853 32. System.exit( -1); 1854
33. } 1855 34. catch (Exception e) { 1856
35. e.printStackTrace(System.err); 1857 36. System.out.println("Error imprevisto"); 1858
37. System.exit( -1); 1859 38. } 1860
39. System.out.print("Ingrese el segundo numero: "); 1861 40. try { 1862
41. numero2 = Integer.parseInt(br.readLine()); 1863 42. } 1864
43. catch (IOException e) { 1865 44. e.printStackTrace(System.err); 1866
45. System.out.println("el programa se debe finalizar"); 1867 46. System.exit( -1); 1868
47. } 1869 48. catch (Exception e) { 1870
49. e.printStackTrace(System.err); 1871 50. System.out.println("Error imprevisto"); 1872
51. System.exit( -1); 1873 52. } 1874
53. if (numero1 > numero2) { 1875 54. System.out.println("El numero mayor es: " + 1876
numero1); 1877 55. } 1878
56. else { 1879 57. if (numero1 < numero2) { 1880
56
58. System.out.println("El numero mayor es: " + 1881 numero2); 1882
59. } 1883 60. else { 1884
61. System.out.println("Los dos numeros son iguales: " 1885 + numero1); 1886
62. } 1887 63. } 1888 64. } 1889 65.} 1890
P.C.E5 1891 1. package com.compunauta.aprendiendojava.ex; 1892
2. import java.io.BufferedReader; 1893 3. import java.io.InputStreamReader; 1894
4. import java.io.IOException; 1895 5. 1896
6. /** 1897 7. * <p>Título: Aprendiendo Java</p> 1898
8. * <p>Descripción: Ejemplos del Libro Aprendiendo 1899 Java de Compunauta</p> 1900
9. * <p>Copyright: Copyright (c) 2006 1901 www.compunauta.com</p> 1902
10. * <p>Empresa: [email protected]</p> 1903 11. * @author Julio César Duarte 1904
12. * @version 2006.01.01 1905 13. */ 1906 14. 1907
15.public class Comp0Ej5 { 1908 16. /** 1909
17. * Ejercicio5: Se conocen dos números distintos. 1910 18. * Determinar si el primero de ellos es el mayor 1911
19. */ 1912 20. public static void main(String[] args) { 1913
21. int numero1 = 0; 1914 22. int numero2 = 0; 1915
23. BufferedReader br = new BufferedReader(new 1916 InputStreamReader(System.in)); 1917
24. System.out.print("Ingrese el primer numero: "); 1918 25. try { 1919
57
26. numero1 = Integer.parseInt(br.readLine()); 1920 27. } 1921
28. catch (IOException e) { 1922 29. e.printStackTrace(System.err); 1923
30. System.out.println("el programa se debe finalizar"); 1924 31. System.exit( -1); 1925
32. } 1926 33. catch (Exception e) { 1927
34. e.printStackTrace(System.err); 1928 35. System.out.println("Error imprevisto"); 1929
36. System.exit( -1); 1930 37. } 1931
38. System.out.print("Ingrese el segundo numero 1932 distinto del primero: "); 1933
39. try { 1934 40. numero2 = Integer.parseInt(br.readLine()); 1935
41. } 1936 42. catch (IOException e) { 1937
43. e.printStackTrace(System.err); 1938 44. System.out.println("el programa se debe finalizar"); 1939
45. System.exit( -1); 1940 46. } 1941
47. catch (Exception e) { 1942 48. e.printStackTrace(System.err); 1943
49. System.out.println("Error imprevisto"); 1944 50. System.exit( -1); 1945
51. } 1946 52. if (numero1 > numero2) { 1947
53. System.out.println("Se confirma que el primer 1948 numero es mas 1949
grande"); 1950 54. } 1951
55. else { 1952 56. System.out.println("El primer numero no resulta ser 1953
el mas grande"); 1954 57. } 1955 58. 1956
59. } 1957 60. } 1958
58
P.C.E6 1959 1. package com.compunauta.aprendiendojava.ex; 1960
2. import java.io.BufferedReader; 1961 3. import java.io.InputStreamReader; 1962
4. import java.io.IOException; 1963 5. 1964
6. /** 1965 7. * <p>Título: Aprendiendo Java</p> 1966
8. * <p>Descripción: Ejemplos del Libro Aprendiendo Java de 1967 Compunauta</p> 1968
9. * <p>Copyright: Copyright (c) 2006 1969 www.compunauta.com</p> 1970
10. * <p>Empresa: [email protected]</p> 1971 11. * @author Julio César Duarte 1972
12. * @version 2006.01.01 1973 13. */ 1974 14. 1975
15.public class Comp0Ej6 { 1976 16. /** 1977
17. * Ejercicio6: Se conocen dos números distintos. Calcular 1978 la superficie de un 1979
18. * cuadrado, suponiendo como lado del mismo al mayor de 1980 los números 1981
19. * dados y la superficie de n círculo suponiendo como radio 1982 del 1983
20. * mismo al menor de los números dados. 1984 21. */ 1985 22. 1986
23. public static void main(String[] args) { 1987 24. int numero1 = 0; 1988 25. int numero2 = 0; 1989
26. int mayor = 0; 1990 27. int menor = 0; 1991
28. int cuadrado = 0; 1992 29. double circulo = 0; 1993
30. BufferedReader br = new BufferedReader(new 1994 InputStreamReader(System.in)); 1995
31. System.out.print("Ingrese el primer numero: "); 1996 32. try { 1997
33. numero1 = Integer.parseInt(br.readLine()); 1998
59
34. } 1999 35. catch (IOException e) { 2000
36. e.printStackTrace(System.err); 2001 37. System.out.println("el programa se debe finalizar"); 2002
38. System.exit( -1); 2003 39. } 2004
40. catch (Exception e) { 2005 41. e.printStackTrace(System.err); 2006
42. System.out.println("Error imprevisto"); 2007 43. System.exit( -1); 2008
44. } 2009 45. System.out.print("Ingrese el segundo numero 2010
distinto del primero: "); 2011 46. try { 2012
47. numero2 = Integer.parseInt(br.readLine()); 2013 48. } 2014
49. catch (IOException e) { 2015 50. e.printStackTrace(System.err); 2016
51. System.out.println("el programa se debe finalizar"); 2017 52. System.exit( -1); 2018
53. } 2019 54. catch (Exception e) { 2020
55. e.printStackTrace(System.err); 2021 56. System.out.println("Error imprevisto"); 2022
57. System.exit( -1); 2023 58. } 2024
59. if (numero1 > numero2) { 2025 60. mayor = numero1; 2026 61. menor = numero2; 2027
62. } 2028 63. else { 2029
64. mayor = numero2; 2030 65. menor = numero1; 2031
66. } 2032 67. cuadrado = mayor * mayor; 2033
68. circulo = Math.PI * menor * menor; 2034 69. System.out.println("La supercie del cuadrado es: " + 2035
cuadrado); 2036
60
70. System.out.println("La supercie del circulo es: " + 2037 circulo); 2038
71. } 2039 72.} 2040
P.C.E7 2041 1. package com.compunauta.aprendiendojava.ex; 2042
2. import java.io.BufferedReader; 2043 3. import java.io.InputStreamReader; 2044
4. import java.io.IOException; 2045 5. 2046
6. /** 2047 7. * <p>Título: Aprendiendo Java</p> 2048
8. * <p>Descripción: Ejemplos del Libro Aprendiendo 2049 Java de Compunauta</p> 2050
9. * <p>Copyright: Copyright (c) 2006 2051 www.compunauta.com</p> 2052
10. * <p>Empresa: [email protected]</p> 2053 11. * @author Julio César Duarte 2054
12. * @version 2006.01.01 2055 13. */ 2056 14. 2057
15.public class Comp0Ej7 { 2058 16. /** 2059
17. * Ejercicio7: Se conocen tres números distintos. 2060 Determinar el menor de ellos y 2061
18. * cacular el cuadrado y el cubo del mismo 2062 19. */ 2063 20. 2064
21. public static void main(String[] args) { 2065 22. int numero1 = 0; 2066 23. int numero2 = 0; 2067 24. int numero3 = 0; 2068
25. int menor; 2069 26. BufferedReader br = new BufferedReader(new 2070
InputStreamReader(System.in)); 2071 27. System.out.print("Ingrese el primer numero: "); 2072
28. try { 2073 29. numero1 = Integer.parseInt(br.readLine()); 2074
30. } 2075
61
31. catch (IOException e) { 2076 32. e.printStackTrace(System.err); 2077
33. System.out.println("el programa se debe finalizar"); 2078 34. System.exit( -1); 2079
35. } 2080 36. catch (Exception e) { 2081
37. e.printStackTrace(System.err); 2082 38. System.out.println("Error imprevisto"); 2083
39. System.exit( -1); 2084 40. } 2085
41. System.out.print("Ingrese el segundo numero: "); 2086 42. try { 2087
43. numero2 = Integer.parseInt(br.readLine()); 2088 44. } 2089
45. catch (IOException e) { 2090 46. e.printStackTrace(System.err); 2091
47. System.out.println("el programa se debe finalizar"); 2092 48. System.exit( -1); 2093
49. } 2094 50. catch (Exception e) { 2095
51. e.printStackTrace(System.err); 2096 52. System.out.println("Error imprevisto"); 2097
53. System.exit( -1); 2098 54. } 2099
55. System.out.print("Ingrese el tercer numero: "); 2100 56. try { 2101
57. numero3 = Integer.parseInt(br.readLine()); 2102 58. } 2103
59. catch (IOException e) { 2104 60. e.printStackTrace(System.err); 2105
61. System.out.println("el programa se debe finalizar"); 2106 62. System.exit( -1); 2107
63. } 2108 64. catch (Exception e) { 2109
65. e.printStackTrace(System.err); 2110 66. System.out.println("Error imprevisto"); 2111
67. System.exit( -1); 2112 68. } 2113
69. if (numero1 < numero2) { 2114
62
70. menor = numero1; 2115 71. } 2116
72. else { 2117 73. menor = numero2; 2118
74. } 2119 75. if (menor > numero3) { 2120
76. menor = numero3; 2121 77. } 2122
78. System.out.println("El numero menor es: " + menor); 2123 79. System.out.println("El cuadrado es: " + menor * 2124
menor); 2125 80. System.out.println("El cubo es: " + menor * menor * 2126
menor); 2127 81. } 2128 82.} 2129
P.C.E8 2130 1. package com.compunauta.aprendiendojava.ex; 2131
2. import java.io.BufferedReader; 2132 3. import java.io.InputStreamReader; 2133
4. import java.io.IOException; 2134 5. 2135
6. /** 2136 7. * <p>Título: Aprendiendo Java</p> 2137
8. * <p>Descripción: Ejemplos del Libro Aprendiendo 2138 Java de Compunauta</p> 2139
9. * <p>Copyright: Copyright (c) 2006 2140 www.compunauta.com</p> 2141
10. * <p>Empresa: [email protected]</p> 2142 11. * @author Julio César Duarte 2143
12. * @version 2006.01.01 2144 13. */ 2145 14. 2146
15.public class Comp0Ej8 { 2147 16. /** 2148
17. * Ejercicio8: Se ingresan por teclado las notas obtenidas 2149 por tres alumnos en 2150
18. * un parcial de ciertas materia. Se desea saber cuáles de 2151 estos 2152
63
19. * alumnos resultaron aplazados, y además se pide 2153 determinar cuál 2154
20. * fue la mayor nota, y cuál fue el alumno que la obtuvo. 2155 21. */ 2156
22. public static void main(String[] args) { 2157 23. int nota1 = 0; 2158 24. int nota2 = 0; 2159 25. int nota3 = 0; 2160
26. int mejor; 2161 27. int alumno; 2162
28. BufferedReader br = new BufferedReader(new 2163 InputStreamReader(System.in)); 2164
29. System.out.print("Ingrese la nota del primer alumno: 2165 "); 2166
30. try { 2167 31. nota1 = Integer.parseInt(br.readLine()); 2168
32. } 2169 33. catch (IOException e) { 2170
34. e.printStackTrace(System.err); 2171 35. System.out.println("el programa se debe finalizar"); 2172
36. System.exit( -1); 2173 37. } 2174
38. catch (Exception e) { 2175 39. e.printStackTrace(System.err); 2176
40. System.out.println("Error imprevisto"); 2177 41. System.exit( -1); 2178
42. } 2179 43. System.out.print("Ingrese la nota del segundo 2180
alumno: "); 2181 44. try { 2182
45. nota2 = Integer.parseInt(br.readLine()); 2183 46. } 2184
47. catch (IOException e) { 2185 48. e.printStackTrace(System.err); 2186
49. System.out.println("el programa se debe finalizar"); 2187 50. System.exit( -1); 2188
51. } 2189 52. catch (Exception e) { 2190
53. e.printStackTrace(System.err); 2191
64
54. System.out.println("Error imprevisto"); 2192 55. System.exit( -1); 2193
56. } 2194 57. System.out.print("Ingrese la nota del tercer alumno: 2195
"); 2196 58. try { 2197
59. nota3 = Integer.parseInt(br.readLine()); 2198 60. } 2199
61. catch (IOException e) { 2200 62. e.printStackTrace(System.err); 2201
63. System.out.println("el programa se debe finalizar"); 2202 64. System.exit( -1); 2203
65. } 2204 66. catch (Exception e) { 2205
67. e.printStackTrace(System.err); 2206 68. System.out.println("Error imprevisto"); 2207
69. System.exit( -1); 2208 70. } 2209
71. System.out.println("Alumno Aplazados: "); 2210 72. if (nota1 < 4) { 2211
73. System.out.println("-Primer alumno aplazado"); 2212 74. } 2213
75. if (nota2 < 4) { 2214 76. System.out.println("-Segundo alumno aplazado"); 2215
77. } 2216 78. if (nota3 < 4) { 2217
79. System.out.println("-Tercer alumno aplazado"); 2218 80. } 2219
81. System.out.println("Alumno que obtuvo la mejor 2220 nota: "); 2221
82. if (nota1 > nota2) { 2222 83. mejor = nota1; 2223
84. alumno = 1; 2224 85. } 2225
86. else { 2226 87. mejor = nota2; 2227
88. alumno = 2; 2228 89. } 2229
90. if (mejor < nota3) { 2230
65
91. mejor = nota3; 2231 92. alumno = 3; 2232
93. } 2233 94. System.out.println("El alumno" + alumno + " fue 2234
quien obtuvo un: " + 2235 mejor); 2236 95. } 2237 96.} 2238
P.C.E9 2239 1. package com.compunauta.aprendiendojava.ex; 2240
2. import java.io.BufferedReader; 2241 3. import java.io.InputStreamReader; 2242
4. import java.io.IOException; 2243 5. 2244
6. /** 2245 7. * <p>Título: Aprendiendo Java</p> 2246
8. * <p>Descripción: Ejemplos del Libro Aprendiendo 2247 Java de Compunauta</p> 2248
9. * <p>Copyright: Copyright (c) 2006 2249 www.compunauta.com</p> 2250
10. * <p>Empresa: [email protected]</p> 2251 11. * @author Julio César Duarte 2252
12. * @version 2006.01.01 2253 13. */ 2254 14. 2255
15.public class Comp0Ej9 { 2256 16. /** 2257
17. * Ejercicio9: Un comerciante tiene la venta de 4 tipos de 2258 productos principales 2259
18. * Conociendo la cantidad vendida de cada artículo, y el 2260 precio 2261
19. * unitario de cada artículo, hacer un programa que 2262 determine cuál 2263
20. * fue el producto que realizó el mayor aporte en los 2264 ingresos. 2265
21. * Calcular además, el porcentaje que dicho aporte 2266 significa en el 2267
22. * ingreso absoluto por los cuatro artículos sumados. 2268 23. */ 2269 24. 2270
66
25. public static void main(String[] args) { 2271 26. String buf = new String(""); 2272
27. float precio1 = 0; 2273 28. int cantidad1 = 0; 2274 29. float aporte1 = 0; 2275 30. float precio2 = 0; 2276 31. int cantidad2 = 0; 2277 32. float aporte2 = 0; 2278 33. float precio3 = 0; 2279 34. int cantidad3 = 0; 2280 35. float aporte3 = 0; 2281 36. float precio4 = 0; 2282 37. int cantidad4 = 0; 2283 38. float aporte4 = 0; 2284
39. float aportetotal = 0; 2285 40. float mayor = 0; 2286
41. int id = 0; 2287 42. float porcentaje = 0; 2288
43. BufferedReader br = new BufferedReader(new 2289 InputStreamReader(System.in)); 2290
44. System.out.print("Ingrese el precio producto1: "); 2291 45. try { 2292
46. //precio1=Double.valueOf(br.readLine()); 2293 47. precio1 = Float.valueOf(br.readLine()).floatValue(); 2294
48. } 2295 49. catch (IOException e) { 2296
50. e.printStackTrace(System.err); 2297 51. System.out.println("el programa se debe finalizar"); 2298
52. System.exit( -1); 2299 53. } 2300
54. catch (Exception e) { 2301 55. e.printStackTrace(System.err); 2302
56. System.out.println("Error imprevisto"); 2303 57. System.exit( -1); 2304
58. } 2305 59. System.out.print("Ingrese el precio producto2: "); 2306
60. try { 2307 61. precio2 = Float.valueOf(br.readLine()).floatValue(); 2308
62. } 2309
67
63. catch (IOException e) { 2310 64. e.printStackTrace(System.err); 2311
65. System.out.println("el programa se debe finalizar"); 2312 66. System.exit( -1); 2313
67. } 2314 68. catch (Exception e) { 2315
69. e.printStackTrace(System.err); 2316 70. System.out.println("Error imprevisto"); 2317
71. System.exit( -1); 2318 72. } 2319
73. System.out.print("Ingrese el precio producto3: "); 2320 74. try { 2321
75. precio3 = Float.valueOf(br.readLine()).floatValue(); 2322 76. } 2323
77. catch (IOException e) { 2324 78. e.printStackTrace(System.err); 2325
79. System.out.println("el programa se debe finalizar"); 2326 80. System.exit( -1); 2327
81. } 2328 82. catch (Exception e) { 2329
83. e.printStackTrace(System.err); 2330 84. System.out.println("Error imprevisto"); 2331
85. System.exit( -1); 2332 86. } 2333
87. System.out.print("Ingrese el precio producto4: "); 2334 88. try { 2335
89. precio4 = Float.valueOf(br.readLine()).floatValue(); 2336 90. } 2337
91. catch (IOException e) { 2338 92. e.printStackTrace(System.err); 2339
93. System.out.println("el programa se debe finalizar"); 2340 94. System.exit( -1); 2341
95. } 2342 96. catch (Exception e) { 2343
97. e.printStackTrace(System.err); 2344 98. System.out.println("Error imprevisto"); 2345
99. System.exit( -1); 2346 100. } 2347
68
101. System.out.print("Ingrese la cantida vendida del 2348 producto1: "); 2349
102. try { 2350 103. cantidad1 = Integer.parseInt(br.readLine()); 2351
104. } 2352 105. catch (IOException e) { 2353
106. e.printStackTrace(System.err); 2354 107. System.out.println("el programa se debe finalizar"); 2355
108. System.exit( -1); 2356 109. } 2357
110. catch (Exception e) { 2358 111. e.printStackTrace(System.err); 2359
112. System.out.println("Error imprevisto"); 2360 113. System.exit( -1); 2361
114. } 2362 115. System.out.print("Ingrese la cantida vendida del 2363
producto2: "); 2364 116. try { 2365
117. cantidad2 = Integer.parseInt(br.readLine()); 2366 118. } 2367
119. catch (IOException e) { 2368 120. e.printStackTrace(System.err); 2369
121. System.out.println("el programa se debe finalizar"); 2370 122. System.exit( -1); 2371
123. } 2372 124. catch (Exception e) { 2373
125. e.printStackTrace(System.err); 2374 126. System.out.println("Error imprevisto"); 2375
127. System.exit( -1); 2376 128. } 2377
129. System.out.print("Ingrese la cantida vendida del 2378 producto3: "); 2379
130. try { 2380 131. cantidad3 = Integer.parseInt(br.readLine()); 2381
132. } 2382 133. catch (IOException e) { 2383
134. e.printStackTrace(System.err); 2384 135. System.out.println("el programa se debe finalizar"); 2385
136. System.exit( -1); 2386
69
137. } 2387 138. catch (Exception e) { 2388
139. e.printStackTrace(System.err); 2389 140. System.out.println("Error imprevisto"); 2390
141. System.exit( -1); 2391 142. } 2392
143. System.out.print("Ingrese la cantida vendida del 2393 producto4: "); 2394
144. try { 2395 145. cantidad4 = Integer.parseInt(br.readLine()); 2396
146. } 2397 147. catch (IOException e) { 2398
148. e.printStackTrace(System.err); 2399 149. System.out.println("el programa se debe finalizar"); 2400
150. System.exit( -1); 2401 151. } 2402
152. catch (Exception e) { 2403 153. e.printStackTrace(System.err); 2404
154. System.out.println("Error imprevisto"); 2405 155. System.exit( -1); 2406
156. } 2407 157. aporte1 = precio1 * cantidad1; 2408 158. aporte2 = precio2 * cantidad2; 2409 159. aporte3 = precio3 * cantidad3; 2410 160. aporte4 = precio4 * cantidad4; 2411
161. aportetotal = aporte1 + aporte2 + aporte3 + 2412 aporte4; 2413
162. if (aporte1 > aporte2) { 2414 163. mayor = aporte1; 2415
164. id = 1; 2416 165. } 2417
166. else { 2418 167. mayor = aporte2; 2419
168. id = 2; 2420 169. } 2421
170. if (mayor < aporte3) { 2422 171. mayor = aporte3; 2423
172. id = 3; 2424 173. } 2425
70
174. if (mayor < aporte4) { 2426 175. mayor = aporte4; 2427
176. id = 4; 2428 177. } 2429
178. porcentaje = (mayor / aportetotal) * 100; 2430 179. System.out.println("El producto" + id + " fue el que 2431
mas aporto con: " 2432 + 2433
180. mayor); 2434 181. System.out.println("El porentaje de aporte sobre el 2435
total es de: " + 2436 182. porcentaje + "%"); 2437
183. 2438 184. } 2439 185.} 2440
Práctica Complementaria (bucles sin 2441
arreglos) 2442
III – Métodos estáticos y 2443
Mecanismos de Programación. 2444
Este capítulo pretende proporcionar al usuario 2445
final las herramientas para solucionar 2446 problemas 2447
del tipo programación estructurada, de pilas, 2448
colas, vectores, árboles, etc. Que es 2449 necesario para formar 2450
correctamente al alumno en cualquier 2451 ambiente de programación, incluida la 2452
programación orientada a 2453
objetos, no pretendemos ir a la P.O.O todavía 2454 sino hasta más adelante, de esta manera este 2455
capítulo 2456 puede utilizarse para afianzar los 2457
conocimientos necesarios para un curso de 2458 física o matemáticas donde 2459
71
se desee aplicar a problemas en general. 2460
La P.O.O. en este capítulo será 2461
completamente básica, y ni siquiera la 2462 mencionaremos en muchos 2463
caso hasta el final del capítulo a menos que 2464
sea necesario. 2465
Métodos estáticos (funciones o 2466
procedimientos) 2467
En el capitulo anterior no utilizamos nada de la 2468
programación estructurada, sólo seguimos un 2469 orden de ejecución secuencial, es decir paso 2470
a paso y no planteamos el problema de la 2471
reutilización de 2472 código. 2473
Problema: necesitamos ingresar datos por 2474 teclado, hacer varios cálculos y volver a 2475
ingresar datos 2476
por teclado y hacer otros cálculos diferentes, y 2477
este mismo proceso, repetidas veces, como 2478 vimos en los 2479
ejemplos anteriores tendríamos que repetir el 2480 bloque try{}catch(){} varias veces, y si 2481
quisiéramos 2482 repetir un bloque de cálculos para ciertos 2483
datos... ¿Que pasaría si quiero cambiar 2484
esas órdenes las 2485 veces que se hayan repetido?. 2486
Entonces comenzamos con las funciones, o 2487
métodos estáticos en Java, se les denomina 2488 estáticos 2489
72
porque pertenecen a la Clase o tipo de datos y 2490
no es necesario crear un objeto para 2491
invocarlos o 2492 llamarlos, para nosotros en este momento nos 2493
servirán para solucionar el problema de 2494
repetición y 2495 mantenimiento de código. 2496
Ejemplo 3.1: 2497 Se requiere ingresar los datos de 3 valores y 2498
calcular su promedio, paso seguido, preguntar 2499
el 2500 nombre del usuario e imprimir de manera 2501
personalizada “Usuario, el promedio de tus 2502 tres valores es: 2503
XXX”, es un problema muy similar a los 2504
anteriores, pero utilizaremos una función 2505 llamada leer que 2506
fabricaremos para no repetir el código de 2507
lectura del teclado. 2508 1. package com.compunauta.aprendiendojava; 2509
2. import java.io.*; 2510 3. /** 2511
4. * <p>Título: Aprendiendo Java</p> 2512 5. * <p>Descripción: Ejemplos del Libro Aprendiendo 2513
Java de Compunauta</p> 2514 6. * <p>Copyright: Copyright (c) 2006 2515
www.compunauta.com</p> 2516 7. * <p>Empresa: COMPUNAUTA</p> 2517 8. * @author Gustavo Guillermo Pérez 2518
9. * @version 2006.01.01 2519 10. */ 2520 11. 2521
12.public class MetodoLeer { 2522 13. public static void main(String[] args) { 2523
73
14. BufferedReader br=new BufferedReader(new 2524 InputStreamReader(System.in)); 2525
15. int acumulador=0; 2526 16. for(int i=0;i<3;i++){ 2527
17. System.out.println("Ingrese el valor "+(i+1)+" de 2528 3?"); 2529 18. 2530
acumulador=acumulador+=Integer.parseInt(leer(br)); 2531 19. } 2532
20. acumulador/=3; 2533 21. System.out.println("Ingrese su nombre?"); 2534
22. String nombre=leer(br); 2535 23. System.out.println("Usuario: "+nombre+" tu 2536
promedio es:"+acumulador); 2537 24. } 2538 25. 2539
26.public static String leer(BufferedReader buff){ 2540 27. String lee=""; 2541
28.try{lee=buff.readLine();} 2542 29.catch(Exception ex){ 2543
30. ex.printStackTrace(System.err);} 2544 31.return lee; 2545
32.}//final de la funcion leer 2546 33.}//final de la clase 2547
Como podemos ver desde la línea 26 a la 32 2548
se define la función estática leer, que es 2549 pública y 2550
devolverá datos de tipo String, esta función 2551 para poder procesar la lectura necesita que le 2552
pasemos como 2553 argumento un objeto del tipo BufferedReader 2554
que es el encargado de leer las líneas, esta 2555
función tiene 2556
como objetivo que no se repita el código de 2557 control de errores y en el futuro podremos 2558
modificar esta 2559
74
función o fabricar otra para leer números que 2560
revise una correcta entrada de datos. 2561
Bien, ahora veamos el código mejorado 2562 utilizando una función para leer texto y otra 2563
para los 2564
números enteros: 2565 1. package com.compunauta.aprendiendojava; 2566
2. import java.io.*; 2567 3. /** 2568
4. * <p>Título: Aprendiendo Java</p> 2569 5. * <p>Descripción: Ejemplos del Libro Aprendiendo 2570
Java de Compunauta</p> 2571 6. * <p>Copyright: Copyright (c) 2006 2572
www.compunauta.com</p> 2573 7. * <p>Empresa: COMPUNAUTA</p> 2574 8. * @author Gustavo Guillermo Pérez 2575
9. * @version 2006.01.01 2576 10. */ 2577 11. 2578
12.public class MetodoLeer { 2579 13. public static void main(String[] args) { 2580
14. BufferedReader br=new BufferedReader(new 2581 InputStreamReader(System.in)); 2582
15. int acumulador=0; 2583 16. for(int i=0;i<3;i++){ 2584
17. System.out.println("Ingrese el valor "+(i+1)+" de 2585 3?"); 2586 18. 2587
acumulador=acumulador+=Integer.parseInt(leerTexto(br2588 )); 2589
19. } 2590 20. acumulador/=3; 2591
21. System.out.println("Ingrese su nombre?"); 2592 22. String nombre=leerTexto(br); 2593
23. System.out.println("Usuario: "+nombre+" tu 2594 promedio es:"+acumulador); 2595
24. } 2596 25. 2597
75
26.public static String leerTexto(BufferedReader buff){ 2598 27. String lee=""; 2599
28.try{lee=buff.readLine();} 2600 29.catch(Exception ex){ 2601
30. ex.printStackTrace(System.err);} 2602 31.return lee; 2603
32.}//final de la funcion leer 2604 33. 2605
34.public static int leerInt(BufferedReader buff){ 2606 35. int lee=0; 2607
36. boolean error; 2608 37. do { 2609
38. error=false; 2610 39. try {lee = Integer.parseInt(buff.readLine());} 2611
40. catch (NumberFormatException ex) { 2612 41. System.out.println("Entrada erronea, repetir:?"); 2613
42. error=true;} 2614 43. catch (Exception 2615
ex){ex.printStackTrace(System.err);} 2616 44. } while (error); 2617
45.return lee; 2618 46.}//final de la funcion leer 2619
47. 2620 48.} 2621
Arreglos (Arrays) o Vectores. 2622
Los arreglos son como un vector, con varias 2623
componentes incluso en programación un 2624
arreglo 2625 puede representar una matriz de varias 2626
dimensiones. Por ejemplo si tenemos 10 2627 frases que enseñaremos 2628
según un número del 1 al 10, podemos utilizar 2629
un vector de una sola dimensión, donde 2630
indicaremos con 2631 un subíndice a los elementos que este mismo 2632
almacene. 2633
76
En Java un arreglo se representa por un 2634
objeto que tiene un límite de elementos al ser 2635
definido, o 2636 en alguna parte de nuestro programa le 2637
asignaremos un objeto arreglo de cierto tipo. 2638
Los elementos que 2639 pondremos en nuestro arreglo de datos deben 2640
estar definidos en cantidad, no en valor, si 2641 creemos que 2642
podemos necesitar más o menos 10+/-3 2643
elementos asignaremos 13 por más que a 2644 veces usemos 7. 2645
Los arreglos tienen una cantidad de 2646 elementos, pero el subíndice que usaremos 2647
para acceder al 2648
contenido de cada elemento irá del 0 a 2649 ELEMENTOS-1. Veamos un ejemplo: 2650
Problema: 2651
Se desea ingresar por teclado tres resultados 2652 de exámenes, e imprimir el 1º y último, 2653
utilizamos la 2654 función leerInt() que ejemplificamos 2655
anteriormente. 2656 1. package com.compunauta.aprendiendojava; 2657
2. import java.io.*; 2658 3. /** 2659
4. * <p>Título: Aprendiendo Java</p> 2660 5. * <p>Descripción: Ejemplos del Libro Aprendiendo 2661
Java de Compunauta</p> 2662 6. * <p>Copyright: Copyright (c) 2006 2663
www.compunauta.com</p> 2664 7. * <p>Empresa: COMPUNAUTA</p> 2665 8. * @author Gustavo Guillermo Pérez 2666
9. * @version 2006.01.01 2667
77
10. */ 2668 11. 2669
12.public class Arreglos { 2670 13. public static void main(String[] args) { 2671
14. BufferedReader br=new BufferedReader(new 2672 InputStreamReader(System.in)); 2673 15. int[] examenes=new int[3]; 2674
16. System.out.println("La longitud de datos de mi 2675 arreglo 2676
es:"+examenes.length); 2677 17. for (int i=0;i<examenes.length;i++){ 2678
18. System.out.println("Ingrese el valor para el examen 2679 "+(i+1)+" de 2680
"+examenes.length); 2681 19. examenes[i]=leerInt(br); 2682
20. } 2683 21. System.out.println("El resultado del primer examen 2684
es:"+examenes[0]); 2685 22. System.out.println("El resultado del último examen 2686
es:"+examenes[examenes.length-1]); 2687 23. } 2688
24. public static int leerInt(BufferedReader buff){ 2689 25. int lee=0; 2690
26. boolean error; 2691 27. do { 2692
28. error=false; 2693 29. try {lee = Integer.parseInt(buff.readLine());} 2694
30. catch (NumberFormatException ex) { 2695 31.System.out.println("Entrada erronea, repetir:?"); 2696
32. error=true;} 2697 33. catch (Exception 2698
ex){ex.printStackTrace(System.err);} 2699 34. } while (error); 2700
35.return lee; 2701 36.}//final de la funcion leer 2702
37. 2703 38.} 2704
La salida por pantalla será algo como esto: 2705 La longitud de datos de mi arreglo es:3 2706
78
Ingrese el valor para el examen 1 de 3 2707 23 2708
Ingrese el valor para el examen 2 de 3 2709 21 2710
Ingrese el valor para el examen 3 de 3 2711 12 2712
El resultado del primer examen es:23 2713 El resultado del último examen es:12 2714
La clase Math de procedimientos y 2715
constantes matemáticas 2716
A continuación veremos la utilidad de la Clase 2717 de la biblioteca más útil, que provee algunas 2718
cuantas funciones matemáticas que usaremos 2719
para resolver nuestros problemas en este 2720 capítulo. 2721
Resumen de Campos 2722
static double E 2723 El valor double que es el mas cercano a e, la 2724
base de los logaritmos 2725
naturales. 2726 static double PI 2727
El valor double que es más cercano a pi, la 2728
relación de una circunferencia 2729
con su diámetro. 2730
Resumen de Métodos 2731
static double abs(double a) 2732 Devuelve el valor absoluto de un valor double. 2733
static float abs(float a) 2734
Devuelve el valor absoluto de un valor float. 2735 static int abs(int a) 2736
Devuelve el valor absoluto de un valor int. 2737 static long abs(long a) 2738
79
Devuelve el valor absoluto de un valor long. 2739
static double acos(double a) 2740
Devuelve el arcocoseno de un ángulo, en el 2741 rango de 0.0 hasta pi. 2742
static double asin(double a) 2743
Devuelve el arcoseno de un ángulo, en el 2744 rango de -pi/2 hasta pi/2. 2745
static double atan(double a) 2746 Devuelve el arcotangente de un ángulo, en el 2747
rango de -pi/2 hasta pi/2. 2748
static double atan2(double y, double x) 2749 Convierte coordenadas rectangulares (x, y) a 2750
polares (r, theta). 2751
static double cbrt(double a) 2752 Devuelve la raíz cuadrada de un valor double. 2753
static double ceil(double a) 2754 Devuleve el más pequeño (cercano al infinito 2755
negativo) valor double que es 2756
más grande o igual al argumento a y es igual 2757 a un entero matemático. 2758
static double cos(double a) 2759
Devuelve el coseno trigonométrico de un 2760 ángulo. 2761
static double cosh(double x) 2762 Devuelve el coseno hiperbólico de un valor 2763
value. 2764
static double exp(double a) 2765 Devuelve el valor e de Euler elevado a la 2766
potencia del valor double a. 2767
static double expm1(double x) 2768 Devuelve ex -1. 2769
static double floor(double a) 2770
80
Devuelve el más largo (cercano al positivo 2771
infinito) valor double que es 2772
menor o igual al argumento a y es igual a un 2773 entero matemático. 2774
static double hypot(double x, double y) 2775 Devuelve sqrt(x2 +y2) sin el overflow o 2776
underflow intermedio. 2777
static double IEEEremainder(double f1, double 2778 f2) 2779
Computa la operación prescripta por el 2780
estándar IEEE 754 entre los dos 2781 argumentos f1 y f2. 2782
static double log(double a) 2783 Devuelve el logaritmo natural (base e) de un 2784
valor double. 2785
static double log10(double a) 2786 Devuelve el logaritmo en base 10 de un valor 2787
double. 2788
static double log1p(double x) 2789 devuelve ex+1. 2790
static double max(double a, double b) 2791
Devuelve el más grande de los dos valores 2792 double a y b. 2793
static float max(float a, float b) 2794 Devuelve el más grande de los dos valores 2795
float a y b. 2796
static int max(int a, int b) 2797 Devuelve el más grande de los dos valores int 2798
a y b. 2799
static long max(long a, long b) 2800 Devuelve el más grande de los dos valores 2801
long a y b. 2802
81
static double min(double a, double b) 2803
Devuelve el más pequeño de los dos valores 2804
double a y b. 2805 static float min(float a, float b) 2806
Devuelve el más pequeño de los dos valores 2807
float a y b. 2808 static int min(int a, int b) 2809
Devuelve el más pequeño de los dos valores 2810 int a y b. 2811
static long min(long a, long b) 2812
Devuelve el más pequeño de los dos valores 2813 long a y b. 2814
static double pow(double a, double b) 2815 Devuelve el valor del argumento a elevado a 2816
la potencia de b: ab . 2817
static double random() 2818 Devuelve un valor de tipo double con signo 2819
positivo,mayor o igual que cero 2820
y menor que uno 1.0. 2821 static double rint(double a) 2822
Devuelve el valor double que es más cercano 2823
al valor a y es igual a un 2824 entero matemático. 2825
static long round(double a) 2826 Devuelve el valor long más cercano al 2827
argumento. 2828
static int round(float a) 2829 Devuelve el valor int más cercano al 2830
argumento. 2831
static double signum(double d) 2832 La función signo, cero si el argumento es cero, 2833
1.0 si el argumento es mayor 2834
82
que cero y -1.0 si el argumento es menor que 2835
cero. 2836
static float signum(float f) 2837 La función signo, cero si el argumento es cero, 2838
1.0 si el argumento es mayor 2839
que cero y -1.0 si el argumento es menor que 2840 cero. 2841
static double sin(double a) 2842 Devuelve el seno trigonométrico de un ángulo. 2843
static double sinh(double x) 2844
Devuelve el seno hiperbólico de un valor 2845 double. 2846
static double sqrt(double a) 2847 Devuelve la raíz cuadrada positiva 2848
redondeada de un valor double. 2849
static double tan(double a) 2850 Devuelve la tangente trigonométrica de un 2851
ángulo. 2852
static double tanh(double x) 2853 Devuelve la tangente hiperbólica de un valor 2854
double. 2855
static double toDegrees(double angrad) 2856 Convierte un ángulo medido en radianes al 2857
aproximado en grados.. 2858 static double toRadians(double angdeg) 2859
Convierte un ángulo medido en grados al 2860
aproximado en radianes. 2861 static double ulp(double d) 2862
Ver definición en la documentación completa. 2863
static float ulp(float f) 2864 Ver definición en la documentación completa. 2865
Tabla 10: La Clase Math - métodos y constantes 2866
83
Buffering – Memoria temporal 2867
Algunas veces es necesario procesar datos 2868
con cierta velocidad o cantidad conocida, la 2869 lectura de 2870
datos de 1 en 1 puede producir que en un 2871 cierto momento nuestro programa se quede 2872
sin hacer nada, o 2873
simplemente es más efectivo leer un archivo 2874 por bloques de datos grandes que de byte en 2875
byte 2876
(sobrecarga de llamadas a la misma función). 2877 En otras ocasiones podemos estar recibiendo 2878
datos por la red y si nuestro programa es lento 2879 para 2880
procesarlos o necesita atención por parte de 2881
un usuario para decidir que hacer, puede 2882 suceder que 2883
lleguen más datos de los que se pueden 2884
procesar, en este caso podemos utilizar un 2885
segmento de memoria 2886 temporal para almacenar estos datos y que no 2887
se pierdan y así aprovechar el tiempo en el 2888
que no llegan 2889
datos. 2890 El criterio para implementar estos tipos de 2891 memorias temporales (buffers de aquí en 2892
adelante) es 2893
variable, siempre se tomará en cuenta el 2894
promedio de datos que lleguen a nuestro 2895
programa o la cantidad 2896
84
de veces que es necesario llamar a una 2897
función que lee datos si lo hacemos con 2898
bloques más pequeños o 2899 más grandes, el valor óptimo siempre es 2900
empírico. 2901
Para determinar este valor siempre tendremos 2902 en cuenta que bloques más grandes de datos 2903
consumen más memoria del sistema 2904 operativo, y que muchas veces para mover 2905
bloques grandes de 2906
datos se puede perder mucho tiempo, por otra 2907 parte si nuestro archivo del disco no dispone 2908
de datos para 2909 llenar esos bloques, estaríamos 2910
desperdiciando memoria si abriéramos 2911
muchos archivos más pequeños 2912 que el buffer, por otro lado si el buffer es muy 2913
pequeño, entonces el efecto es contrario, 2914
estaríamos 2915 llamando innumerables cantidades de veces a 2916
la función leer, por lo que produciríamos un 2917
desperdicio 2918 de recursos del procesador, enlenteceríamos 2919 el sistema operativo, entonces queda claro 2920
que no leeremos 2921
archivos en bloques de 1MB ni lo haremos 2922
byte por byte. 2923
Usando arreglos para un buffer, 2924
colas de espera, pilas y listas. 2925
Bien, pongamos el siguiente ejemplo, se 2926 quieren enviar datos de una máquina a otra en 2927
un sólo 2928
85
sentido, una telefonista debe llamar a ciertos 2929
teléfonos que llegan desde otro punto de una 2930
red y no 2931 puede ver el siguiente teléfono hasta que haya 2932
terminado su llamada, del otro lado una 2933
secretaria que 2934 revisa el correo con una frecuencia de 5 2935
minutos envía los teléfonos del soporte 2936 técnico que deben ser 2937
atendidos por la telefonista, teniendo en 2938
cuenta que las llamadas suelen durar entre 10 2939 a 30 minutos y 2940
que los correos que pueden llegar al mismo 2941 tiempo no son más de 6 y que existen lapsos 2942
de hasta 60 2943
minutos sin recibir ni un sólo correo, y que no 2944 quedan llamadas pendientes en el transcurso 2945
del día. 2946
Criterios: 2947 1. Sobredimensionar es sobrecargar 2948
2. Minimizar es sobrecargar 2949
3. Si llenamos el buffer, no se podrán ingresar 2950 más dátos. 2951
4. Supondremos que en el peor de los casos 2952 llegan 10 correos 2953
5. Supondremos que en el peor de los casos 2954
duran 30 minutos 2955 6. Supondremos que en el peor de los casos 2956
el lapso es de 20 minutos durante 4 períodos. 2957
Los últimos tres criterios son suposiciones, 2958 que en la vida real son la telefonista y 2959
secretaria 2960
86
quienes pueden proveer este tipo de 2961
estadística sobre los horarios más saturados, 2962
tenemos que tener en 2963 cuenta que el problema es humanamente 2964 soluble ya que no quedan pendientes sin 2965
tratar así que durante 2966 el día se resuelven todos los llamados: 20min 2967
x 4p = 80min => 1) se resuelven en 80 2968 minutos 2 llamados 2969
y ¾ 2) se acumularon casi 40 tel – 3 tel = 37 2970
tel 2971 Entonces en el peor de los casos la 2972
acumulación máxima probable y el despacho 2973 de teléfonos más 2974
tardado producen un máximo de 37 teléfonos. 2975
Entonces nuestro buffer óptimo es de 37 2976 elementos. 2977
Como almacenar un teléfono no consume 2978
tanta cantidad de recursos de un sistema 2979 utilizaremos un 2980
buffer de 40 elementos. 2981 Nota: el manejo de memoria RAM en el 2982 sistema para valores o tipos de datos de 2983
almacenamiento fijo, como son todos los tipos 2984 de datos básicos excluyendo “String”, es 2985
de potencias de 2n y a veces de múltiplos de 2986
estas potencias, siendo recomendable elegir 2987 siempre un valor cercano pero no igual porque 2988
si la JVM utiliza bloques de 64enteros 2989
como buffer interno si usáramos 65enteros 2990 estaríamos obligando a usar el espacio de 2991
128enteros. 2992
87
Implementación del buffer tipo FIFO (Cola 2993
de espera, el primero es primero en salir) 2994
El ejemplo anterior necesita conocimientos de 2995 ejecución paralela de dos procesos, uno para 2996
leer 2997
del socket (conexión de red) y otro para 2998 atender a la telefonista, eso no lo veremos 2999
todavía así que 3000 cambiaremos el enunciado para implementar 3001
esta cola de espera. 3002 La telefonista recibe los teléfonos y tardará 3003 solo 1 minuto como máximo por llamada, es 3004
decir los 3005
números saldrán de a 1 por minuto, pudiendo 3006 descansar en el tiempo sobrante, si no hay 3007
números 3008 esperar, y si hay muchos guardarlos 3009
temporalmente. 3010
Utilizaremos una conexión de red, donde la 3011 telefonista tendrá un programa en espera que 3012
escuchará en la red y la secretaria el que 3013
enviará los datos al establecer una conexión. 3014 Telefonista: 3015
gus@gusgus ~$ java 3016 com.compunauta.aprendiendojava.Cap3_sock_3017
tel 3018 Escuchando el puerto:4567 3019
Esperando conexión... 3020 Conectado... Esperando teléfonos 3021 Secretaria llamando al tel:123 3022 Secretaria llamando al tel:432 3023
Ultima llamada, nos vamos... programa 3024 terminado 3025
gus@gusgus ~$ 3026
88
Secretaria: 3027 gus@gusgus ~$ java 3028
com.compunauta.aprendiendojava.Cap3_sock_3029 sec 3030
Intentando conectar con la telefonista 3031 Nos conectamos con la 3032
telefonista:127.0.0.1:4567 3033 Ingrese números -1 termina 3034
123 3035 432 3036 -1 3037
Programa terminado 3038 gus@gusgus ~$ 3039
Codificación: 3040
Como dijimos antes la implementación y 3041 codificación de este ejemplo necesitará de 3042
una conexión 3043 de red para poder comprender mejor el uso de 3044 este tipo de estructuras, no es necesario que 3045
dispongamos 3046 de una red para llevar a cabo este programa, 3047
ya que una PC puede actuar como una red de 3048 1 sola 3049
máquina, en este caso usaremos la dirección 3050 de red local (loopback) que existe en casi 3051
todos los sistemas 3052 operativos en los que corre Java. Esta 3053
dirección especial, permite conectarse por 3054
medio de los protocolos 3055 de red a la misma máquina en caso que 3056
estemos en un laboratorio de informática y 3057
dispongamos de la 3058
información de las direcciones ip de las otras 3059 PCs de la red sería interesante que se 3060
trabajara en grupos 3061
89
de dos, para poder apreciar la conexión 3062
remota. 3063
Nota: Queda como tarea para el lector 3064 revisar los métodos y propiedades de la 3065
clase o tipo de 3066
datos Socket y ServerSocket. 3067 Para establecer una conexión de red es 3068
necesario que alguien esté escuchando en un 3069 puerto, estos 3070
puertos son un concepto abstracto que 3071
podemos asimilarlo comparándolo con un 3072 puerto real donde 3073
llegan barcos, dichos barcos una vez que 3074 llegan son atendidos y siempre que haya 3075
quien atenderlos 3076
podrá entrar otro. 3077 En este caso solo esperaremos una única 3078
conexión en el puerto, y cuando esta se 3079
establezca no 3080 esperaremos ninguna otra. 3081
La clase ServerSocket nos permitirá fabricar 3082
un objeto que podrá esperar una conexión, y 3083 cuando 3084
esta llegue podemos abrirla por medio del 3085 objeto resultante Socket (conexión). El puerto 3086
de escucha en 3087
este ejemplo será: 4567, muchos firewalls y 3088 mecanismos de protección de red pueden 3089
bloquear el acceso 3090
a estos puertos, así que cualquier cosa 3091 preguntamos al administrador de la red, por 3092
otro lado no podemos 3093
90
usar un puerto más bajo inferior a los 1024 3094
porque será necesario por lo general permisos 3095
especiales en 3096 el sistema operativo. 3097
Telefonista: 3098 1. package com.compunauta.aprendiendojava; 3099
2. import java.io.*; 3100 3. import java.net.*; 3101
4. /** 3102 5. * <p>Título: Aprendiendo Java</p> 3103
6. * <p>Descripción: Ejemplos del Libro Aprendiendo 3104 Java de Compunauta</p> 3105
7. * <p>Copyright: Copyright (c) 2006 3106 www.compunauta.com</p> 3107
8. * <p>Empresa: COMPUNAUTA</p> 3108 9. * @author Gustavo Guillermo Pérez 3109
10. * @version 2006.01.01 3110 11. */ 3111 12. 3112
13.public class Cap3_sock_tel { 3113 14.//Declaramos unas variables globales a este tipo de 3114
datos 3115 15.public static int PORT=4567; 3116
16.public static int BUFF_SIZE=40; 3117 17.public static int TIMER_SLEEP=60*1000; 3118
//60sx1000ms 3119 18.public static int buff_elem=0; 3120
19.public static int[] buffer=new int[BUFF_SIZE]; 3121 20. 3122
21. public static void main(String[] args) { 3123 22. //Declaramos la variable socket (será un puntero a 3124
objeto) 3125 23. Socket skt=(Socket)null; 3126
24. //Declaramos vacío el servidor de sockets para 3127 inicializarlo 3128
25. ServerSocket Ss=(ServerSocket)null; 3129 26. 3130
91
27. //Tratamos de escuchar el puerto definido por la 3131 variable PORT 3132
28. System.err.println("Escuchando el puerto:"+PORT); 3133 29. try {Ss = new ServerSocket(PORT);} 3134
30. catch (IOException ex) { 3135 31. System.out.println("El sistema no permite abrir el 3136
puerto"); 3137 32. System.exit(-1);} 3138
33. 3139 34. //Si no ocurrió error arriba entonces esperamos a la 3140
secretaria 3141 35. System.err.println("Esperando conexión..."); 3142
36. try {skt = Ss.accept();} 3143 37. catch (IOException ex1) { 3144
38. ex1.printStackTrace(System.err); 3145 39. System.exit(-1);} 3146
40. 3147 41. //Si no ocurrió error arriba la secretaria está lista 3148
para enviar 3149 42. System.err.println("Conectado... Esperando 3150
teléfonos"); 3151 43. try { 3152
44. ObjectInputStream datos = new 3153 ObjectInputStream(skt.getInputStream()); 3154
45. long timer=0; 3155 46. boolean timer_on=false; 3156
47. while (true){ 3157 48. if((skt.isClosed() && (buff_elem<1)) || (buffer[0]==-3158
1)){ 3159 49. //Terminamos el programa si la secretaria terminó 3160 50. System.err.println("Ultima llamada, nos vamos... 3161
terminado"); 3162 51. System.exit(0); 3163
52. } 3164 53. //si hay teléfonos los guardamos 3165
54. if(datos.available()>0){ 3166 55. put_tel(datos.readInt());} 3167
56. if(timer_on){ 3168
92
57. //si el timer funciona no hacer nada, si se pasó 3169 pararlo 3170 58. if 3171
((timer+TIMER_SLEEP)<System.currentTimeMillis()){ti3172 mer_on=false;} 3173
59. }else{ 3174 60. //Si el timer está apagado, mostramos un tel si es 3175
que hay 3176 61. if (buff_elem>0){System.out.println("Secretaria 3177
llamando al 3178 tel:"+get_tel()); 3179
62. //Encendemos el timer y guardamos la hora en que 3180 empezó 3181
63. timer_on=true; 3182 64. timer=System.currentTimeMillis();} 3183
65. } 3184 66. //Pausamos 100ms para no sobrecargar el 3185
procesador 3186 67. try {Thread.sleep(100);} 3187
68. catch (InterruptedException ex3) {} 3188 69. }//fin del bloque eterno 3189
70. }catch (IOException ex2) { 3190 71. ex2.printStackTrace(System.err); 3191
72. System.exit(-1); 3192 73. } 3193 74. 3194
75. }//fin del método principal 3195 76. 3196
77.//Funciones o métodos auxiliares 3197 78.public static void put_tel(int tel){ 3198
79.//Si se supera el espacio producir un error 3199 80.if (BUFF_SIZE<(buff_elem+1)){ 3200
81.System.err.println("Buffer overrun: El buffer se llenó 3201 demasiado rápido"); 3202 82.System.exit(-1);} 3203
83.//guardamos el tel y aumentamos en uno el contador 3204 84.buffer[buff_elem++]=tel; 3205
85.} 3206 86. 3207
93
87.public static int get_tel(){ 3208 88. //almacenamos el primer teléfono 3209
89. int tel=buffer[0]; 3210 90. //quitamos uno al contador de elementos 3211
91. buff_elem--; 3212 92. //recorremos los otros elementos 3213
93. for (int i=0;i<buff_elem;i++) buffer[i]=buffer[i+1]; 3214 94. //devolvemos el primer teléfono 3215
95. return tel; 3216 96.} 3217 97. 3218
98.}//final de la clase 3219 De las líneas 15 a la 19 se declaran las 3220
variables globales que serán accesibles por 3221
todos los 3222 métodos estáticos de la clase como ser el 3223
puerto de escucha, el tamaño del buffer y el 3224
verdadero buffer 3225 donde utilizamos el tamaño definido para 3226
crearlo, recordemos que una vez definido el 3227
arreglo que 3228 actuará de buffer no podemos expandirlo o 3229
reducirlo, por ello el cálculo previo para 3230
estimar su máxima 3231 cantidad de datos. También se define el 3232
tiempo en milisegundos que esperaremos 3233 antes de mostrar en 3234
pantalla el siguiente teléfono. 3235
A partir de la línea 21 comienza el método 3236 principal, el cual se ejecutará paso seguido de 3237
inicializar las variables globales. Revisemos la 3238
línea 23, la declaración de la variable skt, no 3239 estamos 3240
94
inicializando el objeto de la biblioteca, sino 3241
que lo estamos apuntando a un objeto 3242
especial de tipo nulo, 3243 este objeto llamado null es un objeto vacío 3244 que no posee propiedades de ningún tipo y 3245
cada vez que 3246 queramos operar sobre el producirá un error 3247
de puntero nulo, entonces ¿porqué lo 3248 necesitamos?. El 3249
compilador no es lo suficientemente 3250
inteligente como para detectar que lo 3251 inicializaremos en un bloque 3252
de código futuro y necesitamos declararlo en 3253 este punto de nuestro método principal, 3254
porque todo lo que 3255
se declara en bloques especiales como 3256 try{}catch(){} es local y desaparece fuera de 3257
ellos. 3258
En la línea 25 declaramos el objeto de la 3259 biblioteca ServerSocket que escuchará y 3260
devolverá un 3261
objeto del tipo Socket, usamos el mismo 3262 objeto nulo para inicializarlo. 3263
Desde la línea 27 a la 32 intentamos crear el 3264 objeto ServerSocket y lo que es más 3265
importante, 3266
detectar si hubo o no un error por parte del 3267 sistema ya que no podremos continuar si se 3268
produce un error, 3269
como podemos ver en nuestro bloque de 3270 control de errores salimos si el sistema no nos 3271
permite abrir 3272
95
dicho puerto, en el caso que tengamos algún 3273
tipo de protección de red tendremos que 3274
desactivarla 3275 temporalmente para poder trabajar. 3276
Entre las líneas 34 y 39 nos encargamos de 3277
esperar una conexión remota, nuevamente es 3278 necesario 3279
capturar las posibles excepciones de error que 3280 puedan producirse, es obligatorio por el 3281
compilador 3282
manejar las excepciones declaradas por 3283 ServerSocket, como podemos ver, la función 3284
accept(); de 3285 ServerSocket aceptará una conexión y esa 3286
conexión la almacenaremos en el apuntador 3287
skt, teniendo 3288 ahora correctamente inicializado dicho 3289
apuntador podemos usar las características 3290
de la conexión. 3291 A partir de la línea 42 comenzamos la 3292
operación de lectura de la conexión de red y 3293
de la impresión 3294 en pantalla de los teléfonos. 3295
Ya habíamos visto los objetos del tipo 3296 InputStream para la lectura de texto desde el 3297
teclado, en 3298
este caso lo usaremos para la lectura desde la 3299 conexión, solo que para practicar, utilizaremos 3300
un objeto 3301
de la misma familia pero del tipo 3302 ObjectInputStream que nos permitiría enviar 3303
objetos a través del 3304
96
canal o flujo de datos. 3305
El objeto skt provee la función 3306
getInputStream(); que nos devolverá el Objeto 3307 del tipo 3308
InputStream que necesita el objeto de la 3309
biblioteca del tipo ObjectInputStream para 3310 ser construido. 3311
En la línea 45 declaramos una variable de tipo 3312 entero largo (long) timer que utilizaremos para 3313
medir el tiempo y así crear nuestro 3314
temporizador, le damos un valor inicial. 3315 En la línea 46 declaramos una variable 3316
booleana timer_on que nos servirá de 3317 bandera para saber 3318
el estado del temporizador, si es que está 3319
activo (true) o parado (false). Lo inicializamos 3320 en parado 3321
porque no tenemos teléfonos hasta que la 3322
secretaria los comience a escribir. 3323 En la línea 47 se comienza un bloque del tipo 3324
“mientras”, while(){} el cual deseamos que sea 3325
infinito porque leeremos datos hasta que la 3326 secretaria envíe la señal de fin, pero mientras 3327
tengamos 3328 teléfonos para mostrar en el buffer no 3329
podremos dejar de mostrarlos, así que para 3330
mejor comprensión del 3331 código, el bloque while(true){} se ejecutará 3332
por siempre a menos que el programa decida 3333
terminar. 3334 Revisemos el código de la línea 48 a la 52, en 3335
este bloque comparamos dos condiciones 3336
97
importantes para decidir si el programa debe 3337
salir o no, la primera es una condición doble, 3338
por eso está 3339 encerrada entre paréntesis, es decir si la 3340 conexión está cerrada y la cantidad de 3341
elementos del buffer es 3342 inferior a 1 o sucede que el elemento cero del 3343 buffer es el número -1 que indica la secretaria 3344
que 3345
terminó entonces nos vamos porque es el 3346
último elemento y no es necesario mostrarlo. 3347 El siguiente bloque desde la línea 54,55 3348
almacenamos un número entero desde la 3349 conexión de red 3350
datos, sólo si es que hay datos disponibles, 3351
eso lo revisamos con la función available(); 3352 que no se 3353
quedará esperando, si existen o no datos 3354
disponibles de todas maneras el programa 3355 sigue su curso. 3356
El timer, entre las líneas 58 a la 65, funciona 3357
de la siguiente manera, cuando queremos 3358 comenzar a 3359
medir el tiempo, almacenamos dentro de la 3360 variable timer la hora actual medida en 3361
milisegundos, ese 3362
dato lo obtenemos con la función del objeto 3363 system, currentTimeMillis(), si al timer, le 3364
sumamos la 3365
cantidad de tiempo que queremos esperar, 3366 ese valor siempre será más grande que la 3367
hora actual, hasta 3368
98
que se pase el tiempo, eso es lo que 3369
comparamos en el bloque if(){}, caso contrario 3370
nos preparamos para 3371 ver si es necesario encender el timer y mostrar 3372 teléfonos, que sólo sucederá si hay más de 1 3373
elemento en 3374 el buffer, recordemos que en buff_elem 3375
almacenamos la cantidad de elementos de 3376 nuestra memoria 3377
temporal. 3378
En las líneas 67,68 incluimos otro bloque de 3379 control de errores obligatorio porque 3380
utilizaremos 3381 otra función de la biblioteca de Java que 3382
pertenece a la clase Thread (hilo) esa función 3383
detiene la 3384 ejecución del programa una cierta cantidad de 3385
milisegundos, el uso de este pequeño retardo 3386
de 100 3387 milisegundos es para no sobrecargar el 3388
procesador, ya que estaríamos ejecutando 3389
nuestro bucle 3390 while(true){} infinidades de veces en 1 único 3391 segundo lo cual no es necesario ya que la 3392
secretaria no es 3393
tan veloz y dejamos libre el procesador para el 3394
sistema operativo. 3395 En la línea 69 termina el bloque eterno 3396
while(true){} y el bloque de control de errores 3397
que lo 3398
99
contiene, dado el caso que se produzca un 3399
error dentro del bloque será necesario 3400
terminar el programa. 3401 Los métodos auxiliares: 3402
public static void put_tel(int tel){ 3403 Esta función agregará un teléfono en la 3404 memoria temporal, en nuestro buffer, 3405
haciendo una cierta 3406
detección de errores, en el caso que el buffer 3407
no sea lo suficientemente grande como para 3408
almacenar el 3409 próximo dato, en este caso el programa se 3410
sale con error. 3411 Si esto no sucede, la línea más importante de 3412
esta función es: 3413 buffer[buff_elem++]=tel; 3414
Donde como vimos al principio de este libro el 3415 signo ++ a la derecha de buff_elem simboliza 3416
que 3417
primero se utilizará el valor y después se 3418
incrementará, entonces en una sola línea 3419
representamos las dos 3420 operaciones buffer[buff_elem]tel; buff_elem++; 3421
public static int get_tel(){ 3422 Esta función extraerá un elemento del buffer, 3423
pero al mismo tiempo que lo extrae debe 3424 posicionar 3425
los demás elementos hacia el inicio del 3426 arreglo. 3427
Tampoco hacemos la comprobación de que 3428 no haya elementos en el buffer porque la 3429
hacemos en 3430
100
el código cada vez que vemos si hay teléfonos 3431
para mostrar, aunque deberíamos por buena 3432
práctica 3433 porque si este es un prototipo y nuestro 3434
programa irá creciendo, entonces tal vez se 3435
nos escape revisar. 3436 Almacenamos de manera temporal el teléfono 3437
próximo antes de recorrer los datos: 3438 int tel=buffer[0]; 3439
Después de eso quitamos uno al apuntador de 3440
elementos, y lo quitamos antes porque para 3441 subir los 3442
datos sumaremos uno al índice que 3443 recorremos para acomodar los datos y 3444
tendríamos que estar 3445
revisando que el índice no supere buff_elem-3446 1, como esa condición se compararía cada 3447
vez que pasamos 3448 por un valor del índice estaríamos ejecutando 3449
innecesariamente una resta que podríamos 3450 hacer antes. 3451
Una vez terminado devolvemos el teléfono 3452
que almacenamos antes que desapareciera. 3453
Nota: Es incorrecto el manejo de error en la 3454 función put_tel, ya que en Java existe un 3455 modelo de excepciones que deben ser 3456
lanzadas y capturadas como en cualquier 3457
bloque de control de errores, si no 3458
corroboramos el índice Java producirá una 3459
IndexOutOfBoundException que de todas 3460 maneras terminará el programa. 3461
Secretaria: 3462 1. package com.compunauta.aprendiendojava; 3463
101
2. import java.io.*; 3464 3. import java.net.*; 3465
4. /** 3466 5. * <p>Título: Aprendiendo Java</p> 3467
6. * <p>Descripción: Ejemplos del Libro Aprendiendo 3468 Java de Compunauta</p> 3469
7. * <p>Copyright: Copyright (c) 2006 3470 www.compunauta.com</p> 3471
8. * <p>Empresa: COMPUNAUTA</p> 3472 9. * @author Gustavo Guillermo Pérez 3473
10. * @version 2006.01.01 3474 11. */ 3475 12. 3476
13.public class Cap3_sock_sec { 3477 14.//Declaramos unas variables globales a este tipo de 3478
datos 3479 15.public static int PORT=4567; 3480
16.public static String HOST="127.0.0.1"; 3481 17. 3482
18. public static void main(String[] args) { 3483 19. System.err.println("Intentando conectar con la 3484
telefonista"); 3485 20. Socket skt=(Socket)null; 3486
21. try {skt = new Socket(HOST, PORT);} 3487 22. catch (Exception ex) { 3488
23. System.err.println("La telefonista no está en línea"); 3489 24. System.exit(-1); 3490
25. } 3491 26. 3492
27. int tel; 3493 28. BufferedReader teclado=new BufferedReader(new 3494
InputStreamReader(System.in)); 3495 29. try { 3496
30. ObjectOutputStream datos = new 3497 ObjectOutputStream(skt.getOutputStream()); 3498
31. System.err.println("Nos conectamos con la 3499 telefonista:"+HOST 3500
+":"+PORT); 3501 32. System.err.println("Ingrese números -1 termina"); 3502
102
33. while (true){ 3503 34. if((tel=leerInt(teclado))==-1){ 3504
35. System.err.println("Programa terminado"); 3505 36. datos.writeInt(-1); 3506
37. datos.flush(); 3507 38. datos.close(); 3508
39. skt.close(); 3509 40. System.exit(0); 3510
41. }else{ 3511 42. datos.writeInt(tel); 3512
43. datos.flush(); 3513 44. } 3514
45. }//fin de la lectura eterna 3515 46. }catch (IOException ex1) 3516
{ex1.printStackTrace(System.err);} 3517 47. 3518
48. }//fin del método principal 3519 49. 3520
50.//Funciones o métodos auxiliares 3521 51.public static int leerInt(BufferedReader buff){ 3522
52. int lee=0; 3523 53. boolean error; 3524
54. do { 3525 55. error=false; 3526
56. try {lee = Integer.parseInt(buff.readLine());} 3527 57. catch (NumberFormatException ex) { 3528
58. System.err.println("Entrada erronea, repetir:?"); 3529 59. error=true;} 3530
60. catch (Exception 3531 ex){ex.printStackTrace(System.err);} 3532
61. } while (error); 3533 62. return lee; 3534
63. }//final de la funcion leer 3535 64. 3536
65.}//final de la clase 3537 Descripción del funcionamiento: 3538
103
En las líneas 15 y 16 declaramos las variables 3539
globales que almacenarán el puerto y la 3540
dirección 3541 de red donde nos conectaremos, en este caso 3542 la dirección 127.0.0.1 es universal y permite 3543
conectarse a 3544 la misma máquina así que podremos ejecutar 3545
el programa de la secretaria y la telefonista en 3546 la misma 3547
PC en consolas de comandos diferentes, si 3548
estamos en el laboratorio con más de 1 PC en 3549 RED, entonces 3550
en ese número pondremos el que nos 3551 comente el administrador del sistema para 3552
conectarnos a la PC que 3553
correrá la telefonista. 3554 En la línea 18 comienza nuestro método 3555
principal y de la misma manera que en el 3556
programa 3557 anterior definimos el Socket (skt) como un 3558
elemento vacío sin inicializar, ya que estamos 3559
obligados a 3560 revisar errores. 3561
Entre las líneas 21 a 25 comprobamos que se 3562 pueda hacer una conexión al puerto y 3563
dirección de 3564
red indicados, puede suceder que el error no 3565 sea exactamente que la telefonista no está en 3566
línea y que el 3567
sistema operativo esté denegando el acceso a 3568 conectarse al exterior, por ello revisar el 3569
firewall del 3570
104
sistema o los permisos necesarios. 3571
Si nos pudimos conectar el programa siguió 3572
adelante y procedemos a crear un objeto 3573 BufferedReader para manipular la entrada por 3574
teclado y declaramos una variable tel que 3575
almacenará un 3576 teléfono para enviar. 3577
En la línea 29 comienza el bloque donde 3578 abriremos la conexión de datos remota por 3579
medio de un 3580
flujo de datos del tipo ObjetOutputStream. 3581 Como en el componente anterior utilizamos un 3582
bucle eterno para la ejecución del programa 3583 que 3584
saldrá por otros mecanismos. (línea 33). 3585
En la línea 34, asignamos el valor que se lee 3586 por teclado a la variable tel, ese segmento 3587
está entre 3588
paréntesis porque porque ese mismo valor 3589 asignado lo compararemos antes de 3590
proseguir, podríamos 3591
haber hecho primero la asignación y después 3592 la comparación. 3593
Si la secretaria escribió -1 enviamos el -1 a la 3594 telefonista para avisarle que terminamos, 3595
(línea 36), 3596
la orden datos.fluxh(); vacía los datos de 3597 memoria RAM al flujo de datos 3598
inmediatamente y en las 3599
líneas 38 y 39 cerramos debidamente el flujo 3600 de datos y la conexión de red antes de salir 3601
sin producir 3602
105
error, salir con el código 0 es no producir error. 3603
En la línea 41 comienza el bloque de datos 3604
que se ejecutará caso contrario a que la 3605 secretaria 3606
ingrese un -1. Donde podemos ver que 3607
escribimos en el flujo de datos el número 3608 entero correspondiente 3609
al teléfono y obligamos la escritura inmediata 3610 con la orden flush();. 3611
Termina el bucle etenro while(true){} termina 3612
el bloque de control de errores y el método 3613 principal, a continuación están la función 3614
auxiliar leerInt que no explicaremos porque es 3615 la misma que 3616
vimos en el capítulo anterior. 3617
Nota: Veremos con más detalles el uso de 3618 sockets durante el transcurso del libro, no 3619
ahondaremos en ello ahora. Queda como 3620
ejercicio para el lector producir el error de 3621 Buffer Overrun y revisar en la 3622
documentación electrónica los métodos y 3623
objetos 3624 utilizados de la biblioteca de Java. 3625
Implementación del buffer tipo LIFO (La 3626 pila, último en llegar es primero en salir) 3627
Modifiquemos el ejemplo anterior para que 3628
ahora sean una bibliotecaria y su asistente, la 3629 bibliotecaria recibirá libros nuevos para 3630
catalogar y los enviará a apilar en el escritorio 3631
de la asistente, la 3632
106
asistente tendrá un minuto para leer el nombre 3633
de la etiqueta que envió la bibliotecaria a 3634
través de la red 3635 y ordenarlo, es visto que los libros ahora 3636
saldrán en forma de pila y no cola de espera, 3637
el límite será la 3638 altura de la asistente que hace las tarjetas 3639
sentada, pero no lo calcularemos :p. 3640 Libros en total 24, se envía el contenido de la 3641
tarjeta en modo texto. 3642
Asistente: 3643 gus@gusgus ~$ java 3644
com.compunauta.aprendiendojava.Cap3_lifo_3645 asis 3646
Escuchando el puerto:4567 3647 Esperando conexión... 3648
Conectado... Esperando títulos 3649 Libro:Introducción a la física 3650 No hay más, nos vamos cuando 3651
terminemos... 3652 Libro:Aprendiendo Java 3653
Libro:Lectura I 3654 Libro:Asambleas 3655
Ya no es necesario esperar, terminado... 3656 gus@gusgus ~$ 3657
Bibliotecaria: 3658 gus@gusgus ~$ java 3659
com.compunauta.aprendiendojava.Cap3_lifo_3660 bib 3661
Intentando conectar con la asistente 3662 Nos conectamos con la 3663
asistente:127.0.0.1:4567 3664 Ingrese Títulos (línea vacía termina) 3665
Introducción a la física 3666 Asambleas 3667 Lectura I 3668
Aprendiendo Java 3669
107
Programa terminado 3670 gus@gusgus ~$ 3671
Asistente: 3672 1. package com.compunauta.aprendiendojava; 3673
2. import java.io.*; 3674 3. import java.net.*; 3675
4. /** 3676 5. * <p>Título: Aprendiendo Java</p> 3677
6. * <p>Descripción: Ejemplos del Libro Aprendiendo 3678 Java de Compunauta</p> 3679
7. * <p>Copyright: Copyright (c) 2006 3680 www.compunauta.com</p> 3681
8. * <p>Empresa: COMPUNAUTA</p> 3682 9. * @author Gustavo Guillermo Pérez 3683
10. * @version 2006.01.01 3684 11. */ 3685 12. 3686
13.public class Cap3_lifo_asis { 3687 14.//Declaramos unas variables globales a este tipo de 3688
datos 3689 15.public static int PORT=4567; 3690
16.public static int BUFF_SIZE=24; 3691 17.public static int TIMER_SLEEP=60*1000; 3692
//60sx1000ms 3693 18.public static int buff_elem=0; 3694
19.public static String[] buffer=new 3695 String[BUFF_SIZE]; 3696
20. 3697 21. public static void main(String[] args) { 3698
22. //Declaramos la variable socket (será un puntero a 3699 objeto) 3700
23. Socket skt=(Socket)null; 3701 24. //Declaramos vacío el servidor de sockets para 3702
inicializarlo 3703 25. ServerSocket Ss=(ServerSocket)null; 3704
26. 3705 27. //Tratamos de escuchar el puerto definido por la 3706
variable PORT 3707 28. System.err.println("Escuchando el puerto:"+PORT); 3708
108
29. try {Ss = new ServerSocket(PORT);} 3709 30. catch (IOException ex) { 3710
31. System.out.println("El sistema no permite abrir el 3711 puerto"); 3712
32. System.exit(-1);} 3713 33. 3714
34. //Si no ocurrió error arriba entonces esperamos a la 3715 secretaria 3716
35. System.err.println("Esperando conexión..."); 3717 36. try {skt = Ss.accept();} 3718
37. catch (IOException ex1) { 3719 38. ex1.printStackTrace(System.err); 3720
39. System.exit(-1);} 3721 40. 3722
41. //Si no ocurrió error arriba la secretaria está lista 3723 para enviar 3724
42. System.err.println("Conectado... Esperando títulos"); 3725 43. try { 3726
44. BufferedReader datos = new BufferedReader(new 3727 InputStreamReader((skt.getInputStream()))); 3728
45. long timer=0; 3729 46. boolean timer_on=false; 3730
47. boolean ultimo=false; 3731 48. while (true){ 3732
49. if(!ultimo && (skt.isClosed() || ((buff_elem>0) && 3733 buffer[buff_elem-1]!=null && buffer[buff_elem-3734
1].equals("fin")))){ 3735 50. //Terminamos el programa si la bibliotecaria terminó 3736 51. System.err.println("No hay más, nos vamos cuando 3737
terminemos..."); 3738 52. //el libro fin no se debe guardar es el aviso 3739
53. buff_elem--; 3740 54. ultimo=true; 3741
55. } 3742 56. if(ultimo && (buff_elem==0)){ 3743
57. System.err.println("Ya no es necesario esperar, 3744 terminado..."); 3745
58. System.exit(0);} 3746 59. //si hay títulos los guardamos 3747
109
60. if(!ultimo && datos.ready()){ 3748 61. put_tit(datos.readLine());} 3749
62. if(timer_on){ 3750 63. //si el timer funciona no hacer nada, si se pasó 3751
pararlo 3752 64. if 3753
((timer+TIMER_SLEEP)<System.currentTimeMillis()) 3754 {timer_on=false;} 3755
65. }else{ 3756 66. //Si el timer está apagado, mostramos un tel si es 3757
que hay 3758 67. if 3759
(buff_elem>0){System.out.println("Libro:"+get_tit()); 3760 68. //Encendemos el timer y guardamos la hora en que 3761
empezó 3762 69. timer_on=true; 3763
70. timer=System.currentTimeMillis();} 3764 71. } 3765
72. //Pausamos 100ms para no sobrecargar el 3766 procesador 3767
73. try {Thread.sleep(100);} 3768 74. catch (InterruptedException ex3) {} 3769
75. }//fin del bloque eterno 3770 76. }catch (Exception ex2) { 3771
77. ex2.printStackTrace(System.err); 3772 78. System.exit(-1); 3773
79. } 3774 80. 3775
81. }//fin del método principal 3776 82. 3777 83. 3778
84.//Funciones o métodos auxiliares 3779 85.public static void put_tit(String tit){ 3780
86.//Si se supera el espacio producir un error 3781 87.if (BUFF_SIZE<(buff_elem+1)){ 3782
88.System.err.println("Buffer overrun: El buffer se llenó 3783 demasiado rápido"); 3784 89.System.exit(-1);} 3785
90.//guardamos el tel y aumentamos en uno el contador 3786
110
91.buffer[buff_elem++]=tit; 3787 92.} 3788 93. 3789
94.public static String get_tit(){ 3790 95. //quitamos uno al contador de elementos 3791
96. //devolvemos el último libro 3792 97. return buffer[--buff_elem]; 3793
98.} 3794 99. 3795
100.}//final de la clase 3796 Descripción del funcionamiento: 3797
La declaración de variables globales a la clase 3798 o tipo de datos se realiza entre las líneas 15 y 3799
19. 3800
El método principal comienza en la línea 21, y 3801 declaramos los objetos del tipo Socket y 3802
ServerSocket como en el apartado anterior. 3803 Desde la línea 28 a la 32 intentamos abrir el 3804
puerto para escuchar conexiones entrantes, si 3805
sucede 3806
un error nos salimos. 3807 Si no hay errores, entre la línea 35 y 38 3808
esperamos una conexión entrante con su 3809 respectivo bloque 3810
de control de errores. 3811 Como la función accept();detendrá el 3812
programa hasta que arribe una conexión, si 3813
estamos 3814 ejecutando el bloque principal entre las líneas 3815
43 y siguientes, es porque se recibió una 3816
conexión. En el 3817 respectivo bloque de control de errores 3818
iniciamos el flujo de datos que usaremos para 3819
ir recibiendo 3820
111
renglones, en este caso usamos el mismo tipo 3821
de objeto que nos permite leer líneas desde el 3822
teclado, solo 3823 que ahora las leeremos desde la conexión de 3824
red. 3825
Declaramos algunas cuantas variables para 3826 crear nuestro temporizador de 1 minuto igual 3827
que en el 3828 ejemplo anterior, y definimos una variable 3829
ultimo que nos avisará cuando los libros son 3830
todos. 3831 En este caso la bandera que usamos para 3832
saber que hemos terminado por parte de la 3833 bibliotecaria 3834
es la palabra clave “fin”, y por supuesto 3835
revisamos que la conexión no esté cerrada, 3836 que haya elementos 3837
y todo eso antes de proceder a retirar un libro 3838
del buffer y enseñarlo en pantalla. La bandera 3839 binaria 3840
ultimo solo se activará en la condición 3841
anterior para asegurar que seguiremos 3842 mostrando títulos 3843
mientras, es una variación respecto del 3844 ejemplo anterior para ver otras maneras de 3845
resolver algo similar. 3846
Si, el ultimo elemento ya llegó y no hay más 3847 en la memoria temporal, entonces nos salimos 3848
del 3849
programa. (líneas 56-58). 3850
112
Si no es el ultimo elemento y hay datos 3851
disponibles en el flujo de datos de red, 3852
entonces leer una 3853 línea y ponerla en la memoria temporal. 3854
Si el timer está encendido entonces 3855
procedemos igual que antes, el único cambio 3856 sustancial serán 3857
las funciones que guardan y extraen los datos 3858 del buffer. 3859
La única función que cambia es la que quita 3860
elementos del buffer, que es mucho más 3861 simple que 3862
antes. 3863 return buffer[--buff_elem]; 3864
Donde estamos decrementando el contador 3865
de elementos antes (el -- está a la izquierda) y 3866 como 3867
sabemos que los arreglos se acceden desde 3868 el 0 a cantidad-1 entonces es correcto el 3869
resultado devuelto. 3870 Bibliotecaria: 3871
1. package com.compunauta.aprendiendojava; 3872 2. import java.io.*; 3873
3. import java.net.*; 3874 4. /** 3875
5. * <p>Título: Aprendiendo Java</p> 3876 6. * <p>Descripción: Ejemplos del Libro Aprendiendo 3877
Java de Compunauta</p> 3878 7. * <p>Copyright: Copyright (c) 2006 3879
www.compunauta.com</p> 3880 8. * <p>Empresa: COMPUNAUTA</p> 3881 9. * @author Gustavo Guillermo Pérez 3882
10. * @version 2006.01.01 3883 11. */ 3884 12. 3885
113
13.public class Cap3_lifo_bib { 3886 14.//Declaramos unas variables globales a este tipo de 3887
datos 3888 15.public static int PORT=4567; 3889
16.public static String HOST="127.0.0.1"; 3890 17. 3891
18. public static void main(String[] args) { 3892 19. System.err.println("Intentando conectar con la 3893
asistente"); 3894 20. Socket skt=(Socket)null; 3895
21. try {skt = new Socket(HOST, PORT);} 3896 22. catch (Exception ex) { 3897
23. System.err.println("La asistente no está en línea"); 3898 24. System.exit(-1); 3899
25. } 3900 26. 3901
27. String titulo; 3902 28. BufferedReader teclado=new BufferedReader(new 3903
InputStreamReader(System.in)); 3904 29. try { 3905
30. PrintWriter datos = new 3906 PrintWriter(skt.getOutputStream()); 3907
31. System.err.println("Nos conectamos con la 3908 asistente:"+HOST+":"+PORT); 3909
32. System.err.println("Ingrese Títulos (línea vacía 3910 termina)"); 3911
33. while (true){ 3912 34. if((titulo=leerLinea(teclado)).length()==0){ 3913 35. System.err.println("Programa terminado"); 3914
36. datos.println("fin"); 3915 37. datos.flush(); 3916 38. datos.close(); 3917
39. skt.close(); 3918 40. System.exit(0); 3919
41. }else{ 3920 42. datos.println(titulo); 3921
43. datos.flush(); 3922 44. } 3923
45. }//fin de la lectura eterna 3924
114
46. }catch (IOException ex1) 3925 {ex1.printStackTrace(System.err);} 3926
47. 3927 48. }//fin del método principal 3928
49. 3929 50.//Funciones o métodos auxiliares 3930
51.public static String leerLinea(BufferedReader buff){ 3931 52. try {return buff.readLine();} 3932
53. catch (Exception 3933 ex){ex.printStackTrace(System.err);} 3934
54. return ""; 3935 55. }//final de la función leer 3936
56. 3937 57.}//final de la clase 3938
Esta implementación es idéntica a la de la 3939
secretaria del ejemplo anterior, solo que para 3940 variar 3941
utilizamos otro tipo de Objeto para el flujo de 3942 datos. 3943
Implementación de una Lista de datos. 3944
En este caso la memoria temporal será una 3945
simple lista, se pretenderá que el usuario 3946
ingrese una 3947
lista de nombres y que en cualquier momento 3948 se pueda buscar, borrar, o agregar elementos. 3949
Salida por pantalla: 3950 gus@gusgus ~$ java 3951
com.compunauta.aprendiendojava.Cap3_lista 3952 SELECCIONE UNA OPCIÓN: 3953
1) Ingresar un elemento al listado 3954 2) Listar los elementos de la lista 3955 3) Borrar un elemento de la lista 3956
0) Salir 3957 opción? 3958
1 3959 Dato:? 3960 Azul 3961
115
opción? 3962 1 3963
Dato:? 3964 Celeste 3965 opción? 3966
1 3967 Dato:? 3968 Caffe 3969
opción? 3970 1 3971
Dato:? 3972 Osos 3973
opción? 3974 2 3975
Item[0]:[Azul] 3976 Item[1]:[Celeste] 3977 Item[2]:[Caffe] 3978 Item[3]:[Osos] 3979
SELECCIONE UNA OPCIÓN: 3980 1) Ingresar un elemento al listado 3981 2) Listar los elementos de la lista 3982 3) Borrar un elemento de la lista 3983
0) Salir 3984 opción? 3985
3 3986 Item a borrar:? 3987
2 3988 SELECCIONE UNA OPCIÓN: 3989
1) Ingresar un elemento al listado 3990 2) Listar los elementos de la lista 3991 3) Borrar un elemento de la lista 3992
0) Salir 3993 opción? 3994
2 3995 Item[0]:[Azul] 3996
Item[1]:[Celeste] 3997 Item[2]:[Osos] 3998 gus@gusgus ~$ 3999
Ahora veamos el código: 4000
116
1. package com.compunauta.aprendiendojava; 4001 2. import java.io.*; 4002
3. 4003 4. /** 4004
5. * <p>Título: Aprendiendo Java</p> 4005 6. * <p>Descripción: Ejemplos del Libro Aprendiendo 4006
Java de Compunauta</p> 4007 7. * <p>Copyright: Copyright (c) 2006 4008
www.compunauta.com</p> 4009 8. * <p>Empresa: COMPUNAUTA</p> 4010 9. * @author Gustavo Guillermo Pérez 4011
10. * @version 2006.01.01 4012 11. */ 4013 12. 4014
13.public class Cap3_lista { 4015 14. //Variables globales 4016
15. public static int MAX=15; 4017 16. public static String[] lista=new String[MAX]; 4018
17. public static int lista_elem=0; 4019 18. 4020
19. public static void main(String[] args) { 4021 20. BufferedReader teclado=new BufferedReader(new 4022
InputStreamReader(System.in)); 4023 21. int op=-1; 4024
22. while(true){ 4025 23. switch (op){ 4026
24. case 1: 4027 25. System.out.println("Dato:?"); 4028 26. ingresa(leerLinea(teclado)); 4029
27. break; 4030 28. case 2: 4031 29. listar(); 4032 30. break; 4033 31. case 3: 4034
32. System.out.println("Item a borrar:?"); 4035 33. borrar(opcion(teclado)); 4036
34. break; 4037 35. case 0: 4038
36. System.out.println("Terminado.."); 4039
117
37. System.exit(0); 4040 38. break; 4041
39. } 4042 40. if(op!=1)imprimir_menu(); 4043
41. System.out.println("opción?"); 4044 42. op = opcion(teclado); 4045 43. }//fin del bucle eterno 4046
44. }//fin del método principal 4047 45. 4048
46. //Funciones auxiliares 4049 47. public static void ingresa(String dato){ 4050
48. lista[lista_elem++]=dato; 4051 49. } 4052 50. 4053
51. public static void listar(){ 4054 52. for (int i=0;i<lista_elem;i++){ 4055
53. System.out.println("Item["+i+"]:["+lista[i]+"]"); 4056 54. } 4057 55. } 4058 56. 4059
57. public static void borrar(int item){ 4060 58. lista_elem--; 4061
59. for (int i=item;i<lista_elem;i++){ 4062 60. lista[i]=lista[i+1]; 4063
61. } 4064 62. } 4065 63. 4066
64. public static void imprimir_menu(){ 4067 65. System.out.println("SELECCIONE UNA OPCIÓN:"); 4068
66. System.out.println("1) Ingresar un elemento al 4069 listado"); 4070
67. System.out.println("2) Listar los elementos de la 4071 lista"); 4072
68. System.out.println("3) Borrar un elemento de la 4073 lista"); 4074
69. System.out.println("0) Salir"); 4075 70. } 4076 71. 4077
72. public static int opcion(BufferedReader buff){ 4078
118
73. int lee=0; 4079 74. boolean error; 4080
75. do { 4081 76. error=false; 4082
77. try {return lee = Integer.parseInt(buff.readLine());} 4083 78. catch (NumberFormatException ex) { 4084
79.System.err.println("Entrada erronea, repetir:?"); 4085 80. error=true;} 4086
81. catch (Exception 4087 ex){ex.printStackTrace(System.err);} 4088
82. } while (error); 4089 83.return lee; 4090
84.}//final de la funcion leer 4091 85. 4092
86.public static String leerLinea(BufferedReader buff){ 4093 87. try {return buff.readLine();} 4094
88. catch (Exception 4095 ex){ex.printStackTrace(System.err);} 4096
89. return ""; 4097 90. }//final de la funcion leer 4098
91. 4099 92.}//fin de la clase 4100
En esta implementación agregamos un menú 4101 de usuario en pantalla que nos permitirá 4102
interoperar 4103 un poco mejor el programa para probar todas 4104 las opciones e incluso hacer experimentos y 4105
expandirlo 4106
con los ejemplos que seguirán a este. 4107
Como antes entre las líneas 15 y 17 4108 declaramos globalmente la lista, sus límites y 4109
el apuntador de 4110
elementos. 4111 Nuestro método principal (línea 20) creará un 4112 objeto como antes hicimos para leer desde el 4113
119
teclado (o podría ser una fuente externa como 4114
la red en los ejemplos anteriores). 4115
Definimos de manera local al método principal 4116 la variable op que almacenará la opción de 4117
menú 4118
que haya escogido el usuario (línea 21). 4119 De la misma manera que antes ejecutamos 4120
indefinidamente el bloque while(true){} aunque 4121 podríamos igual que en todos los casos 4122
anteriores proponer una condición viable que 4123
también sea válida 4124 para terminar el programa como por ejemplo 4125
(op==0). 4126 Cada cláusula case ejecutará la función 4127
correcta, para no producir una reimpresión 4128
excesiva 4129 molesta en la pantalla del menú de usuario 4130
sólo lo reimprimiremos si la opción de menú 4131
no fue la de 4132 agregar datos (línea 40). 4133
En las líneas 41 y 42 imprimimos la leyenda 4134
para solicitar la opción. Podemos utilizar print 4135 en vez 4136
de println para que el ingreso de datos quede 4137 junto al signo de interrogación. 4138
Función ingresa (línea 47), muy simple antes 4139
de aumentar en uno el contador de elementos 4140 se 4141
utiliza el valor del índice para almacenar el 4142
valor del dato que se desea ingresar a la lista. 4143
120
Función listar (línea 51), listamos todos los 4144
elementos de la lista en pantalla indicando su 4145
índice en 4146 el arreglo de texto lista[]. 4147
Función borrar (línea 57), decrementamos en 4148
uno el contador de elementos y recorremos 4149 todos los 4150
elementos restantes a la posición que 4151 queremos eliminar. 4152
Función imprimir_menu() (línea 64), sólo 4153
imprime en pantalla las opciones que compara 4154 el 4155
método principal para realizar acciones. 4156 Función opción (línea 72), idéntica a leerInt 4157 que hemos estado viendo en todos estos 4158
ejemplos. 4159 Función leerLinea (línea 86), idéntica a 4160
leerLinea de todos estos ejemplos anteriores. 4161
Nota: a partir de aquí añadiremos 4162 funciones para experimentar con la lista, es 4163
ejercicio 4164
para el lector agregar a este ejemplo las 4165 entradas del menú y los correctos 4166
mecanismos para ejecutar esa 4167 funcionalidad en los bloques case del 4168
método principal. 4169
Búsqueda de datos 4170
Veremos tres maneras diferentes de encontrar 4171
un elemento en una lista de datos, el primero 4172
es el 4173
121
más lógico, el secuencial, el opuesto, 4174
aleatorio, y el binario cuando la lista lleva 4175
algún tipo de orden. 4176
Búsqueda secuencial 4177
La búsqueda secuencial es el equivalente a 4178 recorrer todos los elementos de la lista y 4179
compararlos 4180
del primero al último de manera que cuando 4181 encontramos el elemento terminamos la 4182
búsqueda. 4183 public static String search(String patron){ 4184
for (int i=0;i<lista_elem;i++){ 4185 if(lista[i].indexOf(patron)!=-1) return lista[i]; 4186
} 4187 return null; 4188
} 4189 Nota: Recordemos que lista_elem siempre 4190 almacenará la cantidad de elementos y al 4191
comprarar i<lista_elem estamos 4192
asegurándonos que jamás se llegará a este 4193
valor, ya 4194 que los arreglos se acceden desde 0 hasta 4195
lista_elem-1. 4196
Búsqueda aleatoria, desordenar lista. 4197
Este método es completamente probabilístico 4198
y es funcional cuando el método binario u otro 4199
método más eficaz no visto sea aplicable. Es 4200 factible si el acceso a los datos es 4201
extremadamente lento, es 4202
decir si la búsqueda secuencial podría tardar 4203 horas para encontrar el último entre unos 4204
cuantos y 4205
122
queremos probar suerte (ya que las 4206
probabilidades de la búsqueda secuencial son 4207
las mismas), también 4208 sirve para desordenar una lista, por ejemplo 4209 para repartir “cartas mezcladas de un juego 4210
virtual”. 4211 Ejemplo: En una situación donde la consulta 4212
en línea de archivos clasificados depende de 4213 personal 4214
humano para deducir la respuesta y la 4215
respuesta humana puede tardar minutos en 4216 encontrar por ejemplo 4217
un sello en una carpeta, la búsqueda se 4218 minimizaría de manera aleatoria si tenemos 4219
suerte, otro ejemplo 4220
sería buscar dentro de los archivos de una 4221 lista de archivos alojados en un servidor 4222
remoto 4223
completamente saturado y con escasas 4224 posibilidades de transferencia a alta velocidad, 4225
también 4226
minimizaríamos el tiempo de búsqueda de 4227 manera que en el peor de los casos nuestra 4228
respuesta estaría 4229 entre el 50% y el 100% de los últimos 4230
registros y en el mejor de los casos entre el 4231
0% y el 50% de los 4232 primeros registros, de todas maneras es la 4233
misma probabilidad que la búsqueda 4234
secuencial así que solo 4235 el azar es el que influye. 4236
Búsqueda desordenada de la lista: 4237
123
1. public static String buscar_desordenado(String 4238 patron){ 4239
2. int[] indice=new int[lista_elem]; 4240 3. int aleatorio; 4241
4. for (int i=0;i<lista_elem;i++) indice[i]=i; 4242 5. for (int i=lista_elem;i>0;i--){ 4243
6. aleatorio=(int)(Math.random()*i); 4244 7. if(lista[indice[aleatorio]].indexOf(patron)!=-1) return 4245
lista[indice[aleatorio]]+":"+(lista_elem-i); 4246 8. for (int j=aleatorio;j<i-1;j++)indice[j]=indice[j+1]; 4247
9. } 4248 10. return null; 4249
11. } 4250 Fabricamos un índice para acceder a la lista, 4251
con la cantidad de elementos actual y no la 4252 máxima 4253
que es su capacidad, ya que será de manera 4254
temporal y local a la función, todos los objetos 4255 y variables 4256
declarados dentro de una función a menos 4257 que sean declarados estáticos se perderán y 4258
se liberará 4259 memoria del sistema. 4260
Rellenamos el índice con los elementos desde 4261
el 0 al máximo menos uno. Extraemos al azar 4262
un 4263 elemento del índice y recorremos los demás 4264 hasta el que quitamos, así comparamos un 4265
elemento de la 4266
lista al azar y terminamos si lo encontramos. 4267
Nota: El tipo de búsqueda no es exacto ya 4268
que usamos indexOf en vez de equals. 4269 Queda 4270
para el lector agregar esta función en el 4271 ejemplo anterior y probarla. 4272
124
Desordenar la lista: 4273 12. public static void desordenar(){ 4274 13. int[] indice=new int[lista_elem]; 4275
14. String[] desordenado=new String[lista_elem]; 4276 15. int des_elem=0; 4277
16. int aleatorio; 4278 17. for (int i=0;i<lista_elem;i++) indice[i]=i; 4279
18. for (int i=lista_elem;i>0;i--){ 4280 19. aleatorio=(int)(Math.random()*i); 4281
20. desordenado[des_elem++]=lista[indice[aleatorio]]; 4282 21. for (int j=aleatorio;j<i-1;j++)indice[j]=indice[j+1]; 4283
22. } 4284 23. for (int i=0;i<lista_elem;i++) lista[i]=desordenado[i]; 4285
24.} 4286 Para desordenar la lista estamos usando una 4287 lista temporal, con su respectivo contador e 4288
índice 4289
variable de elementos. 4290 Nota: Queda como tarea para el lector 4291
optimizar esta función para que no sea 4292 necesaria la 4293
lista temporal que en caso de escasos 4294 recursos y enormes listas no sería algo 4295
permitido, utilizando sólo 1 objeto temporal 4296
del tipo String para intercambiar valores 4297
y eliminar el uso del índice temporal. 4298
Búsqueda Binaria (lista ordenada) 4299
La búsqueda binaria es un método simple que 4300
se usa para encontrar datos en una lista 4301 ordenada, el 4302
mecanismo es el siguiente... 4303
Si tenemos una lista de n datos, ordenados de 4304 mayor a menor y queremos encontrar uno en 4305
125
particular, haremos una búsqueda con dos 4306
índices, o sea almacenaremos el valor del 4307
elemento 4308 comparado más grande y más pequeño hasta 4309
arrinconar el resultado o llegar a un punto 4310
donde no existe 4311 tal elemento pero los dos mas cercanos son 4312
estos índices mayor y menor. 4313 Veamos ahora un trozo de código para 4314
cuando la lista está ordenada de manera 4315
creciente y 4316 decreciente, estas dos funciones utilizan la 4317
fórmula que vimos en la ilustración anterior 4318 para calcular el 4319
índice superior e inferior, de esa manera y 4320
teniendo en cuenta que la operación de 4321 división será 4322
redondeada y sólo tendremos un número 4323
entero veamos como quedarían nuestras 4324 funciones. 4325
Orden ascendente de Texto: 4326 1. public static String buscar_ordenado_az(String 4327
inicio){ 4328 2. int Is=lista_elem-1; 4329
Ilustración 2: Búsqueda binaria en una lista ordenada 4330
0123456789 4331
IINFERIOR 4332
ISUPERIOR 4333
(9-0)/2+0 4334
126
4 456789 4335
IINFERIOR 4336
ISUPERIOR 4337
(9-4)/2+4 4338
6 4339
Se busca el elemento 7 de una 4340
lista ordenada, los contenidos 4341
pueden ser nombres de una 4342
agenda. 4343
IINFERIOR 4344
ISUPERIOR 4345
6789 4346
(9-6)/2+6 4347
7 7 4348
PComp= 4349
[ I S I I ] 4350
2 II 4351
Si el punto de comparación es mayor 4352
127
que dato que buscamos se actualiza el 4353 índice superior al punto de 4354
comparación, si es menor se actualiza 4355 el inferior, hasta que el punto de 4356
comparación sea el resultado buscado 4357 3. int Ii=0; 4358
4. int cmp=0; 4359 5. int old_cmp=-1; 4360
6. int compare; 4361 7. while (cmp!=old_cmp){ 4362
8. old_cmp=cmp; 4363 9. cmp=(Is-Ii)/2+Ii; 4364
10. compare=lista[cmp].compareTo(inicio); 4365 11. if(compare==0){return lista[cmp];} 4366
12. if(compare<0){Ii=cmp;} 4367 13. if(compare>0){Is=cmp;} 4368
14. } 4369 15. return lista[Is]; 4370
16. } 4371 Orden descendente de texto: 4372
17. public static String buscar_ordenado_za(String 4373 inicio){ 4374
18. int Is=lista_elem-1; 4375 19. int Ii=0; 4376
20. int cmp=0; 4377 21. int old_cmp=-1; 4378
22. int compare; 4379 23. while (cmp!=old_cmp){ 4380
24. old_cmp=cmp; 4381 25. cmp=(Is-Ii)/2+Ii; 4382
26. compare=lista[cmp].compareTo(inicio); 4383 27. if(compare==0){return lista[cmp];} 4384
28. if(compare>0){Ii=cmp;} 4385 29. if(compare<0){Is=cmp;} 4386
30. } 4387 31. return lista[Ii]; 4388
32. } 4389
128
En estas dos funciones iguales, sólo cambian 4390
las comparaciones, el problema en este 4391
ejemplo es la 4392 manera en la que la función de la biblioteca 4393
efectúa la comparación, podemos crear 4394
nuestras propias 4395 funciones de comparación y evitar usar las de 4396
la biblioteca, pero, la biblioteca suele tener 4397 funciones 4398
optimizadas al nivel del sistema operativo y no 4399
la máquina virtual de Java, por lo tanto las 4400 usaremos 4401
siempre que podamos. 4402 Nota: Queda para el lector agregar esta 4403
función al ejemplo de las listas y 4404
reconstruirla para 4405 el caso que los elementos sean números 4406
cualesquiera enteros en vez de objetos de 4407
texto. 4408
Métodos para ordenar listas 4409
Veremos a continuación algunos pocos 4410 métodos para ordenar listas de datos, esto 4411
nos servirá para 4412
poder aplicar la búsqueda binaria sobre una 4413 lista de datos, aunque en la actualizad esto ya 4414
casi no se 4415 utiliza debido a que los motores de bases de 4416
datos ordenan los resultados (resultsets) de 4417
manera que ya 4418
no es necesario ordenar, se delega la tarea a 4419 programas optimizados para hacer eso de 4420
manera 4421
129
extraordinariamente rápida como MySQL 4422
compilado para el procesador de la PC. 4423
Método de la burbuja o Método de 4424
Ordenación por Selección 4425
Este método es antiguo y obsoleto, pero sirve 4426 para aprender, por su simpleza y porque para 4427
pocos 4428
elementos no consume muchos recursos, la 4429 idea es la siguiente: tenemos una lista de 4430
datos desordenada 4431 y comparamos los dos primeros y sólo esos 4432
dos los ordenamos de mayor a menor, el paso 4433
siguiente es 4434 comparar el que sigue con el anterior y así 4435
sucesivamente hasta llegar al final, si 4436 contamos las 4437
comparaciones, fueron el total de los datos de 4438
la lista, menos una porque son de dos en dos. 4439
Con cada 4440 pasada por la lista un dato queda ordenado, y 4441
el nombre de burbuja es porque podríamos 4442 imaginarnos 4443
una burbuja que se lleva nuestro dato más 4444 grande hacia abajo o hacia arriba 4445
dependiendo como estemos 4446
recorriendo la lista y como estemos 4447 ordenando, si de mayor a menor o menor a 4448
mayor. 4449
Como podemos ver, para que la lista quede 4450 ordenada en el ejemplo de la ilustración 4451
anterior, 4452
130
debemos repetir el procedimiento N-1 veces, 4453
pero también como podemos ver ya que el 4454
elemento más 4455 grande quedó ordenado, podemos reducir el 4456
espacio de la burbuja desde el primer 4457
elemento al N-1-i 4458 donde i es el número de veces que se ha 4459
recorrido la lista para ordenarla, de esa 4460 manera reducimos la 4461
cantidad de comparaciones, que hace la 4462
burbuja para quedarse con el elemento más 4463 grande. 4464
Ilustración 3: Método de la burbuja o Método de 4465 Ordenación por Selección, para ordenar datos 4466
2<0 34 10 4 89 100 4467
23 45 12 15 20 90 47 4468
< 4469
20 34 10 4 89 100 23 4470
45 12 15 20 90 47 4471
20 10 34 4 89 100 23 4472
45 12 15 20 90 47 4473
20 10 4 34 89 100 23 4474
45 12 15 20 90 47 4475
131
20 10 4 34 89 100 23 4476
45 12 15 20 90 47 4477
20 10 4 34 89 100 23 4478
45 12 15 20 90 47 4479
20 10 4 34 89 23 100 4480
45 12 15 20 90 47 4481
20 10 4 34 89 23 45 4482
100 12 15 20 90 47 4483
20 10 4 34 89 23 45 4484
12 15 20 90 47 100 4485
Veamos un ejemplo: 4486 1. public static void burbuja_mayormenor(int[] 4487
listado){ 4488 2. int temporal; 4489
3. for (int j = 0; j < listado.length - 1; j++) { 4490 4. for (int i = 0; i < listado.length - 1; i++) { 4491
5. if (listado[i] < listado[i + 1]) { 4492 6. temporal = listado[i + 1]; 4493 7. listado[i + 1] = listado[i]; 4494
8. listado[i] = temporal; 4495 9. } 4496
10. } 4497 11. } 4498
132
12. } //final metodo ordenar burbuja mayor menor 4499 la función descrita arriba ordena de mayor a 4500 menor los elementos de la lista, la lista es un 4501
arreglo 4502 de números enteros que se recorre de la 4503
misma manera que en la Ilustración 3 sólo que 4504 se compara de 4505
manera que el más pequeño sea el que se 4506
queda, en la linea 3 repetimos el proceso N 4507
cantidad de veces, 4508
ya que la burbuja ordena de 1 elemento por 4509 pasada y el proceso de recorrido empieza en 4510
la línea 4, en la 4511 línea 5 se hace la comparación y dado el caso 4512
se dan vuelta los elementos utilizando una 4513
variable 4514 temporal del mismo tipo que almacena el 4515
arreglo. 4516 Ahora veamos como acotar los recorridos para 4517
reducir la cantidad de comparaciones: 4518 13.public static void ordenar_burbuja_mayormenor(int[] 4519
listado){ 4520 14. int temporal; 4521
15. for (int j = listado.length - 1; j > 0; j--) { 4522 16. for (int i = 0; i < j; i++) { 4523
17. if (listado[i] < listado[i + 1]) { 4524 18. temporal = listado[i + 1]; 4525 19. listado[i + 1] = listado[i]; 4526
20. listado[i] = temporal; 4527 21. } 4528 22. } 4529 23. } 4530
24. }//final metodo ordenar burbuja mayor menor 4531
133
Este ejemplo es idéntico al anterior sólo que 4532
ahora la línea 3 no sólo se utiliza para contar 4533
la 4534 cantidad de veces que tenemos que recorrer 4535
el arreglo sino que va decreciendo para que el 4536
recorrido 4537 siempre sea un elemento menos, es decir el 4538
que quedó ordenado no se vuelve a comparar. 4539 Nota: Queda como ejercicio para el lector 4540
construir las dos funciones inversas, las 4541
que 4542 ordenan de menor a mayor, y la que ordena 4543
de menor a mayor acotando las 4544 comparaciones. 4545
Método QuickSort Recursivo 4546
Este método para ordenar, es recursivo, si 4547 entendimos el ejemplo anterior, pudimos ver 4548
que la 4549
ejecución del algoritmo era secuencial, es 4550
decir 1 sola función hizo todo el trabajo en si 4551 misma. 4552
Este algoritmo implementa la división en dos 4553
grupos del arreglo a ordenar y por lo tanto la 4554
misma 4555 operación se realiza con cada subgrupo que a 4556 su vez se vuelve a dividir, y como es la misma 4557
operación 4558
se llama a la misma función varias veces. 4559
Esto tiene una desventaja, la plataforma que 4560
corre nuestra implementación debe producir 4561 una 4562
134
interrupción del proceso de ejecución para 4563
llamar a otra función, esto no tiene nada de 4564
malo excepto que 4565 cuando sean demasiados elementos la 4566
cantidad de veces que una función llamó a la 4567
misma función que 4568 llamó a la misma función puede ser tan larga 4569
que podría producir un agotamiento de 4570 recursos que 4571
ralentice o impida la ejecución de este tipo de 4572
algoritmos, en conclusión este método es muy 4573 difícil 4574
implementarlo de manera secuencial pero la 4575 cantidad de comparaciones se reduce 4576
notablemente.{1}{2} 4577 1. public static void quicksort_menormayor(int[] 4578
listado,int i,int j){ 4579 2. if (i>=j){return;} 4580
3. int p = dividiren_menormayor(listado,i,j); 4581 4. quicksort_menormayor(listado,i,p-1); 4582 5. quicksort_menormayor(listado,p+1,j); 4583
6. }//final del método principal de quicksort 4584 7. 4585
8. public static int dividiren_menormayor(int[] 4586 listado,int i,int j){ 4587 9. int p= i; i++; 4588
10. while (true){ 4589 11. while (i < j && listado[i]<=listado[p]){i++;} 4590 12. while (i < j && listado[j]>=listado[p]){j--;} 4591
13. if (i == j) break; 4592 14. swap(listado,i,j); 4593
15. } 4594 16. if (listado[p]<listado[i]){i--;} 4595
17. swap(listado,p,i); 4596 18. return i; 4597
19. }//final del método que divide y ordena 4598
135
En el código de ejemplo vemos que se 4599
declararon varias funciones, la función swap 4600
hace el 4601 intercambio con la variable temporal como en 4602 el método anterior, la función dividiren es la 4603
más 4604 importante de este procedimiento, es no solo 4605
la que divide sino la que intercambia los 4606 elementos que se 4607
van ordenando. Y por supuesto quicksort se 4608
llama así misma por cada subsegmento. 4609 Cada segmento se recorre hacia arriba y 4610
hacia abajo saltándose los menores e iguales 4611 y mayores e 4612
iguales que el elemento inferior, cuando no 4613
hay nada que saltar, se intercambian los 4614 valores de manera 4615
que quedan por encima y debajo de p los 4616
mayores y los menores. 4617 Ahora veamos la misma función pero 4618
ordenando de mayor a menor, como podemos 4619
ver sólo 4620 cambian los signos de comparación referentes 4621
a los contenidos del listado. 4622 1. public static void quicksort_mayormenor(int[] 4623
listado,int i,int j){ 4624 2. if (i>=j){return;} 4625
3. int p = dividiren_mayormenor(listado,i,j); 4626 4. quicksort_mayormenor(listado,i,p-1); 4627 5. quicksort_mayormenor(listado,p+1,j); 4628
6. }//final del método principal de quicksort 4629 7. 4630
8. public static int dividiren_mayormenor(int[] 4631 listado,int i,int j){ 4632
136
9. int p= i; i++; 4633 10. while (true){ 4634
11. while (i < j && listado[i]>=listado[p]){i++;} 4635 12. while (i < j && listado[j]<=listado[p]){j--;} 4636
13. if (i == j) break; 4637 14. swap(listado,i,j); 4638
15. } 4639 16. if (listado[p]>listado[i]){i--;} 4640
17. swap(listado,p,i); 4641 18. return i; 4642
19. }//final del método que divide y ordena 4643
Otros mecanismos para ordenar. 4644
Existen otros mecanismos que no podemos 4645 tratar en este momento porque es necesario 4646
implementar objetos, así que ese será el 4647 próximo tema, algunos son, por inserción, por 4648
fusión, de shell y 4649 con un árbol binario. 4650
Ejercicios 4651
Los ejercicios del capítulo III son los últimos 4652
antes de proceder con objetos, es 4653 recomendable que 4654
todo aquello que se ha visto hasta el momento 4655
quede perfectamente asimilado ya que en el 4656 próximo 4657
tema los objetos comenzarán a ser la 4658 herramienta principal. 4659
Ejercicio 3.1 4660
Realizar un programa cuyo método principal 4661
pida 10 valores numéricos y los asigne a un 4662 arreglo, 4663
posteriormente imprimir en pantalla el 4664 resultado ordenado creciente, y decreciente 4665
utilizando el método 4666
137
de la burbuja, computar la cantidad de 4667
comparaciones realizadas entre elementos del 4668
arreglo y 4669 mostrarlas al final como estadística. 4670
1. package com.compunauta.aprendiendojava; 4671 2. import java.io.*; 4672
3. /** 4673 4. * <p>Título: Aprendiendo Java</p> 4674
5. * <p>Descripción: Ejemplos del Libro Aprendiendo 4675 Java de Compunauta</p> 4676
6. * <p>Copyright: Copyright (c) 2006 4677 www.compunauta.com</p> 4678
7. * <p>Empresa: COMPUNAUTA</p> 4679 8. * @author Gustavo Guillermo Pérez 4680
9. * @version 2007.10.01 4681 10. */ 4682 11. 4683
12.public class Cap3_ej1 { 4684 13. public static int comparaciones=0; 4685
14. public static void main(String[] args) { 4686 15. BufferedReader br=new BufferedReader(new 4687
InputStreamReader(System.in)); 4688 16. int[] listado=new int[10]; 4689
17. System.out.println("Ingrese 10 números, de a uno 4690 presionando ENTER"); 4691
18. for(int i=0;i<10;i++){ 4692 19. listado[i]=leerInt(br); 4693
20. } 4694 21. 4695
22. burbuja_mayormenor(listado); 4696 23. for(int i=0;i<10;i++){ 4697
24. System.out.println("NRO >:["+i+"] "+listado[i]); 4698 25. } 4699 26. 4700
System.out.println("Comparaciones:"+comparaciones); 4701 27. burbuja_menormayor(listado); 4702
28. for(int i=0;i<10;i++){ 4703 29. System.out.println("NRO <:["+i+"] "+listado[i]); 4704
138
30. } 4705 31. 4706
32. } 4707 33. public static int leerInt(BufferedReader buff){ 4708
34. int lee=0; 4709 35. boolean error; 4710
36. do { 4711 37. error=false; 4712
38. try {lee = Integer.parseInt(buff.readLine());} 4713 39. catch (NumberFormatException ex) { 4714
40. System.out.println("Entrada erronea, repetir:?"); 4715 41. error=true;} 4716
42. catch (Exception 4717 ex){ex.printStackTrace(System.err);} 4718
43. } while (error); 4719 44. return lee; 4720
45. }//final de la función leer 4721 46. 4722
47. public static void 4723 ordenar_burbuja_mayormenor(int[] listado){ 4724
48. int temporal; 4725 49. for (int j = listado.length - 1; j > 0; j--) { 4726
50. for (int i = 0; i < j; i++) { 4727 51. comparaciones++; 4728
52. if (listado[i] < listado[i + 1]) { 4729 53. temporal = listado[i + 1]; 4730 54. listado[i + 1] = listado[i]; 4731
55. listado[i] = temporal; 4732 56. } 4733 57. } 4734 58. } 4735
59. }//final método ordenar burbuja mayor menor 4736 60. 4737
61. public static void burbuja_mayormenor(int[] 4738 listado){ 4739
62. int temporal; 4740 63. for (int j = 0; j < listado.length - 1; j++) { 4741 64. for (int i = 0; i < listado.length - 1; i++) { 4742
65. comparaciones++; 4743
139
66. if (listado[i] < listado[i + 1]) { 4744 67. temporal = listado[i + 1]; 4745 68. listado[i + 1] = listado[i]; 4746
69. listado[i] = temporal; 4747 70. } 4748 71. } 4749 72. } 4750
73. } //final método ordenar burbuja mayor menor 4751 74. 4752
75. public static void 4753 ordenar_burbuja_menormayor(int[] listado){ 4754
76. int temporal; 4755 77. for (int j = 0; j < listado.length - 1; j++) { 4756 78. for (int i = listado.length - 1; i > j; i--) { 4757
79. comparaciones++; 4758 80. if (listado[i] < listado[i - 1]) { 4759
81. temporal = listado[i - 1]; 4760 82. listado[i - 1] = listado[i]; 4761
83. listado[i] = temporal; 4762 84. } 4763 85. } 4764 86. } 4765
87. }//final método ordenar burbuja menor mayor 4766 88. 4767
89. public static void burbuja_menormayor(int[] 4768 listado){ 4769
90. int temporal; 4770 91. for (int j = 0; j < listado.length - 1; j++) { 4771 92. for (int i = listado.length - 1; i > 0; i--) { 4772
93. comparaciones++; 4773 94. if (listado[i] < listado[i - 1]) { 4774
95. temporal = listado[i - 1]; 4775 96. listado[i - 1] = listado[i]; 4776
97. listado[i] = temporal; 4777 98. } 4778 99. } 4779 100. } 4780
101. } //final método ordenar burbuja menor mayor 4781 102.} 4782
140
Línea 1, declaración del paquete, línea 2 4783
importamos java.io para usar los métodos de 4784
lectura del 4785 teclado, Línea 12 declaración de la clase, 4786
línea 13 declaramos la variable estática a la 4787
clase 4788 comparaciones que es la que usaremos para 4789
computar la cantidad de comparaciones para 4790 ordenar el 4791
arreglo. 4792
El programa en sí comienza en el método 4793 principal línea 14, línea 15 se construye un 4794
objeto 4795 BufferedReader para lectura por teclado, línea 4796
16 se inicializa un arreglo de 10 elementos 4797
que será el 4798 tamaño del arreglo a trabajar. 4799
Líneas 17 a 20 es la entrada por teclado de 4800
los números del arreglo utilizando la función 4801 leerInt(BufferedReader) utilizada en ejercicios 4802
anteriores. 4803
Línea 22 se invoca a la función que ordena 4804 sobre el arreglo listado de números enteros, y 4805
en las 4806 líneas 23 a 26 se imprime en pantalla la 4807
información correspondiente y la estadística 4808
de las 4809 comparaciones. Línea 33 a 45 Función leer. 4810
Línea 47 – 59 la función ordenar de mayor a 4811
menor con la optimización de acotación de 4812 índices, y 4813
las demás variantes con y sin optimización. 4814
141
Ejercicio 3.2 4815
Realizar un programa cuyo fin sea el del 4816
ejercicio 3.1 pero utilizando el procedimiento 4817 quicksort. 4818
Ejercicio 3.3 4819
Integrar con un pequeño menú en pantalla la 4820 selección del método que se utilizará para 4821
ordenar el 4822 arreglo reutilizando el código de los ejercicios 4823
anteriores 3.1 y 3.2, pero añadir al cómputo 4824 las 4825
comparaciones en total incluyendo las de los 4826
índices en bucles. 4827
IV- Primeros Objetos como 4828
mecanismo de programación. 4829
En este capítulo del libro comenzaremos a 4830
utilizar objetos para resolver problemas, la 4831
construcción eficiente del objeto también será 4832 parte del problema, recordemos que un objeto 4833
puede 4834
tener, métodos estáticos y dinámicos y 4835 propiedades estáticas y dinámicas, la 4836
selección de cada una 4837 dependerá del problema y del criterio utilizado. 4838
Lista con punteros para ordenar 4839
datos. 4840
Éste es otro método un poco más complejo 4841
para ordenar datos mientras se insertan, lo 4842 propondremos como una variante a los 4843
métodos vistos anteriormente pero 4844
construiremos un objeto que 4845
142
almacenará el dato, proveerá métodos para 4846
compararlo con otros objetos iguales y tendrá 4847
propiedades 4848 que nos permitirá conectarlo con otros objetos 4849 del mismo tipo. El objeto y el procedimiento irá 4850
haciéndose más complejo conforme 4851 avancemos en el tema. 4852
Imaginemos una persona, tiene dos manos y 4853 cada mano puede unirse a otra persona, cada 4854
persona 4855
simboliza un objeto que almacena un dato o 4856 un conocimiento, entonces el objeto de 4857
nuestra lista puede 4858 vincularse por la izquierda y derecha o puede 4859 estar vinculado por solo uno de los dos lados, 4860
o ninguno 4861 en el estado inicial. 4862
Cuando queremos insertar un elemento en 4863
nuestra lista, compararemos el nuevo de 4864 manera binaria 4865
recorriendo la lista como hemos visto 4866
anteriormente, y desconectaremos el lugar 4867 donde le corresponde ir 4868
uniendo su lado derecho e izquierdo con los 4869 elementos de la ruptura. 4870
Este tipo de lista se maneja por apuntadores, 4871
vínculos entre objetos que no es lo mismo que 4872 tener 4873
un arreglo de datos que se puede acceder en 4874
cualquier momento a cualquier elemento por 4875 medio de su 4876
143
índice. En este caso es necesario ir 4877
recorriendo cada elemento para saber a quien 4878
está conectado y seguir 4879 la cadena de datos de derecha a izquierda y 4880
viceversa.{3} 4881
Nuestro primer objeto 4882
Para poder realizar la lista ordenada que 4883
mencionamos utilizaremos un objeto que 4884 representará el 4885
nodo que puede conectarse por izquierda y 4886
por derecha y que almacena el dato, conforme 4887 podamos 4888
introduciremos funciones extra para realizar 4889 comparaciones. 4890 Propiedades 4891
Necesitamos la propiedad derecha e izquierda 4892 que serán punteros o variables que 4893
almacenarán 4894
objetos del mismo tipo “nodo” que serán como 4895
las manos que conectan los objetos 4896 adyacentes. 4897
Necesitamos la propiedad valor que 4898
almacenará una cantidad entera dentro del 4899
objeto, y esta 4900 cantidad se establecerá al construir el objeto. 4901
1.package com.compunauta.aprendiendojava; 4902 2.public class Nodo { 4903
3. public Nodo izquierda=null; 4904 4. public Nodo derecha=null; 4905
5. public int Dato; 4906 6. public Nodo(int Dato) { 4907
7. this.Dato=Dato; 4908 8. } 4909 9.} 4910
144
Ahora para hacer pruebas construiremos un 4911
método principal y como esta vez la 4912
información la 4913 almacenaremos en un arreglo sería 4914 interesante que tengamos un par de 4915
apuntadores principales que nos 4916 permitan acceder al primer y último objeto de 4917
manera inmediata, así que incluiremos esos 4918 apuntadores 4919
para trabajar. Utilizaremos también las 4920
funciones que hemos visto anteriormente para 4921 leer enteros del 4922
teclado y recorreremos la lista del elemento 4923 inicial (el más pequeño) al elemento final (el 4924
más grande), 4925
después incluiremos algunas modificaciones 4926 para mejorar la capacidad de inserción 4927
acortando las 4928
comparaciones y más adelante rediseñaremos 4929 el método para tener mayor control sobre los 4930
elementos 4931
que no pertenecen a un arreglo en concreto. 4932 1.package com.compunauta.aprendiendojava; 4933
2.import java.io.*; 4934 3./** 4935
4. * <p>Título: Aprendiendo Java</p> 4936 5. * <p>Descripción: Ejemplos del Libro Aprendiendo 4937
Java de Compunauta</p> 4938 6. * <p>Copyright: Copyright (c) 2007 4939
www.compunauta.com</p> 4940 7. * <p>Empresa: COMPUNAUTA</p> 4941 8. * @author Gustavo Guillermo Pérez 4942
9. * @version 2007.10.02 4943 10. */ 4944 11. 4945
145
12.public class Nodo { 4946 13. public Nodo izquierda=null; 4947 14. public Nodo derecha=null; 4948
15. public int Dato; 4949 16. public Nodo(int Dato) { 4950
17. this.Dato=Dato; 4951 18. } 4952
19. public static Nodo ini=null; //inicio 4953 20. public static Nodo fin=null; //final 4954
21. public static int total=0; 4955 22. public static void main(String[] args) { 4956
23. BufferedReader br = new BufferedReader(new 4957 InputStreamReader(System.in)); 4958
24. System.out.println("Ingrese 10 números, de a uno 4959 presionando ENTER"); 4960
25. for (int i = 0; i < 10; i++) { 4961 26. addObject(leerInt(br)); 4962
27. } 4963 28. printList(); 4964
29. } 4965 30. public static void addObject(int Dato){ 4966
31. Nodo dato=new Nodo(Dato); 4967 32. Nodo apuntador; 4968
33. total++; 4969 34. if (total==1){ 4970
35. ini=dato; 4971 36. fin=ini; 4972 37. }else{ 4973
38. if (fin.Dato <= Dato){ 4974 39. fin.derecha=dato; 4975 40. dato.izquierda=fin; 4976
41. fin=dato; 4977 42. return; 4978
43. } 4979 44. if (ini.Dato >= Dato){ 4980 45. ini.izquierda=dato; 4981 46. dato.derecha=ini; 4982
47. ini=dato; 4983 48. return; 4984
146
49. } 4985 50. apuntador=ini; 4986
51. while (apuntador.Dato < Dato){ 4987 52. apuntador=apuntador.derecha; 4988
53. } 4989 54. dato.izquierda=apuntador.izquierda; 4990 55. apuntador.izquierda.derecha=dato; 4991
56. dato.derecha=apuntador; 4992 57. apuntador.izquierda=dato; 4993
58. return; 4994 59. } 4995 60. } 4996 61. 4997
62. public static void printList(){ 4998 63. Nodo apuntador=ini; 4999
64. int elementos=0; 5000 65. while (apuntador!=null){ 5001
66. System.out.println("Elemento 5002 ["+(elementos++)+"]:"+apuntador.Dato); 5003
67. apuntador=apuntador.derecha; 5004 68. } 5005 69. } 5006
70. public static int leerInt(BufferedReader buff){ 5007 71. int lee=0; 5008
72. boolean error; 5009 73. do { 5010
74. error=false; 5011 75. try {lee = Integer.parseInt(buff.readLine());} 5012
76. catch (NumberFormatException ex) { 5013 77. System.out.println("Entrada erronea, repetir:?"); 5014
78. error=true;} 5015 79. catch (Exception 5016
ex){ex.printStackTrace(System.err);} 5017 80. } while (error); 5018
81. return lee; 5019 82. }//final de la funcion leer 5020
83. 5021 84.} 5022
147
Como podemos ver la función printList() 5023
recorre la lista para impresión en pantalla y la 5024
función 5025 leer renglones, es como la que hemos visto 5026 anteriormente, la que realiza la operación de 5027
inserción en la 5028 lista es addObject(int Dato) y tenemos en 5029
cuenta 4 casos. 5030 1. El primer objeto es ini y fin y tiene nulas 5031
derecha e izquierda 5032
2. Si no es el primer objeto y es más grande 5033 que todos unir a la derecha 5034
3. Si no es el primer objeto y es más pequeño 5035 que todos unir a la izquierda 5036
4. Si se encuentra en medio, recorremos 5037
desde el inicio hasta encontrar uno más 5038 grande. 5039
Nota: Queda como ejercicio para el lector 5040
modificar el programa para recorrer la lista 5041 de 5042
menor a mayor o mayor a menor 5043
dependiendo del valor del dato a insertar. 5044