Vous êtes sur la page 1sur 213

Curso de Java

por Michael Moossen


Version 1.0.14, 16 de marzo de 2003

Este documento es de dominio publico. Se puede imprimir y distribuir libre de gastos en su forma original, incluyendo la lista de los
autores. Si se altera o se utilizan partes de e ste dentro de otro documento, la lista de autores debe incluir todos los autores originales y el autor
o autores que hayan realizado los cambios.
En caso de que este documento sea utlizado con fines comerciales, se aplicaran los terminos de la GNU General Public Licence.

c by Michael Moossen. 2002-03.


Copyright

Manual del Departamento de Informatica


de la Universidad Tecnica Federico Santa Mara
Valparaso, Chile

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


Indice
general

Indice
General

Prefacio
Convenciones de Escritura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1. Introduccion a Java
1.1. Resena Historica . . . . . . .
1.2. Caractersticas . . . . . . . . .
1.2.1. Portabilidad . . . . . .
1.2.2. Lenguaje Interpretado
1.2.3. Orientacion a Objetos
1.2.4. Integracion en la Red .
1.2.5. Multitarea . . . . . . .
1.2.6. Robustez . . . . . . .
1.2.7. Seguridad . . . . . . .
1.3. Instalacion . . . . . . . . . . .
1.3.1. Distribuciones . . . .
1.3.2. Ayuda en Lnea . . . .
1.4. Primer Programa Java . . . . .
1.4.1. Compilacion . . . . .
1.4.2. Ejecucion . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

1
1
2
2
2
3
4
4
4
4
4
5
5
5
6
7

2. Principios de Programacion con Java


2.1. La Sintaxis del Lenguaje . . . . .
2.1.1. Palabras Clave . . . . . .
2.1.2. Identificadores . . . . . .
2.1.3. Literales . . . . . . . . . .
2.1.4. Separadores . . . . . . . .
2.1.5. Comentarios . . . . . . .
2.2. Variables . . . . . . . . . . . . .
2.2.1. Declaracion . . . . . . . .

2.2.2. Ambito
. . . . . . . . . .
2.2.3. Control de Acceso . . . .
2.2.4. Arreglos . . . . . . . . . .
2.3. Tipos de Dato . . . . . . . . . . .
2.3.1. Basicos . . . . . . . . . .
2.3.2. Conversion de Tipos . . .
2.3.3. Objetos . . . . . . . . . .
2.4. Operadores . . . . . . . . . . . .
2.4.1. Operadores Unarios . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

9
9
9
10
10
10
11
11
11
12
12
13
14
14
15
17
18
18

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

INDICE GENERAL
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

19
20
21
21
23
23
23
25
26
26
26
27
27
27
27
28
29
29
30
30
31
31
31
32

3. Programacion Orientada a Objetos


3.1. Taxonoma de Lenguajes Orientados a Objetos . . . . . . . . . . . . . .
3.2. Ventajas de la Tecnologa Orientada a Objetos . . . . . . . . . . . . . . .
3.3. Desventajas de la Tecnologa Orientada a Objetos . . . . . . . . . . . . .
3.4. Caractersticas de la Tecnologa Orientada a Objetos . . . . . . . . . . .
3.4.1. Abstraccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.2. Modularidad . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.3. Encapsulamiento . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.4. Jerarqua . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.5. Polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.6. Caractersticas Adicionales de los Lenguajes Orientados a Objetos
3.5. Clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.5.1. Atributos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.5.2. Metodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.5.3. Constructores . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.5.4. Destructores . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.6. Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.6.1. Operador new . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.6.2. Objeto this . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.6.3. Objeto super . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.7. Modificadores de Atributos y Metodos . . . . . . . . . . . . . . . . . . .
3.7.1. El Modificador static . . . . . . . . . . . . . . . . . . . . . . .
3.7.2. El Modificador final . . . . . . . . . . . . . . . . . . . . . . .
3.7.3. El Modificador abstract . . . . . . . . . . . . . . . . . . . . .
3.7.4. El Modificador transient . . . . . . . . . . . . . . . . . . . .
3.7.5. El Modificador volatile . . . . . . . . . . . . . . . . . . . . .
3.8. Clases Internas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

35
35
35
36
36
36
37
37
37
39
40
40
41
41
43
44
45
45
45
46
48
48
50
50
51
51
51

2.5.

2.6.

2.7.

2.8.
2.9.

2.4.2. Operadores Aritmeticos . . . . . . . . .


2.4.3. Operadores de Rotacion . . . . . . . . .
2.4.4. Operadores de Comparacion . . . . . . .
2.4.5. Operadores Logicos . . . . . . . . . . .
2.4.6. Operador Ternario . . . . . . . . . . . .
2.4.7. Operadores de Asignacion . . . . . . . .
2.4.8. Precedencia de Operadores . . . . . . . .
2.4.9. Operaciones con Objetos . . . . . . . . .
Control de Flujo . . . . . . . . . . . . . . . . . .
2.5.1. La Sentencia if . . . . . . . . . . . . .
2.5.2. La Sentencia switch . . . . . . . . . . .
Ciclos . . . . . . . . . . . . . . . . . . . . . . .
2.6.1. La Sentencia while . . . . . . . . . . .
2.6.2. La Sentencia for . . . . . . . . . . . . .
2.6.3. Control de Flujo en Ciclos . . . . . . . .
Manejo de Excepciones . . . . . . . . . . . . . .
2.7.1. try...catch...finally . . . . . . .
2.7.2. La Clase Exception . . . . . . . . . . .
2.7.3. Capturar Excepciones . . . . . . . . . .
2.7.4. Lanzar Excepciones . . . . . . . . . . .
2.7.5. Declaracion de Excepciones en Metodos
Recursividad . . . . . . . . . . . . . . . . . . .
2.8.1. Numeros de Fibonacci . . . . . . . . . .
La Clase Object . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

Departamento de Informatica. U.T.F.S.M.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

Michael Moossen

INDICE GENERAL
3.8.1. Clases Internas Estaticas . . . . . .
3.8.2. Clases Internas Miembro . . . . . .
3.8.3. Clases Internas Locales . . . . . . .
3.8.4. Clases Anonimas . . . . . . . . . .
3.9. Interfaces . . . . . . . . . . . . . . . . . .
3.9.1. Declaracion de una Interfaz . . . .
3.9.2. Uso de una Interfaz . . . . . . . . .
3.10. Paquetes . . . . . . . . . . . . . . . . . . .
3.10.1. Uso de Paquetes . . . . . . . . . .
3.10.2. Nombre de Paquetes y Clases . . .
3.10.3. Uso de Otros Paquetes . . . . . . .
3.10.4. Estructura Jerarquica de Directorios
3.10.5. Ejecucion de las Clases . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

52
53
55
55
56
57
58
59
59
59
60
60
60

4. Programacion con la API Estandar


4.1. Manejo de Strings . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.1. La Clase String . . . . . . . . . . . . . . . . . . . . . .
4.1.2. La Clase StringBuffer . . . . . . . . . . . . . . . . . .
4.1.3. La Clase StringTokenizer . . . . . . . . . . . . . . . .
4.2. Utilidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.1. Iteradores . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.2. Vectores . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.3. La Clase Hashtable . . . . . . . . . . . . . . . . . . . .
4.2.4. La Clase System . . . . . . . . . . . . . . . . . . . . . .
4.3. Funciones Matematicas . . . . . . . . . . . . . . . . . . . . . . .
4.3.1. La Clase Abstracta Number . . . . . . . . . . . . . . . .
4.3.2. La Clase Math . . . . . . . . . . . . . . . . . . . . . . .
4.3.3. El paquete java.math . . . . . . . . . . . . . . . . . . .
4.4. Manejo de Fechas . . . . . . . . . . . . . . . . . . . . . . . . . .
4.4.1. La Clase Date . . . . . . . . . . . . . . . . . . . . . . .
4.4.2. La Clase GregorianCalendar . . . . . . . . . . . . . .
4.4.3. La Clase SimpleDateFormat . . . . . . . . . . . . . . .
4.4.4. La Clase SimpleTimeZone . . . . . . . . . . . . . . . .
4.5. Entrada y Salida de Datos . . . . . . . . . . . . . . . . . . . . . .
4.5.1. Archivos y Directorios . . . . . . . . . . . . . . . . . . .
4.5.2. Lectura y Escritura en Archivos de Texto . . . . . . . . .
4.5.3. Lectura y Escritura en Archivos Binarios . . . . . . . . .
4.5.4. Archivos de Acceso Aleatorio . . . . . . . . . . . . . . .
4.5.5. Serializacion de Objetos . . . . . . . . . . . . . . . . . .
4.6. Conectividad a Base de Datos (JDBC) . . . . . . . . . . . . . . .
4.6.1. Introduccion a los Drivers JDBC . . . . . . . . . . . . . .
4.6.2. Registrar un Driver JDBC: La Clase DriverManager . .
4.6.3. La Conexion: La Clase Connection y URLs de Conexion
4.6.4. Ejecutar una Instruccion SQL: La Clase Statement . . .
4.6.5. Obtencion de Resultados: La Interfaz ResultSet . . . . .
4.6.6. Manejo de Transacciones . . . . . . . . . . . . . . . . . .
4.7. Hilos y Sincronizacion . . . . . . . . . . . . . . . . . . . . . . .
4.7.1. Creacion de Hilos . . . . . . . . . . . . . . . . . . . . . .
4.7.2. Ciclo de Vida de un Thread . . . . . . . . . . . . . . . .
4.7.3. Sincronizacion . . . . . . . . . . . . . . . . . . . . . . .
4.7.4. Prioridades . . . . . . . . . . . . . . . . . . . . . . . . .
4.7.5. Grupos de Thread . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

63
63
63
64
65
65
65
65
66
67
68
68
68
70
70
70
71
72
73
74
74
76
77
78
78
80
80
81
82
83
83
85
87
87
88
91
93
94

Michael Moossen

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

Departamento de Informatica. U.T.F.S.M.

INDICE GENERAL
5. Java e Internet
5.1. Trabajo en Red . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1.1. Conceptos Basicos . . . . . . . . . . . . . . . . . . . .
5.1.2. URL . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1.3. Sockets . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1.4. Datagramas . . . . . . . . . . . . . . . . . . . . . . . .
5.2. HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.1. Primera Pagina . . . . . . . . . . . . . . . . . . . . . .
5.2.2. Formateo Basico . . . . . . . . . . . . . . . . . . . . .
5.2.3. Caracteres Especiales . . . . . . . . . . . . . . . . . . .
5.2.4. Enlaces . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.5. Listas . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.6. Imagenes . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.7. Formateo Fino . . . . . . . . . . . . . . . . . . . . . .
5.2.8. Estructura del Documento . . . . . . . . . . . . . . . .
5.2.9. Formularios . . . . . . . . . . . . . . . . . . . . . . . .
5.2.10. Tablas . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.11. Marcos . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3. Java Server Pages . . . . . . . . . . . . . . . . . . . . . . . . .
5.3.1. Plantilla de Texto . . . . . . . . . . . . . . . . . . . . .
5.3.2. Elementos de Script . . . . . . . . . . . . . . . . . . .
5.3.3. Directivas . . . . . . . . . . . . . . . . . . . . . . . . .
5.3.4. Variables Predefinidas . . . . . . . . . . . . . . . . . .
5.3.5. Accciones . . . . . . . . . . . . . . . . . . . . . . . . .
5.3.6. Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4. Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4.1. El Tag APPLET de HTML . . . . . . . . . . . . . . . .
5.4.2. Ciclo de Vida de un Applet . . . . . . . . . . . . . . . .
5.4.3. Metodos para Dibujar un Applet . . . . . . . . . . . . .
5.4.4. Comunicacion entre Applet y Browser . . . . . . . . . .
5.4.5. Sonidos en Applets . . . . . . . . . . . . . . . . . . . .
5.4.6. Imagenes en Applets . . . . . . . . . . . . . . . . . . .
5.4.7. Threads en Applets . . . . . . . . . . . . . . . . . . . .
5.4.8. Applets como Aplicaciones . . . . . . . . . . . . . . .
5.4.9. Restricciones de Seguridad . . . . . . . . . . . . . . . .
5.5. Seguridad . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.5.1. Controlador de Seguridad . . . . . . . . . . . . . . . .
5.5.2. Un Controlador de Seguridad Propio . . . . . . . . . . .
5.5.3. Instalar un Controlador de Seguridad . . . . . . . . . .
5.5.4. Decidir que Metodos Sobreescribir del SecurityManager

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

95
95
95
96
102
107
111
111
113
115
115
116
117
118
119
121
124
126
129
129
129
131
133
134
134
135
136
137
137
139
140
140
141
142
143
144
144
145
147
148

6. Interfaces Graficas
6.1. Contexto Historico . . . . . . . . . .
6.2. Introduccion a Swing . . . . . . . . .
6.2.1. Contenedores . . . . . . . . .
6.2.2. Componentes . . . . . . . . .
6.3. Manejo de Eventos . . . . . . . . . .
6.4. Diseno de Interfaces . . . . . . . . .
6.4.1. Administracion de Disposicion
6.4.2. Posicionamiento Absoluto . .
6.4.3. Relleno . . . . . . . . . . . .
6.4.4. Bordes . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

151
152
153
153
156
158
159
159
162
162
163

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

INDICE GENERAL
6.4.5. Look & Feel . . . . . .
6.5. Contenedores . . . . . . . . . .
6.5.1. Ventanas de Dialogo . .
6.5.2. Contenedores Generales
6.6. Componentes . . . . . . . . . .
6.6.1. Etiquetas . . . . . . . .
6.6.2. Botones . . . . . . . . .
6.6.3. Listas Desplegables . . .
6.6.4. Cajas de Texto . . . . .
6.6.5. Campos de Password . .

6.6.6. Areas
de Texto . . . . .
6.6.7. Listas . . . . . . . . . .
6.6.8. Tablas . . . . . . . . . .
6.7. Lo que falto . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

164
165
165
167
171
171
172
173
173
173
174
174
176
177

7. Java 2 Enterprise Edition


7.1. Introduccion . . . . . . . . . . . .
7.1.1. Enterprise Java Bean . . .
7.1.2. Contenedor EJB . . . . .
7.1.3. Arquitectura . . . . . . .
7.1.4. Distribucion de Carga . .
7.1.5. Descriptores de Instalacion
7.2. Enterprise Java Beans . . . . . . .
7.2.1. Session Beans . . . . . .
7.2.2. Entity Beans . . . . . . .
7.2.3. Message Driven Beans . .
7.3. Transacciones . . . . . . . . . . .
7.3.1. Manejo Programado . . .
7.3.2. Manejo Declarado . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

179
179
179
179
180
181
181
181
182
182
182
182
183
183

A. Utilitarios de Java
A.1. Generador de Documentacion
A.2. Java ARchive . . . . . . . . .
A.3. Applet Viewer . . . . . . . . .
A.4. Java Debugger (jdb) . . . . .
A.5. Java IDEs . . . . . . . . . . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

185
185
186
186
187
187

.
.
.
.
.

.
.
.
.
.

B. Propiedades del Sistema

189

Bibliografa

191

Indice
alfabetico

193

Michael Moossen

Departamento de Informatica. U.T.F.S.M.

Prefacio
Este manual tiene la intencion de ser una herramienta de apoyo al aprendizaje del lenguaje de programacion
Java, para personas con conocimientos previos mnimos de programacion, entregando por una parte una sobrevista
general del lenguaje mismo y sus principales a reas y aplicaciones, como tambien todos los conceptos para que el
alumno pueda desarrollarse mas alla de este manual por s mismo.
Este curso se divide en seis captulos:
El captulo 1 introduce el lenguaje de programacion Java exponiendo sus virtudes y desventajas. Ademas, se ven
aspectos practicos de los pasos de configuracion de una plataforma de programacion totalmente operable y
el primer ejemplo de codigo.
El captulo 2 incide en los detalles basicos sobre la programacion en Java. Dando a conocer las herramientas
basicas con las que cuenta el programador y mostrando de a poco los conceptos de orientacion a objetos
basicos.
El captulo 3 entra de lleno en materia de programacion orientada a objetos, en sus orgenes y su evolucion, y de
todos los aspectos practicos presentes en Java.
El captulo 4 presenta algunos temas de programacion mas especficos, como son algunas libreras estandares de
Java, conectividad a bases de datos va JDBC, manipulacion avanzada de Strings y manejo de archivos.
El captulo 5 entra en el mundo web pasando de HTML basico, haca paginas JSP, servlets y applets. Ademas se
ven temas de seguridad y manejo de Sockets.
El captulo 6 introduce la programacion de interfaces de usuario graficas, va AWT y Swing(JFC).
El apendice A introduce algunas herramientas incluidas en la distribucion de Java y que pueden ser de gran
utilidad para el programador.
El apendice B presenta las propiedades del sistema que son accesibles por defecto.
Es importante leer los captulos en secuencia. Se recomienda, leer cuidadosamente los ejemplos, ya que en ellos
encontrara gran parte de la informacion, entregada en este manual.

Si tiene ideas sobre algo que debera ser anadido o alterado en este documento, por favor hagalo saber.

Michael Moossen <mmoossen@labmc.inf.utfsm.cl>


Estudiante de Magister, Departamento de Informatica, Universidad Tecnica Federico Santa Mara

La version vigente de este documento estara disponible en:


http://www.labmc.inf.utfsm.cl/mmoossen

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

Convenciones de Escritura
Durante este curso se usaran las siguientes convenciones de escritura para el codigo Java:
Codigo Fuente
El codigo fuente, en general, sera escrito con letra monoespaciada, como en el siguiente ejemplo:
System.out.println("Ejemplo:");
for(int i=0; i<10; i++) { //itera 10 veces
System.out.println(i);
}
Palabras Reservadas
Ademas, las palabras reservadas de Java, se presentaran en color azul:
System.out.println("Ejemplo:");
for (int i=0; i<10; i++) { //itera 10 veces
System.out.println(i);
}
Comentarios
Los comentarios, seran verdes:
System.out.println("Ejemplo:");
for (int i=0; i<10; i++) { //itera 10 veces
System.out.println(i);
}
Literales
Los literales, tanto numericos como alfabeticos, seran rosados:
System.out.println("Ejemplo:");
for (int i=0; i<10; i++) { //itera 10 veces
System.out.println(i);
}
Clases e Interfaces
Tanto, las clases como las interfaces, seran representadas con color rojo:
System.out.println("Ejemplo:");
for (int i=0; i<10; i++) { //itera 10 veces
System.out.println(i);
}
Metodos y Atributos
Finalmente, los metodos y atributos de una clase, se muestran en color turquesa:
System.out.println("Ejemplo:");
for (int i=0; i<10; i++) { //itera 10 veces
System.out.println(i);
}

Numeros
de Lnea
En algunos ejemplos, se incluyen los numeros de lnea. Esta numeracion es de color gris:

01 System.out.println("Ejemplo:");
02 for (int i=0; i<10; i++) { //itera 10 veces
03
System.out.println(i);
04 }
Para el codigo HTML, se usaran convenciones de escritura similares:
Tags seran escritos con color azul.
Atributos seran escritos con color rojo.

Literales, Comentarios y Numeros


de Lnea mantienen las misma convenciones que en codigo Java.
Como se muestra en el siguiente ejemplo:
01
02
03
04
05
06
07
08
09
10
11
12

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >


<HTML>
<HEAD>
<TITLE> The Robot </TITLE>
<META NAME="Author" CONTENT="Michael Moossen" >
</HEAD>
<!-- Aqu
comienza el contenido de la p
agina -->
<BODY>
<APPLET CODE="Robot.class" WIDTH=600 HEIGHT=400>
</BODY>
</HTML>

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

Captulo 1

Introduccion a Java
1.1.

Historica
Resena

El desarrollo del lenguaje Java se inicio en 1991, contemporaneamente a la creacion en Suiza de la World
Wide Web. En esa e poca, un equipo de Sun MicroSystems, en el que participaba James Gosling, trabajaba en el
proyecto de crear productos electronicos de consumo que fueran sencillos y fiables. Para ello, se necesitaba una
forma de crear codigo, que fuera independiente de la plataforma y que permitiera ejecutar el software en cualquier
CPU.
Como punto de partida, para un lenguaje informatico que implementara esta independencia de la plataforma, el
equipo de Sun se fijo en un primer momento en C++. Pronto abandonaron la idea y no consiguieron encontrar
ningun lenguaje que se adaptara a sus necesidades.
Decidieron entonces desarrollar un lenguaje nuevo llamado Oak (el nombre fue tomado de un enorme roble que
haba frente al despacho de Mike Sheridan, coordinador y fundador del equipo de trabajo), mas tarde y al existir
ya un lenguaje llamado Oak, se rebautizo el lenguaje con el nombre de Java (Java, en el argot norteamericano
significa cafe. El equipo de trabajo de Sheridan se reuna en una cafetera cercana a las instalaciones de Sun,
donde discutan acaloradamente del proyecto. De aqu tomo su nombre Java). Hacia el otono de 1992, el equipo
haba puesto en marcha un proyecto llamado Star 7 (*7), consistente en un control remoto personal y manual;
para este proyecto el equipo se constituyo en una sociedad filial de Sun llamada la First Person, Inc. First Person
perdio un concurso convocado por la Time Warner para desarrollar una television set-top box, First Person se
disolvio y a Sun MicroSystems u nicamente le quedo el lenguaje Java.
A mediados de 1994, la popularidad de la Web atrajo la atencion de los directivos de Sun e intuyendo las enormes
posibilidades de este nuevo medio de comunicacion, decidieron programar un navegador, empleando la tecnologa
Java.
Aquel primer programa, que se llamo WebRunner, quedo listo en Mayo de 1995 y viendo las enormes posibilidades
decidieron mejorar el navegador. El 23 de Mayo de 1995 en la Sun World 95 de San Francisco, Sun presenta su
nuevo navegador HotJava y Netscape anuncia su intencion de integrar Java en su navegador.
A partir de aquel verano, los acontecimientos se desarrollan vertiginosamente para el mundo Java, sobre todo
despues del lanzamiento y distribucion libre del Java Development Kit (JDK) 1.0. A finales de 1995 (solo seis
meses despues del lanzamiento de JDK!!) Java haba firmado acuerdos con las principales firmas del software, para
que pudieran utilizar Java en sus productos, entre otras Netscape, Borland, Mitsubishi Electronics, Dimension
X, Adobe, IBM, Lotus, Macromedia, Oracle, SpyGlass... pero lo mas espectacular fue el anuncio por parte de
Bill Gates, presidente y director ejecutivo de Microsoft, el 7 de Diciembre de 1995, de la voluntad por parte de
Microsoft, de obtener la licencia de utilizacion de Java.
Aquel anuncio vena a mostrar claramente que Microsoft consideraba a Java como una parte importante en la
estratega global de Internet. Este anuncio es significativo, si se considera el desprecio que meses antes Bill Gates
haba mostrado hacia Java, calificandolo como un lenguaje mas. El propio director general de Microsoft en
Espana, haba calificado a Java como un lenguaje para tostadoras.
1

1.2. CARACTERISTICAS
Durante 1996 se planteo el debate de crear un terminal tonto o netPc, que u nicamente sirviera para conectarse
a la World Wide Web. En un principio se proyecto que este terminal estara gobernado por un sistema operativo
Java. La idea del netPc no cuajo como se esperaba, pero la idea de producir un sistema operativo Java, si que se ha
desarrollado, se llama JavaOS. S algun da podra competir con los sistemas operativos de moda como Windows
9x y Linux, solo el tiempo lo dira. Tambien se sabe (aunque Sun no lo reconoce abiertamente) del proyecto
de construir un chip Java que incorporara todo el codigo de la Maquina Virtual Java en el propio hardware.
Esto sin duda, acelerara enormemente los tiempos de proceso de cualquier programa Java y lo equiparara a las
velocidades de lenguajes que compiten directamente con Java, por ejemplo C++. El desarrollo de una tecnologa
de componentes (JavaBeans) al estilo OLE y ActiveX, facilmente implementables en codigo, la incorporacion
vertiginosa por parte de Sun de nuevas APIs (Java2D, APIS de telefona, JDBC, etc..) mas la renovacion continua
del compilador gratuito JDK (actualmente la version mas reciente de JDK es la 1.4) hacen de Java una tecnologa
prometedora que sin duda tiene un papel importante en la actualidad y lo tendra cada vez mas en el futuro.

1.2.

Caractersticas

1.2.1.

Portabilidad

Efectivamente, Java esta preparado para practicamente la totalidad de las plataformas y sistemas operativos
existentes hoy en da.
El proceso de diseno y programacion del codigo de un programa Java, no es distinto del de cualquier programa en
otro lenguaje. Se usa un editor de texto para escribir las sentencias y el archivo de codigo fuente obtenido se guarda en un archivo con extension .java. La novedad que introduce Java, viene dada en el proceso de compilacion.
En este proceso, el compilador traduce el codigo fuente a un formato especial llamado bytecode. Este bytecode
es grabado en un archivo con extension .class y no es directamente interpretable por el computador, sino por
cualquier computador que tenga instalada una Maquina Virtual Java.
Aqu radica la novedad que introduce Java y aunque es una idea sencilla, a la vez es potente, y es lo que ha hecho
que Java sea lo mejor que le ha pasado a la informatica desde la aparicion del PC.
No importa el procesador ni el sistema operativo, la u nica condicion para que un programa Java pueda correr en
un computador, es que tenga instalada la Maquina Virtual. Mas lejos aun, ni siquiera es necesario que sea un computador. Cualquier aparato que implemente la Maquina Virtual Java o partes de ella, estara preparado para ejecutar
programas Java; podra ser el sistema de menus de un video, el control de un edificio inteligente o simplemente
una cafetera.
Ya han habido otros lenguajes interpretados, como por ejemplo Visual Basic. Sin embargo, nunca se haba empleado como punto de partida a un lenguaje multiplataforma, ni se haba hecho de manera tan eficiente. Cuando
Java aparecio en el mercado, se hablaba de que era entre 10 y 30 veces mas lento que C++. Ahora, con los compiladores JIT (Just in Time) se habla de tiempos casi comparables. Con la potencia de las maquinas actuales, esa
lentitud es un precio que se puede pagar sin problemas, contemplando las ventajas de un lenguaje portable.

1.2.2.

Lenguaje Interpretado

Java no es exactamente un lenguaje interpretado del todo, se podra definir como un hbrido compiladointerpretado. Otros lenguajes interpretados, como por ejemplo el Perl , no necesitan de un proceso de compilacion para estar preparados para correr. El caso mas simple de un lenguaje interpretado, seran los archivos batch,
simplemente se escriben las ordenes en un archivo y el computador las ejecuta. Si se ha cometido un error, por
ejemplo escribiendo incorrectamente alguna o rden, no se sabra hasta que el computador intente ejecutar esa o rden
concreta. Entonces avisara con el correspondiente mensaje de error.
Los archivos de codigo fuente Java, a diferencia de los de Perl o los archivos batch, no estan preparados para
correr en el computador, necesitan de un proceso de compilacion previa. Entonces...Por que se dice que Java
es un lenguaje interpretado?. El archivo .class (bytecode) que se obtiene de la compilacion previa del codigo
fuente necesita de una Maquina Virtual que interprete el bytecode y lo ejecute en el computador. As como los
archivos batch, necesitan del interprete de comandos (command.com o sh) para ejecutarse, Java necesita de la
2

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

A JAVA
CAPITULO 1. INTRODUCCION
interpretacion de la Maquina Virtual.

1.2.3.

Orientacion a Objetos

Dado que Java es un lenguaje orientado a objetos, es imprescindible entender que es esto y en que afecta
a los programas. Desde el principio, la carrera por crear lenguajes de programacion, ha sido una carrera para
intentar realizar abstracciones sobre la maquina. Al principio, no eran grandes abstracciones y el concepto de
lenguajes imperativos es prueba de ello. Exigen pensar en terminos del computador y no en terminos del problema
a solucionar. Esto provoca que los programas sean difciles de escribir y mantener, al no tener una relacion obvia
con el problema que representan, no abstraen lo suficiente.
Muchos paradigmas de programacion, intentaron resolver este problema alterando la vision del mundo y adaptandola al lenguaje. Estas aproximaciones, modelaban el mundo como un conjunto de objetos o de listas. Funcionaban
bien para algunos problemas pero no para otros. Los lenguajes orientados a objetos, mas generales, permiten
realizar soluciones que, ledas, describen el problema. Permiten escribir soluciones pensando en el problema y no
en el computador que debe solucionarlo en u ltimo extremo. Se basan en cinco caractersticas:
Todo es un objeto , es decir, cada elemento del problema debe ser modelizado como un objeto.
Un programa es un conjunto de objetos diciendose entre s que deben hacer, por medio de mensajes , es decir, cuando se necesita que un objeto realice una accion, se le manda un mensaje. Mas concretamente, se
ejecuta un metodo de dicho objeto.
Cada objeto tiene su propia memoria, que llena con otros objetos , es decir, cada objeto puede contener otros
objetos. De este modo se puede incrementar la complejidad del problema, pero detras de dicha complejidad
siguen habiendo simples objetos.
Todo objeto tiene un tipo , es decir, en jerga POO, cada objeto es una instancia (un caso particular) de una clase
(el tipo general). Lo que distingue a una clase de otra, es la respuesta a la pregunta, que mensajes puede
recibir?.
Todos los objetos de un determinado tipo pueden recibir los mismos mensajes . Por ejemplo, dado que un objeto de tipo Gato es tambien un objeto de tipo Animal, se puede hacer codigo pensando en los mensajes
que se mandan a un animal y aplicarlo a todos los objetos de ese tipo, sin pensar si son tambien gatos o no.
Eso de que la programacion orientada a objetos intente establecer una relacion biunvoca entre el espacio del problema y el de la solucion esta bien pero... como se logra que un objeto realice cosas u tiles y necesarias? Por medio
de su interfaz, que esta definida en la clase del objeto. Por ejemplo, suponga que se tiene la clase Interruptor
cuya interfaz define los metodos apagar() y encender(). Entonces se hace lo siguiente:
Interruptor i = new Interruptor();
i.encender();
Primero se crea una referencia llamada i de tipo Interruptor, y luego se crea un objeto, una instancia de dicho
tipo, por medio de la palabra reservada new . Se asigna ese objeto a la referencia por medio del signo =. Por
u ltimo, se enva un mensaje al objeto recien creado y asignado, poniendo el nombre de la referencia, un punto, y
el nombre del mensaje (metodo).
Algunos lenguajes modernos y de e xito, como Visual Basic y Delphi, presumen de estar orientados a objetos y
esto no es cierto, la verdad es que solo estan parcialmente orientados a POO y no aprovechan toda la potencia de
esta filosofa de programacion.
C++ es el lenguaje que impulso y popularizo la filosofa POO y sin duda es un lenguaje completamente orientado
al objeto. Sin embargo, C++ incorpora algunas caractersticas no estandares (muchos autores discuten que formen
parte de POO) como la herencia multiple. Ademas, nada impide desarrollar un programa en C++ no orientado a
objetos. En Java, esto no es posible, puesto que en Java todo son objetos. Incluso para desarrollar el mas simple
programa, se necesita construir por lo menos un objeto. Esto da una idea del grado de relacion entre Java y POO,
filosofa de programacion de la que aprovecha todas sus ventajas.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.


1.3. INSTALACION

1.2.4.

Integracion en la Red

El bytecode tiene la caracterstica de ocupar muy poco espacio. Para tener una idea, el ejemplo final del
captulo(ver seccion 1.4), ocupa en disco solo 420 bytes. Esta virtud lo hace ideal para integrarse en la red Internet
y desde un principio Sun penso en la Worl Wide Web.
En efecto, se pueden integrar pequenos programas Java (applets) en paginas web y as se tiene la posibilidad de
distribuir facilmente un contenido ejecutable. Este contenido, da la posibilidad al usuario que visita una pagina,
de interactuar con esta y convertirla en algo mas que un simple texto plano.
Por otro lado, Java cuenta con una amplia biblioteca de clases para comunicarse, empleando protocolos de Internet
TCP/IP e incluyendo otros protocolos tales como HTTP y FTP. El codigo Java, puede manipular recursos via URL
con la misma facilidad a la que se esta acostumbrado para acceder a un sistema de archivos local empleando Pascal,
C o Basic.

1.2.5.

Multitarea

Java permite desarrollar programas de forma que corran varios procesos al mismo tiempo en un mismo computador. Mientras esta corriendo un proceso, se puede ordenar que comience a ejecutarse otro de una forma muy
sencilla. Esta es una gran ventaja que es bien aprovechada por los grandes servidores web y servidores de aplicaciones basados en Java, al explotar sin mayor esfuerzo las potencialidades del hardware de los servidores.

1.2.6.

Robustez

Un software robusto, es el que no se interrumpe facilmente a consecuencia de fallos a la hora de programar


o eventuales errores logicos en la programacion. Un lenguaje de programacion que favorezca esta robustez del
software, suele poner mas restricciones al programador a la hora de escribir el codigo fuente. Tales restricciones
incluyen las relativas a la escritura de datos y al empleo de punteros.
El lenguaje de programacion C, es poco riguroso a la hora de comprobar compatibilidades de escritura de datos
durante la compilacion y el tiempo de ejecucion. El lenguaje C++ es un poco mas rgido en este aspecto, pero
retiene algunos errores respecto a la escritura de datos. Y para que mencionar los problemas de C y C++ con
punteros.
En Java, al contrario la escritura de datos es mas rigurosa. Java no permite el uso de punteros y por lo tanto es
imposible la escritura de datos de forma accidental, lo que puede traer consecuencias catastroficas. Java tambien
hace un chequeo de los lmites de un arreglo antes de escribir en el, por lo que tambien es imposible escribir fuera
de los lmites de un arreglo. En definitiva, es imposible escribir en sitios indeseados de la memoria, cosa que un
programador en C o C++ puede hacer accidental o deliberadamente.

1.2.7.

Seguridad

La posibilidad de distribuir un contenido ejecutable en la red, podra significar una autentica fiesta para los
hackers. Imagine por un momento, un applet en una pagina HTML que al ser descargado, formatee su disco duro
o lea datos de su computador. Afortunadamente, los creadores de Java se preocuparon bastante de este detalle y
crearon un modelo bastante seguro que hacen imposible que un applet pueda hacer algo danino, por el hecho de
descargarlo de un servidor web.

1.3.

Instalacion

Las siguientes instrucciones ayudaran paso a paso, en la instalacion de la plataforma de trabajo Java. Estas
instrucciones son para usuarios de plataformas Win32, que incluye Windows 9x, Windows Me, Windows NT,
Windows 2k y Windows XP.
En realidad, solo se necesitan dos cosas:
4

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

A JAVA
CAPITULO 1. INTRODUCCION
1. Primero, la Edicion Estandard de la Plataforma Java 2 (J2SE) que puede ser bajada desde http://
java.sun.com/j2se/1.4/download.html. Instalar el J2SE es bastante facil y ante cualquier duda, se
pueden consultar las instrucciones de instalacion del proveedor, en http://java.sun.com/j2se/1.4/
install-windows.html
2. Luego, se necesita un editor de texto para editar los archivos fuentes, para lo cual basta el Notepad de
Windows. Pero se recomienda usar Editplus, que provee entre otras caractersticas, autocompletacion de
instrucciones, resaltado de sintaxis e integracion con el compilador y la JVM. Editplus se puede obtener de
http://www.editplus.com.
Es aconsejable, crear un directorio para almacenar todos los programas que se escriban. Por ejemplo,
C:/codebase
Si se desea realizar una instalacion en una plataforma Unix, los pasos a seguir son practicamente los mismos. La
mayor traba que ofrece este ambiente de desarrollo, es el editor de texto. En la mayora de los casos habra que
conformarse con el vi.

1.3.1.

Distribuciones

Java esta disponible en varias distribuciones, a saber:


J2SE : Edicion estandar que contiene todo lo necesario para empezar a programar aplicaciones profesionales.
J2EE : Incluye el J2SE y ademas agrega un sin numero de nuevas funcionalidades enfocadas al desarrollo de
grandes aplicaciones empresariales.
J2ME : Edicion reducida(Micro Edition), que permite el desarrollo de aplicaciones incrustadas, es decir, muy
especficas sobre chips de escasos recursos. Por ejemplo, un controlador de lavadoras.
Ademas existe un sin numero de paquetes opcionales, tanto de SUN como de otros proveedores, que permiten
ampliar las funcionalidades de Java. Por ejemplo,
Java3D : Paquete de SUN que permite la programacion de aplicaciones con graficas 3D, es parte de un conjunto de paquetes adicionales agrupados bajo el nombre de Java Media, que incluye desde libreras para manipulacion de imagenes, hasta herramientas de reconocimiento de voz. Para mas informacion, ver
http://java.sun.com/products/java-media/.
JAXP : Java API for XML Processing, paquete de SUN que permite la manipulacion de archivos XML.
JavaMail : Paquete de SUN que permite la manipulacion de correos electronicos.
Entre muchos otros.

1.3.2.

Ayuda en Lnea

SUN ofrece un sin numero de documentos de ayuda, manuales de referencia, tutoriales y libros online, todo
disponible en http://java.sun.com/docs.
Para encontrar documentacion en espanol, ver la bibliografa de este curso [1].

1.4.

Primer Programa Java

Ahora, se vera un primer ejemplo totalmente ejecutable, con el cual se revisaran los pasos necesarios para
compilar y ejecutar un programa Java, como tambien los errores tpicos que se podran presentar.
El codigo es el siguiente:
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

1.4. PRIMER PROGRAMA JAVA


public class HelloWorldApp {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
Este codigo debe ser guardado en un archivo con el mismo nombre que la clase que define y con la extension
.java, en este caso, HelloWorldApp.java. Mas especficamente, c:/codebase/HelloWorldApp.java.
Hay que ser cuidadoso con el nombre de las clases y archivos, y en general, cualquier identificador, ya que Java
diferencia entre mayusculas y minusculas.
Ahora se analizara con detalle el codigo presentado. La primera lnea define una estructura importantsima en el
lenguaje Java, la estructura class . No es el momento de estudiarla en profundidad. Basta con saber por ahora,
que una estructura class define una clase y que todo el codigo encerrado entre un par de llaves ({ }) inmediatamente despues de la definicion de esta estructura, pertenece a ella.
No es el caso de este ejemplo, pero un archivo puede tener mas de una estructura class .
Si se ha programado anteriormente en cualquier lenguaje, se vera enseguida que la segunda lnea define un metodo. En este caso, tiene un parametro y no retorna valor alguno. Mas adelante se profundizara en los metodos de
Java.
La finalidad de la tercera lnea es simplemente escribir una lnea de texto seguida por un retorno de carro en la
pantalla.
Luego, se indica el termino del metodo y luego el termino de la clase.
El metodo main() es especialmente importante. Toda aplicacion Java debe incluir en su codigo este metodo,
puesto que es el punto de entrada de la aplicacion. La primera sentencia del programa que se ejecuta, es la primera
sentencia que este dentro de este metodo. El metodo main() debe estar definido exactamente como se indica, lo
u nico que se puede variar en la definicion de este metodo, es el nombre que se le da al parametro de este metodo.
En un archivo o unidad de compilacion, la clase (o estructura class ) que contiene al metodo main(), se denomina clase principal y tiene que cumplir dos normas. La primera, es que debe definirse como public (mas
adelante se vera que significa esto) y la segunda, que debe llamarse exactamente igual que el archivo en donde se
encuentra definida.

1.4.1.

Compilacion

Ahora es necesario compilar este archivo fuente para obtener un ejecutable, llamado en este caso
HelloWorldApp.class. Para lograrlo es necesario ejecutar el comando:
javac -classpath c:/codebase; %CLASSPATH % HelloWorldApp.java
Lo que hace esta lnea es, decirle al compilador que compile el archivo HelloWorldApp.java, y que para ello
busque cualquier referencia que pueda hacer este archivo a otra clase, en el directorio c:/codebase, ademas de
buscar donde normalmente lo hara.
Otra manera, es setear la variable de entorno CLASSPATH, de tal forma que tambien incluya este directorio. Con
esto, bastara ejecutar:
javac HelloWorldApp.java
El compilador busca las referencias donde se le indica y si encuentra alguna que no este compilada o este desactualizada, la compila tambien.
El error mas tpico durante la compilacion es cuando se recibe el mensaje:
Bad command or file name
Que significa que Windows no puede encontrar el compilador Java, javac. Puede ser, que esto se deba a que no
se ha instalado el J2SE adecuadamente o que solo falta incluir el directorio %java home %/bin a la variable de
entorno PATH, siendo %java home % el directorio de instalacion del J2SE.
6

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

A JAVA
CAPITULO 1. INTRODUCCION

1.4.2.

Ejecucion

Una vez creado el archivo ejecutable, se puede ejecutar usando el comando:


java -cp c:/codebase; %CLASSPATH % HelloWorldApp
En donde, la opcion -cp tiene la misma interpretacion que la opcion -classpath al compilar. Y tambien puede
ser omitida, una vez que este bien seteada la variable de entorno.
El error mas tpico al momento de la ejecucion de un programa Java es, cuando se recibe el mensaje:
Exception in thread "main"java.lang.NoClassDefFoundError: HelloWorldApp
Que significa que, Java no puede encontrar el archivo de bytecodes, HelloWorldApp.class. Lo que se puede
deber a dos cosas: Primero, que se halla producido algun error al compilar (o no se halla compilado), o segundo,
que la variable CLASSPATH esta mal seteada.

Michael Moossen

Departamento de Informatica. U.T.F.S.M.

1.4. PRIMER PROGRAMA JAVA

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

Captulo 2

Principios de Programacion con Java


2.1.

La Sintaxis del Lenguaje

La sintaxis de Java, como la de (casi) cualquier otro lenguaje de programacion, esta dada por distintos elementos contructivos basicos:
Palabras Clave
Identificadores
Literales
Separadores
Comentarios
A continuacion se detallara rapidamente cada uno.

2.1.1.

Palabras Clave

Las palabras clave son palabras reservadas por el lenguaje Java, para un proposito definido y especfico. Estas
no se pueden usar como identificadores . Y son:
abstract
int
boolean
interface
break
long
byte
native
case
new

catch
null
char
package
class
private
const
protected
continue
public

default
return
do
short
double
static
else
super
extends
synchronized

false
switch
final
this
finally
throw
float
throws
for
transient

goto
true
if
try
implements
void
import
volatile
instanceof
while

Ademas, el lenguaje se reserva unas cuantas palabras mas, que hasta ahora no tienen una funcion especfica.
Estas son:
cast
inner

const
operator

future
outer
9

generic
rest

goto
var

2.1. LA SINTAXIS DEL LENGUAJE


La Palabra Clave null
Este identificador es la referencia nula. Es decir, cuando se tiene una referencia a un objeto, y aun no se le
quiere asignar uno, pero se desea utilizar esa variable, entonces se le asigna null :
public class Nulo {
public static void main(String[] args) {
String cad = null ;
if (cad == null )
System.out.println("Es nulo");
}
}
Como Java es un lenguaje seguro, si no se inicializa la referencia cad y se intenta acceder a ella, dara un error de
compilacion. Esto tiene una excepcion: cuando se crea un arreglo, todos sus elementos se inicializaran automaticamente en null . Esto se debe a que en tiempo de compilacion, Java no tiene manera de saber que elementos
estan inicializados y cuales no, por lo que no puede dar un error.

2.1.2.

Identificadores

Un identificador es un nombre que se da a un elemento, es decir, una clase, un metodo, una propiedad, etc.
Java distingue entre mayusculas y minusculas, y los identificadores pueden comenzar por una letra, un subrayado
o un smbolo de peso, siendo los siguientes caracteres letras o dgitos, y pueden ser de hasta mas de 500 caracteres
de largo. Por ejemplo, son identificadores validos:
contador
nombre usuario
$dinero
Se recomienda no usar identificadores que comiencen con el signo peso o por el signo de subrayado.

2.1.3.

Literales

Los literales son un mecanismo utilizado para expresar un valor constante (en tiempo de compilacion). Java
utiliza cinco tipos de elementos literales: enteros, reales en coma flotante, booleanos, caracteres y cadenas:
Tipo
Enteros
Reales
Booleanos
Caracteres
Cadenas

Ejemplo
21, 0xDC
3.14, 2e12
true , false
x, \t, \u0234
"Esto es una cadena"

Notar que, mientras los caracteres se expresan encerrados en comillas simples (), las cadenas lo hacen en comillas
dobles (").

2.1.4.

Separadores

Existen otros elementos con significado especial en Java. Estos son los separadores, que en general, delimitan
cierta region del codigo, dandole un cierto significado especfico, segun la siguienta tabla:
10

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION
Separador
( )

{ }
[ ]
;
,
.

2.1.5.

Descripcion
Contienen listas de parametros, tanto en la definicion de un metodo, como en la llamada al mismo.
Tambien se utilizan para modificar la precedencia en una expresion (Seccion 2.4.8), contener
expresiones para control de flujo (Seccion 2.5.1) y realizar conversiones de tipo (Seccion 2.3.2).
Se utilizan para definir bloques de codigo, definir a mbitos (Seccion 2.2.2) y contener los valores
iniciales de arreglos (Seccion 2.2.4).
Se utilizan tanto para declarar arreglos o matrices, como para referenciar valores dentro de los
mismos (Seccion 2.2.4).
Separador de sentencias.
Separador de identificadores consecutivos en la declaracion de variables y en las listas de parametros. Tambien se utiliza para encadenar sentencias dentro de una estructura for (Seccion 2.6.2).
Separa un nombre de propiedad o metodo de una variable de referencia (Seccion 2.3.3). Tambien
separa nombre de paquete de los de un subpaquete o una clase. (Seccion 3.10)

Comentarios

Los comentarios en Java son como los de C++ pero con ciertas funcionalidades especiales, para mas detalle
de esto ver seccion A.1. Los comentarios basicos son:
Comentarios de Fin de Lnea
Este tipo de comentario es introducido por // y dura hasta final de lnea:
// Esto es un comentario
Comentarios de Parrafo
Los comentarios de parrafo o bloque, pueden ocupar mas de una lnea, comenzando con /* y terminando
con */:
/* Esto es un
comentario */

2.2.

Variables

2.2.1.

Declaracion

Declarar una variable es darla a conocer al compilador y as tenerla lista para su posterior uso.
Declarar una variable en Java es muy sencillo. En primer lugar se indica el tipo de dato al que se quiere que
pertenezca esa variable y en segundo lugar su nombre. Algunos ejemplos de declaraciones:
int variable;
short variable short;
long largo;
Se puede inicializar la variable a un determinado valor, en el mismo momento en que se declara. Esto es recomendable y se sugiere como regla de oro, siempre inicializar las variables, ya sea con un valor u til, o cero o null
para luego asignarle un valor u til en tiempo de ejecucion. Para inicializar una variable se hace uso del operador
= seguido del valor que se quiere asignar a la variable, por ejemplo:
int variable = 234;
En realidad esta u ltima sentencia equivaldra a estas dos sentencias seguidas:
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

11

2.2. VARIABLES
int variable;
variable = 234;
Pero, por comodidad y claridad en el codigo, es recomendable la primera forma.
Otros ejemplos de declaraciones-inicializaciones:
String nombre = "Jose Antonio";
int fecha = 2000;
short negativo = -231;
float decimal = 234.565F;
char caracter = \u0234;

2.2.2.

Ambito

Una variable declarada dentro de un metodo, tiene su a mbito restringido al bloque delimitado por llaves ({ }),
en que fue declarada. Por ejemplo,
void main() {
...
int a;
//Aqu comienza el
ambito de a
...
}
//Aqu termina
Las variables declaradas en un bloque pueden ser sobreescritas por variables declaradas en un subbloque. Por
ejemplo,
void main() {
int a = 1;
...
if (cond) {
String a = "abc";
...
}
...
}
Se debe ser muy cuidadoso con este tipo de codigo, por lo que se recomienda evitarlo.
Por el contrario, en el caso de las variables declaradas a nivel de clase, tambien llamadas atributos o propiedades
de la clase, el a mbito de acceso es global dentro de la clase y el acceso fuera de la ella esta determinado por el
modificador de acceso con que se declara la variable.

2.2.3.

Control de Acceso

Cuando se crea una nueva clase en Java, se puede especificar el nivel de acceso que se quiere para las variables
de instancia y los metodos definidos en la clase por medio de los siguientes modificadores de acceso:
public :
Cualquier clase puede acceder a las propiedades y metodos publicos.
protected :
Solo las clases heredadas pueden acceder a las propiedades y metodos protegidos.
private :
Las variables y metodos privados solo pueden ser accedidos desde dentro de la clase.
12

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION
Por defecto
Tambien llamado, friendly. Solo las clases heredadas y aquellas situadas en el mismo paquete pueden acceder a las propiedades y metodos.
Por ejemplo:
class Acceso {
public int publica = 0;
private char privado = x;
protected float protegido = 2.7f;
double amigo = 1.3;
}

2.2.4.

Arreglos

Un arreglo (array) es una manera de agrupar valores de un mismo tipo bajo un mismo nombre. Para acceder
a los valores individuales, se asigna a cada uno de ellos un numero denominado ndice, el cual comienza desde
cero. En Java, se pueden declarar arreglos de dos maneras:
char c[];
char [] c;
De cualquiera de las dos formas, se obtiene un arreglo de caracteres. A partir de ahora, cuando se declare un
arreglo, se utilizara la segunda manera, que separa la declaracion de tipo del nombre de la variable; al contrario
que la primera, que solo representa un mal recuerdo de C y C++.
Crear matrices (arreglos multidimensionales) es tan sencillo como anadir corchetes:
char [][] c;
Los arreglos en Java son en realidad objetos (como casi todo) y por lo tanto se inicializan llamando a un constructor
con new (ver seccion 3.6.1), aunque el constructor tenga una sintaxis totalmente distinta a la vista hasta ahora:
int [][] numeros = new int [30][10];
Existe otra manera de hacerlo y es indicando los valores iniciales en la declaracion:
String[] paises = { "Chile", "Argentina", "Per
u"};
Esta declaracion es equivalente a crear el arreglo por medio de un constructor, e ir asignandole los valores uno a
uno:
String[] paises = new String[3];
paises[0] = "Chile";
paises[1] = "Argentina";
paises[2] = "Per
u";
Como se puede observar, para acceder a un valor especfico de un arreglo, se pone el nombre del mismo, acompanado del ndice correspondiente al valor encerrado entre corchetes. Esto tambien es valido cuando se quiere
consultar el valor del mismo:
public class Arreglos {
static String[] paises = { "Chile", "Argentina", "Per
u"}
public static void main(String[] args) {
System.out.println(paises[1]);
}
}
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

13

2.3. TIPOS DE DATO


Y, como buen objeto que son, todos tienen un metodo llamado length , que indica la longitud del arreglo. Por
ejemplo,
public static void main(String[] args) {
System.out.println(paises[1]);
System.out.println(paises.length );
}
Nota: En realidad, como se puede apreciar en el ejemplo, length es un atributo y no un metodo. Conviene
recordar que los arreglos son objetos, porque a la hora de pasar argumentos a una funcion, se pasaran por referencia
y no por valor, como los tipos de dato basicos.
Por otra parte, hay que tener ciudado al inicializar arreglos multidimensionales, por ejemplo:
String[][] paises = { {"Chile", "Argentina"}, {"Per
u"} };

Esto produce un arreglo de dos arreglos de String, uno de largo dos y el otro de largo uno!.

2.3.

Tipos de Dato

2.3.1.

Basicos

En Java, todo lo que se mueve es un objeto... excepto los tipos de datos basicos, es decir, numeros enteros,
reales, caracteres, valores logicos, etc. Todo lo demas seran objetos o, mejor dicho, referencias a objetos. Son los
u nicos valores que se crean sin utilizar el operador new (ver seccion 45). Y son los siguientes:
Tipo
boolean
char
byte
short
int
long
float
double
void

Descripcion
Valor logico
Caracter
Entero muy pequeno
Entero pequeno
Entero normal
Entero grande
Numero real de precision simple
Numero real de doble precision
Tipo vaco

Tamano
1 bit
16 bit
8 bit
16 bit
32 bit
64 bit
32 bit
64 bit

Clase Encapsuladora
Boolean
Character
Byte
Short
Integer
Long
Float
Double
Void

Podemos crear variables de estos tipos de la manera normal en todos los lenguajes que siguen a C:
int numero = 12;
El definir un valor al declararlo no es necesario, especialmente porque en Java todos tienen un valor por defecto
(0 en los numeros, false en los booleanos y el caracter \x0); en ese caso se puede escribir simplemente:
int numero;
Siempre se debera preferir el uso de las clases que encapsulan(en ingles, Wrappers) los tipos basicos, a usar los
tipos basicos por si mismos. En este ejemplo sera:
Integer numero = new Integer(12);
Ademas, todas las clases encapsuladoras de tipos de datos basicos, excepto Boolean, tienen atributos MIN VALUE
y MAX VALUE, con lo cual se puede obtener el rango de valores que acepta el tipo de dato particular. As ejecutando:
14

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION
class Wrappers {
public static void main(String[] args) {
System.out.println("Byte: "+ Byte.MIN VALUE + "... "+ Byte.MAX VALUE);
System.out.println("Short: "+ Short.MIN VALUE + "... "+ Short.MAX VALUE);
System.out.println("Integer: "+ Integer.MIN VALUE + "... "+ Integer.MAX VALUE);
System.out.println("Long: "+ Long.MIN VALUE + "... "+ Long.MAX VALUE);
System.out.println("Float: "+ Float.MIN VALUE + "... "+ Float.MAX VALUE);
System.out.println("Double: "+ Double.MIN VALUE + "... "+ Double.MAX VALUE);
System.out.println("Character: "+ (int )Character.MIN VALUE + "... "+
(int )Character.MAX VALUE);
}
}
Se obtiene:
Tipo
Byte
Short
Integer
Long
Float
Double
Character

Mnimo
-128
-32768
-2147483648
-9223372036854775808
1.4E-45
4.9E-324
0

Maximo
127
32767
2147483647
9223372036854775807
3.4028235E38
1.7976931348623157E308
65535

Notar que, para los numero reales se indica solo el rango positivo, a esto hay que agregarle el mismo rango
negativo.

2.3.2.

Conversion de Tipos

Como en muchos otros lenguajes de programacion, en Java tambien es posible asignar un valor de un tipo a
una variable de otro tipo. A pesar que esto no representa mucha dificultad, es necesario estar consciente que se
pueden dar ciertos efectos secundarios al convertir datos, para lo cual hay que tener claros algunos conceptos y
procedimientos del compilador:
Conversion de tipos Automatica
Si al hacer la conversion de un tipo a otro, se dan las dos siguientes premisas:
Los dos tipos son compatibles.
El tipo de la variable destino es de un rango mayor al tipo de la variable que se va a convertir.
Entonces, la conversion entre tipos es automatica, e sto es, la JVM tiene toda la informacion necesaria para realizar
la conversion sin necesidad de ayuda externa. A e sto se le conoce como conversion implcita y cuando se habla
de los tipos numericos de Java, se le da el nombre de widening conversion que traducido vendra a ser algo
as como conversion por ampliacion. No obstante, no todos los tipos numericos son compatibles con char o
boolean (concretamente byte y short ) y estos dos tampoco lo son entre ellos.
Conversion de Tipos Incompatibles
Cuando alguna de las 2 premisas anteriores no se cumple, entonces la conversion automatica es imposible
(salvo que se este evaluando una expresion como se ve en la seccion siguiente), el compilador da un error diciendo
algo as como la variable tal necesita una conversion explcita. Pero, no es que no se pueda realizar tal conversion,
sino que la JVM necesita de informacion adicional: el tipo al que se va a convertir la variable de origen. Pues
bien, esta conversion explcita es llamada un casting de tipos. Cuando se trata de tipos numericos, a este tipo de
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

15

2.3. TIPOS DE DATO


conversion se le llama narrowing compresion que se podra traducir como conversion por estrechamiento dado
que se esta recortando la variable para poder guardarla en el tipo destino.
La expresion general del casting de un tipo es:
(tipo destino) valor
donde tipo destino indica el tipo al que se quiere hacer la conversion explcita del valor deseado.
En el caso de los tipos numericos, al recortar el valor de la variable de rango mayor para que quepa en el tipo de
rango menor, resulta que se pierde informacion. Mas adelante, se vera en que se traduce esa perdida de informacion
segun sean los tipos.
Promocion de Tipos Automaticamente al Evaluar una Expresion
Aqu radica uno de los puntos donde la conversion puede dar problemas si no se sabe, pero que una vez
asimilado es una de las muchas ventajas que Java tiene frente a otros lenguajes. El caso es que cuando la JVM,
tiene que analizar una expresion, existe la posibillidad real de que el resultado intermedio de una operacion exceda
el rango de los operandos. Para solventar este problema, lo que Java hace es una promocion automatica de todos
los operandos de tipo byte o short a int. Pero esto tambien puede llevar al error de que se haga una conversion de
tipos incompatibles y, al no hacer el casting correspondiente, la compilacion fallara. Como se ve en el siguiente
ejemplo:
Caso 1:
byte a = 40;
byte b = 50;
int c = a * b; //el compilador no dar
a ning
un error.
Caso 2:
byte a = 25;
a = a*2; //ERROR: Explicit cast needed to convert int to byte.
Ahora, como puede dar este error si el resultado no excede del rango de un tipo byte (-128, 127)?.
Pues bien, lo que ocurre, es que al hacer la multiplicacion, Java ha promocionado automaticamente este valor a int
y por eso para volver a guardarlo en un tipo byte , se tiene que hacer una conversion explcita. En el primer caso,
este error no se produce porque el resultado de la operacion se guarda en un int .
a = (byte )a*2; //ahora el compilador no dar
a ning
un error.
Para concluir con las reglas de promocion de tipos cuando se evaluan expresiones, se dan a conocer otros detalles
mas, que es conveniente tener en cuenta:
Si alguno de los operandos es long , entonces la expresion entera promociona a long .
Si alguno de los operandos es float , entonces la expresion entera promociona a float .
Si alguno de los operandos es double , entonces el resultado sera double .
Por u ltimo, recuerde que cuando un metodo devuelve Object, dado que esta clase es la super-clase de todas, se
puede y a veces se debe hacer un casting explcito al tipo de la variable que interesa. Por ejemplo, si se tiene un
vector en el que se introducieron elementos del tipo MiClase, para poderlos recuperar, hay que ejecutar:
MiClase var = (MiClase) vector.get(index);
A continuacion una serie de casos practicos para concluir este tema.
16

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION
class ConversionTipos {
public static void main(String args[]) {
byte b;
int i = 257;
double d = 323.142;
double d2;
float f = 5.65f;
char c = c;
short s = 1024;
b = (byte ) i;//efecto: se devuelve (i modulo 256), rango de byte.
System.out.println(b);
i = (int ) d;//efecto: truncamiento de la parte decimal.
System.out.println(i);
b = (byte )d;//efecto: truncamiento y luego (result truncado modulo 256)
System.out.println(b);
i = (int )f;//efecto: truncamiento de la parte decimal
System.out.println(i);
i = c;//correcto por ser int, pero un byte necesitar
a un cast expl
cito.
System.out.println(i);
f = c; d = c;//correcto.
i = b * c;//efecto: la operaci
on promociona a int.
System.out.println(i);
d2 = (f*b) + (i/c) - (d*s);
/*
efecto: el resultado de la promoci
on de todas las expresiones es un double:
(f*b) promociona a float, (i/c) promociona a int y (d*s) promociona a double.
Luego, float + int - double promociona a double.
*/
System.out.println(d2);
}
}

2.3.3.

Objetos

Ahora bien, a parte de los tipos de dato basicos, que pueden ser cien por ciento reemplazados por sus respectivos wrappers, todo lo demas son objetos.
Para declarar un objeto en el codigo, primero se indica la clase del objeto a crear, seguido del identificador del
objeto. El objeto declarado, tambien puede ser inicializado directamente, en la misma lnea. Por ejemplo,
String S = "abc";
Sus atributos y metodos publicos pueden ser accesados por medio del operador punto (.) . Siempre y cuando la
referencia no sea nula, en cuyo caso se genera un error en tiempo de ejecucion (NullPointerException). Por
ejemplo,
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

17

2.4. OPERADORES
Double.MIN VALUE;
S.trim();

2.4.

Operadores

Los operadores sirven para unir identificadores y literales para formar expresiones, que son el resultado de una
operacion. Los de Java son muy parecidos a los de C y C++.
De poco servira declarar variables o inicializarlas, si no se puede operar con estas: sumarlas, restarlas, multiplicarlas, compararlas, etc. Para este tipo de operaciones sobre las variables, existen los operadores. En funcion del
numero de operandos sobre los que actuan y el tipo de operacion que efectuan, los operadores en Java se clasifican
segun el siguiente cuadro:
Tipo
Unarios
Aritmeticos
Rotacion
Comparacion
Logicos
Ternarios
Asignacion

2.4.1.

++
*
<<
<
&
?:
=

-/
>>
<=

Operadores
+
!
%
+
>>>
>
>= ==
|
&& ||

()

!=

Operadores Unarios

Se caracterizan por actuar sobre un solo operando:


Operadores Unarios ++ y --
Estos operadores incrementan o decrementan, respectivamente, la variable en una unidad.
int val = 0;
++val;
La variable entera val ahora tiene el valor 1. Esta ha sido su utilizacion prefija. Ahora, se vera su utilizacion sufija.
int val = 0;
val++;
La variable entera val ahora tiene el valor 1. A pesar que a simple vista, pareciera que usar el operador ++ en
prefijo o en sufijo es lo mismo. La respuesta es no. En este ejemplo, se vera la diferencia:
int x = 34;
int y = ++x;
El valor final de x es 35 y el valor final de y es 35 tambien, sin embargo:
int x = 34;
int y = x++;
El valor final de x es 35, pero el valor final de y es 34.
La diferencia radica, en que al utilizar el operador en sufijo, primero se asigna el valor de x a y, y despues se
incrementa x en una unidad. Por el contrario, usando el operador en prefijo, primero se incrementa x en una
unidad, y luego se asigna el valor de x a y.
18

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION
Operadores Unarios + y -
Los operadores + y - dan signo positivo o negativo a una expresion numerica.
int variable = -2;
short variable = -(x + 5);
long siguiente = +4;
Operador Unario de Negacion !
El operador ! invierte el valor de una expresion booleana. Esto es, convierte true a false y viceversa.
boolean bool=!true ;
La variable bool tiene el valor false .
Operador Unario de Inversion
Este operador() actua sobre valores numericos enteros y realiza una inversion a nivel de bits. Todos los bits
del numero sobre el que actua son cambiados, incluyendo el bit del signo. Los ceros por unos y los unos por cero.
Operador Unario de Casting ()
Este operador es importante. Se llama operador de conversion y se utiliza para convertir expresiones numericas
de un tipo a otro, como se vio en la seccion 2.3.2.
int var=234;
long largo=(long )var;

2.4.2.

Operadores Aritmeticos

Estos operadores realizan operaciones aritmeticas en los operandos sobre los que actuan. No hay mucho que
explicar sobre estos operadores, porque hacen justo lo que se espera de ellos. El operador + suma, el operador
- resta, el operador * multiplica y el operador / divide. Unicamente, se explicara el operador % u operador
modulo.
Operador Aritmetico Modulo %
Da como resultado el resto resultante de la division entre los dos operandos sobre los que actua.
int resto = 14 % 3;
La variable resto tiene ahora el valor 2.
Todos estos operadores aritmeticos actuan sobre valores numericos, excepto el operador + que tambien lo hace
sobre cadenas de caracteres. Es posible sumar el contenido de dos cadenas de caracteres para formar una sola.
Por ejemplo:
String s1 = "Este curso ";
String s2 = "trata sobre el lenguaje Java";
String res = s1 + s2;
La cadena res tiene ahora el valor "Este curso trata sobre el lenguaje Java".
Tambien es posible, sumar una cadena y una variable. Automaticamente Java convertira el contenido de esa variable a un valor de cadena representable. Por ejemplo:
int var = 365;
String s = "Un a
no tiene ";
String res = s + var + "d
as";
La cadena res tiene ahora el valor "Un a
no tiene 365 d
as".
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

19

2.4. OPERADORES

2.4.3.

Operadores de Rotacion

Estos operadores actuan a nivel de bits.


Operadores de Rotacion >> y <<
Rotan a la derecha o la izquierda los bits del valor, el numero de posiciones especificado. Por ejemplo:
int var = 1;
var <<2;
La variable var ahora tiene el valor 4. Lo que se explicara a continuacion.
Inicialmente la variable var tiene el valor 1. Su representacion binaria es:
..00000001
En la primera rotacion, todos los bits se rotan a la zquierda una posicion:
..00000010
Y en la segunda rotacion:
..00000100
Cuyo valor en la numeracion decimal es 4. Observese que los bits que van apareciendo por la derecha son ceros.
La rotacion hacia la derecha es similar, excepto que cambia el sentido de rotacion de los bits.
Operador de Rotacion >>>
El operador >>> es ligeramente distinto al operador >> y a menudo es fuente de confusion. En realidad
es muy sencillo de comprender, pero se necesita entender con mas detalle, como se representan los numeros en
memoria.
Como ya se ha visto el tipo de dato int es un entero con signo de 32 bits. El numero 4 en memoria es representado
as:
00000000000000000000000000000100
Pero, para representar numeros negativos se utiliza el primer bit como una senal que indica si el numero es positivo
(bit igual a cero) o negativo (bit igual a 1). La representacion del numero -4 es entonces:
10000000000000000000000000000100
Cuando se rotan numeros negativos con el operador de rotacion a la derecha (>>) antes visto, el signo del numero
se respeta. Imagine que se rota el numero anterior a la derecha con el operador >>, el resultado sera:
10000000000000000000000000000010
Sin embargo, cuando se usa el operador >>> el bit de signo, no se respeta y es rotado tambien:
01000000000000000000000000000010
As, el resultado de la operacion:
int var = -4;
var >>>1;
La variable var tiene ahora el valor 2147483650. Sin embargo:
int var = -4;
var >>1;
La variable var tiene ahora el valor -2.
20

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION

2.4.4.

Operadores de Comparacion

Los operadores de comparacion dan como resultado siempre una expresion booleana (true o false ) independientemente de que los operandos sobre los que actuan sean numericos, booleanos, de caracter, etc.
Los operadores de comparacion en Java son: <, <=, >, >=, == y !=.
Literalmente y de izquierda a derecha estos operadores se leen as: menor que, menor o igual que, mayor que,
mayor o igual que, igual que y distinto de. Aunque su uso es bastante obvio, se vera un ejemplo por cada tipo de
operador de comparacion para su mejor comprension:
boolean resultado;
resultado = (5 <3);
La variable resultado se inicializa con el valor false .
boolean resultado = (3 <= (5 - 2));
La variable resultado se inicializa con el valor true .
boolean resultado = (10 >23);
La variable resultado se inicializa con el valor false .
boolean resultado = (10 >= 10);
La variable resultado se inicializa con el valor true .
boolean resultado = (20 == 21);
La variable resultado se inicializa con el valor false .
boolean resultado = (20 != 21);
La variable resultado se inicializa con el valor true .

2.4.5.

Operadores Logicos

Los operadores logicos pueden operar sobre operandos numericos o sobre operandos booleanos. En el primer
caso, devuelven una expresion numerica y en el segundo caso devuelven una expresion booleana. Cuando operan
sobre expresiones numericas, estos operadores actuan a nivel de bit.
Operador Logico AND &
La tabla logica de la operacion & es la siguiente:
&
0
1

0
0
0

1
0
1

Cuando se usa este operador con dos operandos numericos, este operador actua a nivel de bit. Por ejemplo:
int a = (6 & 2);
El valor de a es ahora 2, puesto que efectuando la operacion logica & sobre 6 y 2 se obtiene:
...0000110 (representaci
on binaria de 6)
...0000010 (representaci
on binaria de 2)
&
...0000010 (que en numeraci
on decimal es 2)

Michael Moossen

Departamento de Informatica. U.T.F.S.M.

21

2.4. OPERADORES
Cuando se usa este operador con dos operandos booleanos, se obtiene una expresion booleana y su uso es aun mas
sencillo. Solo hay que ver la tabla logica de la operacion & y tener en cuenta que false es cero y true es 1.
Por ejemplo:
boolean valor = (true & false );
La variable valor tiene ahora el valor false .
Operador Logico XOR
Su uso es similar al del operador logico &. La tabla logica de esta operacion es:

0
1

0
0
1

1
1
0

Por ejemplo:
int a = (6 2);
El valor de a es ahora 4 puesto que efectuando la operacion logica sobre 6 y 2, se obtiene:
...0000110 (representaci
on binaria de 6)
...0000010 (representaci
on binaria de 2)

...0000100 (que en numeraci


on decimal es 4)
En el caso de que los operandos sean booleanos, se devuelve un valor booleano.
boolean valor = (true true );
La variable valor tiene ahora el valor false .
Operador Logico OR |
La tabla logica de la operacion | es la siguiente:
|
0
1

0
0
1

1
1
1

Por ejemplo:
int a = (6 | 2);
El valor de a es ahora 6 puesto que efectuando la operacion logica | sobre 6 y 2, se obtiene:
...0000110 (representaci
on binaria de 6)
...0000010 (representaci
on binaria de 2)
|
...0000110 (que en numeraci
on decimal es 6)
En el caso de que los operandos sean booleanos, se devuelve siempre un valor booleano. Por ejemplo:
boolean valor = (true | false );
La variable valor tiene ahora el valor true .
22

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION
Operadores Logicos && y ||
Estos operadores solo pueden usarse sobre operandos booleanos y tienen una importante diferencia respecto a
los operadores & y |. Esta es, que puede que no se evalue el operando de la derecha si no es necesario, con lo
que se gana en eficiencia.
Si, por ejemplo, se efectua la operacion "exp a || exp b" y exp a vale true , entonces la expresion exp b
no es evaluada, puesto que da lo mismo que esta sea true o sea false debido a que el valor devuelto va a
ser invariablemente true . Esto mejora la mucho eficiencia en el caso de que exp b sea una expresion booleana
compleja, por ejemplo, formada de cientos de operandos.

2.4.6.

Operador Ternario

Tambien llamado Operador Condicional , es quizas el operador mas complejo de todos, pero es bastante u til.
Toma tres operandos, una condicion booleana y dos expresiones. El primer operando es una condicion booleana
y si su valor es true se evalua el segundo operando(la primera expresion), pero si es false se evalua el tercer
operando(la segunda expresion). Se vera un ejemplo para ver su funcionamiento:
boolean condicion = true ;
int resultado = (condicion) ? 13: -13;
La variable resultado se inicializa con el valor 13. Sin embargo:
boolean condicion = false ;
int resultado = (condicion) ? 13: -13;
La variable resultado se inicializa con el valor -13.

2.4.7.

Operadores de Asignacion

Operador de Asignacion =
Asigna un valor a la expresion a la izquierda del operador. Puede operar sobre todo tipo de datos.
int b = -123;
int a = b;
La variable a se inicializa con el valor -123.
Operadores de Asignacion *=, /=, %=, +=, &=, =, |=, <<=, >>= y >>>=
Ademas de realizar la asignacion, primero se realiza la operacion indicada. Por ejemplo:
int val = 6;
val *= 4;
La variable val tiene ahora el valor 24.

2.4.8.

Precedencia de Operadores

Cuando se necesita construir una expresion compleja con varios operandos y operadores, es importante saber
cuales de estos se resuelven primero, puesto que esto puede variar el resultado final de la expresion. Por ejemplo
en la expresion:
int x=2+4/2;
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

23

2.4. OPERADORES
Si se resuelve la expresion sumando 2 mas 4 y el resultado se divide entre 2 se obtiene en x el valor 3. Sin embargo,
si primero se divide 4 entre 2 y al resultado se le suma 2 se obtiene en x el valor 4.
Java sigue unas estrictas pero sencillas reglas a la hora de evaluar estas expresiones. El analisis de la expresion se
realiza siempre de derecha a izquierda, pero aun no esta resuelto el problema, porque aun siguiendo este orden,
pueden producirse resultados inconsistentes. Para resolverlo Java da un nivel de prioridad distinto a cada operador.
Segun la tabla siguiente:
Precedencia
Mayor

Menor

Operadores
.
[ ] ( )
++
-!
*
/
%
+
<<
>> >>>
<
>
<=
==
!=
&

&&
||
? :
=

>=

En la tabla los elementos de la misma fila tienen la misma precedencia. De los elementos de la misma columna
tienen mayor precedencia los que estan mas arriba. Se vera con un ejemplo, como resolvera el compilador de Java
una expresion compleja:
int res = ( 2 + 3 ) * 12 / 2 - (- 23);
El operador de mayor precedencia es el parentesis (), sin embargo, hay dos parentesis. Se resuelve primero el
de la derecha. Quedara la expresion:
int res = ( 2 + 3 ) * 12 / 2 + 23;
A continuacion el parentesis de la izquierda:
int res = 5 * 12 / 2 + 23;
Los operadores de division y de multiplicacion tienen superior precedencia al operador suma, pero la misma
precedencia entre ellos, luego se resuelve primero el operador de la derecha. La division:
int res = 5 * 6 + 23;
El operador multiplicacion tiene mayor precedencia que el operador suma.
int res = 30 + 23;
Y finalmente:
res = 53;
Es una buena practica, NO valerse de la precedencia de los operadores, sino que siempre incluir la cantidad
suficiente de parentesis, de tal forma que no quede ninguna duda del sentido de la expresion.
24

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION

2.4.9.

Operaciones con Objetos

El operador ==
A pesar que dos objetos pueden compararse usando el operador ==, esto generalmente, no generara el resultado esperado, ya que como Java no soporta sobrecarga de operadores, este operador compara las referencias de
los objetos, es decir, si ocupan el mismo espacio de memoria, y no su contenido. Sin embargo, esto puede producir
confusion, como se ve en el siguiente codigo:
String S1 = "a";
String S2 = "a";
if (S1==S2) {
System.out.println("Que pas
o aqu
?");
}
Lo que sucede es que, a pesar de que S1 y S2 se definieron por separado, el compilador optimiza el codigo,
reconociendo la repeticion del literal "a", guardandolo en solo una direccion de memoria, a la que luego apuntan
tanto S1, como S2.
Por lo tanto, para comparar objetos, siempre usar el metodo compareTo() si lo implementan, o usar el metodo
equals() que se vera mas adelante, en la seccion 2.9.
La Interfaz Comparable
Todas los wrappers de tipos de datos numericos basicos, implementan una interfaz que provee el siguiente
metodo:
int compareTo(Object o)
Esto debido a que Java no soporta sobrecarga de operadores, por lo que cualquier intento de usar operadores de
comparacion con objetos, resultara en un error de compilacion. As, x.compareTo(y) retorna un entero negativo
si x<y, cero si x=y y un entero positivo si se cumple que x>y. Con lo cual, se puede escribir codigo como el
siguiente ejemplo:
Double PI = new Double(3.1415);
Double E = new Double(2.7183);
if (E.compareTo(PI)<0) {
System.out.println("E <PI");
}
Que es equivalente a:
if (E.doubleValue()<PI.doubleValue()) {
System.out.println("E <PI");
}
El Operador instanceof
En ocasiones, puede ser necesario identificar en tiempo de ejecucion el tipo de objeto con el que se esta tratando. Debido a las capacidades de polimorfismo de Java, cuando se tiene una referencia a un objeto, puede que solo
se conozca que dicho objeto es una instancia de una clase o de cualquiera de sus derivadas. Y en ocasiones, puede
ser necesario saber de que clase especfica es dicho objeto.
Java provee de una manera sencilla para identificar el tipo de un objeto:
public class Identificacion {
public static void main(String[] args) {
Object o = new String("Hola");
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

25

2.5. CONTROL DE FLUJO


if (o instanceof String)
System.out.println("Es una cadena")
else
System.out.println("No es una cadena");
}
}
Al ejecutar el codigo: efectivamente es una cadena. Si se inicializa a cualquier cosa que no fuera una cadena dira
que no lo es.

2.5.

Control de Flujo

En Java existen varias sentencias de control de flujo, las mismas que provee C o C++.

2.5.1.

La Sentencia if

El mas basico, sencillo y utilizado es el if -else . Dado que else es opcional, se puede escribir de dos
formas:
if (expresi
on booleana) {
sentencias
}
o
if (expresi
on booleana) {
sentencias
}
else {
sentencias
}
Esta construccion permite ejecutar la primera sentencia si la expresion logica es verdadera. En caso de que sea
falsa (y de que el if -else este en la segunda forma) se ejecutara la segunda sentencia.

2.5.2.

La Sentencia switch

Para bifurcar tambien existe el switch :


switch (expresi
on) {
case valor1:
sentencia;
break ;
case valor2:
sentencia;
break ;
case valor3:
sentencia;
break ;
...
default :
sentencia;
break ;
}
26

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION
La estructura switch compara el valor contenido en la expresion, con cada uno de los valores situados despues
del case , ejecutando en caso de que exista coincidencia, el codigo situado a la derecha de los dos puntos. Ese
codigo no se engloba mediante llaves. Si no existe coincidencia, se ejecuta la sentencia optativa default . Cada
case debera terminar con una sentencia break , de no ser as se ejecuta el codigo del case siguiente.

2.6.

Ciclos

Ahora se vera las distintas estructuras que ofrece Java para realizar iteraciones.

2.6.1.

La Sentencia while

Las mas genericas son while y do -while :


while (expresi
on booleana) {
sentencia
}
y
do {
sentencia
} while (expresi
on booleana);
En ambos casos se ejecutara la sentencia, mientras se cumpla la expresion booleana. La diferencia consiste en que
en el primer caso, esa expresion se comprueba antes de iterar (ejecutar la sentencia) y en el segundo despues. Por
tanto, en ese u ltimo caso, la sentencia se ejecutara siempre al menos una vez.

2.6.2.

La Sentencia for

Otra iteracion interesante es el bucle for:


for (inicializaci
on; expresi
on booleana; paso) {
sentencias
}
En este caso lo primero que hara la JVM, sera ejecutar las sentencias (separadas por comas) contenidas en inicializacion, luego comprobara si es cierta la expresion booleana y ejecutara el codigo de sentencia. Finalmente
ejecutara las sentencias (separadas por comas) contenidas en paso y comprobara de nuevo la expresion booleana.

2.6.3.

Control de Flujo en Ciclos

Las capacidades de controlar el flujo de los ciclos, es bastante limitada, con lo que se ha visto hasta el momento.
Es por eso que Java, cuenta con un par de sentencias que ayudan a controlar el flujo en ciclos.
La Sentencia break
Esta sentencia permite abortar un ciclo definitivamente. Por ejemplo:
boolean cond = false ;
int sum = 0;
int prod = 1;
for (int i = 1; i <5; i++) {
sum += i;
if (i==4 && !cond) {
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

27

2.7. MANEJO DE EXCEPCIONES


break ;
}
prod *= i;
}
Que no es lo mismo que:
for (int i = 1; (i <5 && !(i==4 && !cond)); i++) {
sum += i;
prod *= i;
}
Ya que, en la segunda, no se ejecuta la u ltima suma.
La Sentencia continue
La sentencia continue permite abortar la iteracion actual, pero siguiendo la ejecucion en la proxima iteracion
normalmente. Por ejemplo:
int sum = 0;
int prod = 1;
for (int i = 1; i <5; i++) {
sum += i;
if (i==2) {
continue ;
}
prod *= i;
}
Con lo que se obtiene que, sum = 1+2+3+4 y prod = 1*3*4.

2.7.

Manejo de Excepciones

Las excepciones son la manera que ofrece Java de manejar los errores en tiempo de ejecucion. Muchos lenguajes imperativos, cuando tenan un error de esta clase, lo que hacan era detener la ejecucion del programa. Las
excepciones permiten escribir codigo que permita manejar ese error y continuar (si se estima conveniente) con la
ejecucion del programa.
El error en ejecucion mas clasico en Java, es el de desbordamiento. Es decir, el intento de acceso a una posicion
de un arreglo que no existe. Por ejemplo:
public class Desbordamiento {
static String mensajes[] = {"Primero", "Segundo", "Tercero"};
public static void main(String[] args) {
for (int i=0; i<=3; i++)
System.out.println(mensajes[i]);
System.out.println("Ha finalizado la ejecuci
on");
}
}
Este programa tendra un serio problema cuando intente acceder a mensajes[3], pues no existe dicho valor. Al
ejecutarlo dira lo siguiente (o algo parecido):
Primero
Segundo
28

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION
Tercero
Exception in thread "main"java.lang.ArrayIndexOutOfBoundsException
at Desbordamiento.main(Desbordamiento.java, Compiled Code)
Da un error de ejecucion (en esta terminologa se dira que se lanzo una excepcion) al intentar acceder a dicho valor
inexistente. Se ve que, por ahora, el comportamiento del codigo, es el mismo que en los lenguajes imperativos.
Cuando encuentra el error, se detiene la ejecucion. Ahora se vera como evitar esto.

2.7.1.

try...catch...finally

Existe una estructura que permite capturar excepciones, es decir, reaccionar ante un error de ejecucion. De
este modo se pueden imprimir mensajes de error a la medida y continuar con la ejecucion del programa si se
considera que el error no es demasiado grave. Para ver como funciona, se modificara el ejemplo anterior, pero
ahora capturando las excepciones:
public class PrimerCatch {
static String mensajes[] = {"Primero", "Segundo", "Tercero"};
public static void main(String[] args) {
try {
for (int i=0; i<=3; i++)
System.out.println(mensajes[i]);
}
catch (ArrayIndexOutOfBoundsException e) {
System.out.println("El asunto se ha desbordado");
}
finally {
System.out.println("Ha finalizado la ejecuci
on");
}
}
}
Dentro del bloque que sigue a try , se coloca el codigo a ejecutar. Es como si se intentara ejecutar dicho codigo
para ver que sucedera. Despues de try , se debe colocar al menos un bloque catch o un bloque finally ,
pudiendo tener ambos e incluso mas de un bloque catch .
En el bloque finally , se pone el codigo que se ejecutara siempre, tanto si se lanza la excepcion como si no.
Su utilidad no es mucha, ya que si se permite continuar con la ejecucion del programa, basta con poner el codigo
despues del bloque try ...catch . En el ejemplo se podra haber puesto lo siguiente:
try {
for (int i=0; i<=3; i++)
System.out.println(mensajes[i]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("El asunto se ha desbordado");
}
System.out.println("Ha finalizado la ejecuci
on");
Y habra funcionado exactamente igual. Lo importante esta en los bloques catch .

2.7.2.

La Clase Exception

Cuando se lanza una excepcion, en el mundo orientado a objetos, lo que se hace es lanzar una instancia de
Exception o de una clase derivada de ella. Normalmente, las clases derivadas no anaden mucha funcionalidad
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

29

2.7. MANEJO DE EXCEPCIONES


(muchas veces ninguna en absoluto), pero al ser diferentes, permiten distinguir entre los distintos tipos de excepciones.
En el programa anterior, por ejemplo, en el bloque catch se captura una excepcion del tipo
ArrayIndexOutOfBoundsException, ignorando cualquier otro tipo de excepcion.
Esta clase tiene dos constructores y dos metodos interesantes (tiene mas metodos pero solo se veran estos):
Exception e = new Exception();
Crea una excepcion sin ningun mensaje especfico.
Exception e = new Exception(String msg);
Crea una excepcion con un mensaje que detalla el tipo de excepcion.
String e.getMessage();
Devuelve el mensaje detallado si existe, o null en caso contrario.
void e.printStackTrace();
Escribe por la salida de error estandar, una traza que permite localizar donde se genero el error. Es muy u til para
depurar, pero no es conveniente que los usuarios finales vea estos mensajes.

2.7.3.

Capturar Excepciones

Ahora ya se tienen los conceptos suficientes como para entender como funcionan los catch . Entre parentesis,
como parametro se pone la declaracion de una excepcion, es decir, el nombre de una clase derivada de Exception
(o la misma Exception) seguido por el nombre de la variable. Si se lanza una excepcion, que es la que se desea
capturar o una derivada de la misma, se ejecutara el codigo que contiene el bloque. As, por ejemplo:
catch (Exception e) {
...
}
Se ejecutara siempre que se produzca una excepcion del tipo que sea, ya que todas las excepciones se derivan de
Exception. No es recomendable utilizar algo as ya que se captura cualquier tipo de excepciones sin saber si eso
afectara a la ejecucion del programa o no.
Se pueden colocar varios bloques catch . En ese caso, se comprobara en orden, si la excepcion lanzada es la que
se desea capturar y si no, pasa a comprobar la siguiente. Eso s, solo se ejecuta un bloque catch . En cuanto se
captura la excepcion, deja de comprobar los demas bloques. Por eso, lo siguiente:
catch (Exception e) {
...
} catch (DerivadaDeException e) {
...
}
Dara error, ya que el segundo bloque no podra ejecutarse nunca.

2.7.4.

Lanzar Excepciones

Bajo ciertas circunstancias puede ser deseable generar o lanzar una excepcion para que sea capturada por la
sentencia catch correspondiente. Esto es posible mediante la sentencia throw que recibe como parametro un
objeto que implemente la interfaz Throwable, en general, cualquier excepcion. Por ejemplo,
30

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION
try {
int i = 200;
byte b = (byte )i;
if (i!=b) {
throw (new Exception("Error de Conversi
on de Tipos"));
}
}
catch (Exception E) {
System.out.println(E.getMessage());
}
Aqu, Java no genera una excepcion por s mismo, debido a que la conversion de estos tipos de dato se realiza con
el modulo, pero puede ser que en una aplicacion real, se necesite hacer este tipo de conversiones, sin perder los
valores originales. La u nica forma de lograr esto es validar manualmente, y eventualmente lanzar una excepcion
en caso de error.

2.7.5.

Declaracion de Excepciones en Metodos

Todo metodo en el que se puede producir uno o mas tipos de excepciones (y que no utiliza directamente los
bloques try /catch /finally para tratarlos) debe declararlas en el encabezado de la funcion por medio de la
palabra throws . Si un metodo puede lanzar varias excepciones, se colocan despues de throws separadas por
comas, como por ejemplo:
public void leerArchivo(String fich) throws EOFException, FileNotFoundException
{...}
Se puede declarar solo una superclase de excepciones para indicar que se pueden lanzar excepciones de cualquiera
de sus clases derivadas. El caso anterior sera equivalente a:
public void leerArchivo(String fich) throws IOException {...}
Las excepciones pueden ser lanzadas directamente por leerArchivo() o por alguno de los metodos llamados
por e l.

2.8.

Recursividad

La recursividad es una caracterstica presente en casi todos los lenguajes de programacion, que trata simplemente de permitir que un metodo se invoque a s mismo. Java tambien lo permite, pero es necesario tener
presente ciertos detalles. Primero, a traves de la resursividad, se pueden abstraer problemas reales, de forma mas
clara y sencilla, como se vera en el ejemplo. Sin embargo, implica tiempos de ejecucion mucho mayores, debido
principalmente a la sobrecarga de guardar las variables locales y parametros en el stack.

2.8.1.

Numeros
de Fibonacci

A continuacion se mostrara el ejemplo clasico de los numeros de Fibonacci. Estos numeros forman una serie
que cumple las siguiente condiciones:
F1 = 1
F2 = 1
Fn = Fn1 + Fn2
Una funcion que calcule un elemento arbitrario de esta serie, se puede escribir como una funcion tpica usando
algun iterador, en este ejemplo se usa for :
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

31

2.9. LA CLASE OBJECT


long fibonacci(int num) {
long sum = 0L;
if (num == 1 || num == 2) {
sum = 1;
}
else {
long f1 = 1L;
long f2 = 1L;
for (int i = 3; i <= num; i++) {
sum = f1 + f2;
f1 = f2;
f2 = sum;
}
}
return sum;
}
As, al ejecutar fibonacci(30) se obtendra 832040 como resultado.
Esto mismo se puede lograr con un metodo recursivo:
long fibonacci(int num) {
long sum = 0L;
if (num == 1 || num == 2) {
sum = 1;
}
else {
sum = fibonacci(num-1) + fibonacci(num-2);
}
return sum;
}
donde, se ve mas claramente la logica del problema.
A pesar que, en general, los metodos recursivos son mas claros, siempre es preferible usar alguna adaptacion
iterativa del mismo, ya que su desempeno es peor y en metodos largos y complejos, la depuracion se vuelve
tambien mas compleja.
Para fijar una idea de eficiencia, el primer ejemplo da el resultado practicamente de inmediato para F20000 (aunque
incorrecto, debido a la precision numerica. Ver seccion 4.3.3) y la version recursiva, ya para calcular F45 demora
casi 5 minutos.
Sin embargo, pueden haber casos en los que es muy complicado disenar un algoritmo iterativo para un problema
claramente recursivo. En estos casos, se pueden mantener metodos recursivos, siempre y cuando la profundidad
de la recursion este bien acotada. Por ejemplo, no mas alla de un par de decenas de niveles.

2.9.

La Clase Object

Esta clase rara vez se utiliza directamente, pero por ser la clase de la que heredan todas las demas en Java,
existen varios metodos que se pueden y, a veces, se deben sobreescribir para lograr que las clases realicen ciertas
tareas correctamente. Los mas usados, entre otros, son:
boolean equals(Object O)
Comprueba si el objeto dado como parametro es igual al objeto actual. Esta implementacion comprueba
32

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON JAVA
CAPITULO 2. PRINCIPIOS DE PROGRAMACION
si ambas referencias son iguales por lo que no resulta muy u til, ya que es equivalente al operador ==.
Las distintas clases de Java suelen sobreescribirlo para comprobar si los contenidos de la instancia son
los mismos. Por ejemplo, cuando String sobreescribe este metodo, compara si las cadenas contenidas en
ambas instancias son iguales. Es una buena practica, sobrecargar este operador en las clases propias.
String toString()
Devuelve una representacion del objeto en formato de cadena. Es llamado automaticamente por Java cuando
necesita convertir el objeto en cadena de caracteres. Esta implementacion devuelve una cadena que contiene
el nombre de la clase del objeto, seguido de una arroba y del codigo Hash del mismo, lo cual no es muy u til,
pero s lo es, sobreescribirlo para obtener una verdadera representacion en String de la clase.
Existen otros metodos, pero estos son los mas importantes por el momento.

Michael Moossen

Departamento de Informatica. U.T.F.S.M.

33

2.9. LA CLASE OBJECT

34

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

Captulo 3

Programacion Orientada a Objetos


La tecnologa orientada a objetos se define como una metodologa de diseno de software, que modela las
caractersticas de objetos reales o abstractos, por medio del uso de clases y objetos. Hoy en da, la orientacion
a objetos es fundamental en el desarrollo de software, sin embargo, esta tecnologa no es nueva, sus orgenes se
remontan a la decada de los anos sesenta. De hecho, Simula, uno de los lenguajes de programacion orientados a
objetos mas antiguos, fue desarrollado en 1967.

3.1.

Taxonoma de Lenguajes Orientados a Objetos

Una clasificacion para los lenguajes de programacion con respecto a la orientacion a objetos fue creada por
Wegner. Dicha clasificacion se constituye de la siguiente forma:
Lenguajes Basados en Objetos: Si la sintaxis y semantica del lenguaje soportan las caractersticas de
objetos. Por ejemplo, Turbo Pascal 5 (por el soporte de modulos).
Lenguajes Basados en Clases: Si un lenguaje esta basado en objetos y ademas soporta clases, se dice que
esta basado en clases. Por ejemplo, Visual Basic 5 (por el soporte de modulos de clase, pero no da soporte
a herencia, por ejemplo).
Lenguajes Orientados a Objetos: Si un lenguaje de programacion soporta objetos, clases y ademas permite
la jerarqua de dichas clases, entonces se dice que es un lenguaje de programacion orientado a objetos. Por
ejemplo, Java.
Esta clasificacion es la que prevalece actualmente. Aqu se establece, claramente, que para que un lenguaje de
programacion sea considerado orientado a objetos, este debe soportar la creacion de clases y la herencia.
Java es actualmente uno de los lenguajes de programacion que cumple perfectamente con los requisitos de la
orientacion a objetos, Delphi, Simula, Smalltalk, son tambien considerados lenguajes orientados a objetos.
Java puede ser visto como el resultado de una mezcla de C++ y Smalltalk, tiene la sintaxis de C++, lo que lo
hace relativamente facil de aprender, si se esta familiarizado con C++.Sin embargo, una de las caractersticas
que lo hace mas robusto que C++, es que no tiene punteros, que son causa comun de errores en el desarrollo de
aplicaciones con este lenguaje. Como en el caso de Smalltalk , Java tiene recoleccion de basura, una capacidad
que libera al programador de definir funciones de reservacion y liberacion de estructuras en memoria.

3.2.

Ventajas de la Tecnologa Orientada a Objetos


Flexibilidad: Se parte del hecho de que mediante la definicion de clases se establecen modulos independientes, a partir de los cuales se pueden definir nuevas clases, entonces se puede pensar en estos modulos
como bloques con los cuales se puede construir diferentes programas.
35

3.3. DESVENTAJAS DE LA TECNOLOGIA ORIENTADA A OBJETOS


Reusabilidad: Una vez que se ha definido a la entidad Persona para utilizarla en una aplicacion de negocios, por mencionar un ejemplo, y se desea construir a continuacion una aplicacion, por ejemplo de deportes,
en donde se requiere definir a la misma entidad Persona, no es deseable volver a escribir la definicion para la entidad Persona. Por medio de la reusabilidad se puede utilizar una clase definida previamente en
las aplicaciones que sea conveniente. Es claro que la flexibilidad con la que se definio la clase va a ser
fundamental para su reutilizacion.
Mantenibilidad: Las clases que conforman una aplicacion, vistas como modulos independientes entre s,
son faciles de mantener sin afectar a los demas componentes de la aplicacion.
Extensibilidad: Gracias a la modularidad y a la herencia, una aplicacion disenada bajo el paradigma de la
orientacion a objetos, puede ser facilmente extensible para cubrir necesidades de crecimiento de la aplicacion.

3.3.

Desventajas de la Tecnologa Orientada a Objetos

A pesar de que las ventajas de la programacion orientada a objetos superan a las limitaciones de la misma, se
pueden encontrar algunas caractersticas no deseables en esta.
Limitaciones para el Programador: No obstante que la tecnologa orientada a objetos no es nueva, un
gran porcentaje de programadores no estan familiarizados con los conceptos de dicha tecnologa. En otras
palabras, la logica de la programacion estructurada sigue siendo predominante en la mayora de los desarrolladores de software. Despues de haber revisado de forma breve los principios de la programacion
orientada a objetos, es claro que en esta se requiere una logica de pensamiento totalmente diferente a la
logica comunmente utilizada para la programacion estructurada.
Excesivo en las Aplicaciones Resultantes: La gran mayora de los computadores actuales cuentan
Tamano
con capacidades tanto de almacenamiento como de memoria lo suficientemente buena como para ejecutar
la mayora de las aplicaciones que puedan desarrollarse con la tecnologa orientada a objetos. Sin embargo,
existen casos en los que lo anterior no se cumple. Una de las desventajas de la programacion orientada a
objetos es que cuando se heredan clases a partir de clases existentes, se heredan de forma implcita todos los
miembros de dicha clase aun cuando no todos se necesiten, lo que produce aplicaciones muy grandes que
no siempre encajan en los sistemas disponibles.
Velocidad de Ejecucion: Esto se relaciona, en cierto modo, con el punto anterior, una aplicacion innecesariamente pesada, en muchas ocasiones, es mas lenta de ejecutar que una aplicacion formada u nicamente por
los modulos necesarios.

3.4.

Caractersticas de la Tecnologa Orientada a Objetos

3.4.1.

Abstraccion

La abstraccion es el proceso en el cual se separan las propiedades mas importantes de un objeto, de las que no
lo son. Es decir, por medio de la abstraccion se definen las caractersticas esenciales de un objeto del mundo real,
los atributos y comportamientos que lo definen como tal, para despues modelarlo en un objeto de software.
En el proceso de abstraccion no debe preocupar la implementacion de cada metodo o atributo, solamente se debe
definir en forma general. Por ejemplo, se puede suponer que se desea escribir un programa para representar el
sistema solar. Por medio de la abstraccion, se puede ver a este sistema como un conjunto de objetos, algunos de
estos objetos son los planetas, que tienen un estado, dado por sus caractersticas fsicas, como: tamano, masa, entre
otras. Estos objetos tendran tambien comportamientos: translacion y rotacion, pueden mencionarse como los mas
evidentes.
Visualizar las entidades que se desean trasladar a programas, en terminos abstractos, resulta de gran utilidad para
36

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION
un diseno o ptimo de software, ya que permite comprender mas facilmente la programacion requerida.
En la tecnologa orientada a objetos la herramienta principal para soportar la abstraccion es la clase. Se puede
definir a una clase como una descripcion generica de un grupo de objetos que comparten caractersticas comunes.
Dichas caractersticas son especificadas en sus atributos y comportamientos.

3.4.2.

Modularidad

Dentro de la programacion orientada a objetos, la modularidad juega un papel importante. Una vez que se ha
representado una situacion del mundo real en un programa, se tiene regularmente como resultado, un conjunto
de objetos de software que constituyen la aplicacion. La modularidad, permite modificar las caractersticas de la
clase que definen a un objeto, de forma independiente de las demas clases en la aplicacion. En otras palabras, si la
aplicacion puede dividirse en modulos separados, normalmente clases, y estos modulos pueden compilarse y modificarse sin afectar a los demas, entonces dicha aplicacion ha sido implementada en un lenguaje de programacion
que soporta la modularidad. La tecnologa orientada a objetos brinda esta propiedad para hacer uso de ella en el
proceso de desarrollo de software.

3.4.3.

Encapsulamiento

Tambien referido como ocultamiento de la informacion, el encapsulamiento es la propiedad de la orientacion


a objetos que permite asegurar que la informacion de un objeto sea desconocida para los demas objetos de la
aplicacion. Es muy frecuente referirse a los objetos de software como cajas negras, lo que se debe principalmente
a que no se necesita, dentro de la programacion orientada a objetos, saber como esta instrumentado un objeto para
que interactue con los demas objetos. Generalmente, una clase se define en dos partes, una interfaz por medio
de la cual los objetos que son instanciados de la misma interactuan con los demas objetos en la aplicacion, y la
implementacion de los miembros de dicha clase (metodos y atributos). Se desea realizar una aplicacion en donde
deben interactuar el objeto Porsche, instancia de la clase Autom
ovil y el objeto Juan P
erez, instancia de la
clase Persona. Ambos objetos pueden ser vistos como cajas negras, las cuales se comunican por medio de una
interfaz. El objeto Porsche no sabe como esta implementado el objeto Juan P
erez y viceversa. Concretamente,
el encapsulamiento permite a un objeto ocultar informacion al mundo exterior, o bien restringir el acceso a la
misma.
Una aplicacion orientada a objetos esta constituda, como se menciono anteriormente, por modulos. Estos modulos
se implementan mediante clases, las cuales representan, generalmente, abstracciones de objetos del mundo real. Es
por medio del encapsulamiento que se pueden definir los atributos y los metodos de una clase, para que los objetos
que se instancian de esta trabajen como unidades independientes de los demas objetos con los que interactuan.
En otras palabras, con el encapsulamiento se gana en modularidad, y ademas se protege a los objetos de ser
manipulados de forma inadecuada por objetos externos.

3.4.4.

Jerarqua

Una vez que se ha definido una clase, por ejemplo la clase Persona, con sus atributos y metodos, tal vez se
necesite definir una nueva clase especfica para los Futbolistas. Obviamente, esta nueva clase compartira elementos en comun con la clase Persona, es decir, la clase F
utbolista sera un subconjunto de la clase Persona.
La tecnologa orientada a objetos permite definir jerarquas entre clases y jerarquas entre objetos. Las dos jerarquas mas importantes que existen, son la jerarqua es un que precisa la generalizacion y especializacion entre
clases, y la jerarqua es parte de en la que se delimita la agregacion de objetos.
Comunmente, a la jerarqua es un se le conoce como herencia . La herencia simple es la propiedad que permite
definir una clase nueva en terminos de una clase ya existente. Regresando al ejemplo, si se puede decir que un
F
utbolista es una Persona, entonces se puede definir a la clase F
utbolista a partir de la clase Persona.
Existiran casos en los cuales se necesite definir una clase a partir de dos o mas clases preexistentes, en este caso
se hablara de herencia multiple . Por ejemplo, un Gato es un Mam
fero y a la vez es un Felino. Java no permite
herencia multiple, pero provee interfaces que pueden ser usadas para emularla.
Utilizando herencia, se puede crear una clase general que defina los rasgos comunes de un conjunto de terminos
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

37

3.4. CARACTERISTICAS DE LA TECNOLOGIA ORIENTADA A OBJETOS


relacionados. Esta clase, puede entonces ser heredada por otras clases mas especficas, anadiendo cada una solo
aquellos atributos o metodos que sean particulares a ellas, pero conservando las propiedades generales determinadas por la clase general de la que se hereda. En Java, la clase de la que se hereda, se denomina superclase y la clase
heredera subclase y esta herencia se transmite a traves de la palabra reservada extends . Tambien se dice que una
subclase es una version especializada de su superclase. Esta hereda todas las variables y metodos definidos por su
superclase. Luego, agregara sus propios miembros y/o podra redefinir las variables y metodos heredados.
Todas las clases de Java creadas por el programador tienen una superclase. Cuando no se indica explcitamente
una superclase con la palabra extends , la clase deriva de Object, que es la clase raz de toda la jerarqua de
clases de Java. Como consecuencia, todas las clases tienen algunos metodos que han heredado de Object .
Ejemplo basico de herencia, usando la clase Persona definida anteriormente:
public class EjemploHerencia {
public static void main(String[] args) {
F
utbolista JuanPerez = new F
utbolista();
JuanPerez.edad= new Integer(35);
JuanPerez.sexo= "Masculino";
JuanPerez.nombre= "Juan P
erez";
JuanPerez.equipo= "ABC";
JuanPerez.posicion= new Integer(12);
JuanPerez.jugar();
JuanPerez.imprimir();
}
}
class F
utbolista extends Persona {
String equipo;
Integer posicion;
void jugar() {
estado= "Jugando";
}
}
En cuanto a la jerarqua de agregacion, tambien conocida como inclusion, se puede decir que se trata del agrupamiento logico de objetos relacionados entre s dentro de una clase. Suponga que se quiere definir la clase
Autom
ovil, pero ademas se ha definido ya la clase Volante. Si se puede expresar la oracion, un Volante es
parte de un Autom
ovil, entonces se puede instanciar un objeto de la clase Volante, para definir a la clase
Autom
ovil. En este caso, se dice que Autom
ovil es una agregacion y Volante es un agregado de Autom
ovil.
public class EjemploAgregacion {
public static void main(String[] args) {
Autom
ovil Porsche = new Autom
ovil();
Porsche.color= "Rojo";
Porsche.miVolante= new Volante();
Porsche.miVolante.color= "Negro";
Porsche.miVolante.diametro= new Double(30);
Porsche.virar();
}
}
class Autom
ovil {
String color;
38

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION
Volante miVolante;
void virar() {
miVolante.virar();
}
}
class Volante {
String color;
Double diametro;
void virar() {
System.out.println("Virando volante de color "+ color)
System.out.println("y di
ametro de "+ diametro+ "cm.");
}
}

3.4.5.

Polimorfismo

Muchas veces es necesario que un mismo comportamiento o accion se realice de diferentes maneras, por
ejemplo, suponga que se desea implementar a la clase Mam
fero, suponga tambien que uno de los metodos que
se desea implementar para esta clase, es el que permita a tales mamferos desplazarse de forma natural. Entonces
se tendra que para algunos mamferos el desplazamiento se realizara por medio de caminar, como es el caso de
las personas, para otros el desplazamiento natural sera nadar, como el caso de los delfines mientras que para otros,
el desplazamiento se logra por medio de volar, como sucede con los murcielagos. En otras palabras, un mismo
comportamiento, en este caso el desplazamiento, puede tomar diferentes formas.
Dentro de la programacion orientada a objetos puede modelarse esta situacion del mundo real, en objetos de
software, gracias al polimorfismo. El polimorfismo es la propiedad por la cual una entidad puede tomar diferentes
formas. Generalmente, esta entidad es una clase, y la forma en que se consigue que tome diferentes formas es por
medio de nombrar a los metodos de dicha clase con un mismo nombre pero con diferentes implementaciones. En
Java, esto se logra a traves de la:
Sobrecarga de Metodos
Esto permite definir dos o mas metodos dentro de la misma clase con el mismo nombre, siempre que la declaracion de sus parametros sea diferente. En este caso, se dice que el metodo esta sobrecargado y el proceso de
definir un metodo as, se conoce como sobrecarga del metodo. La sobrecarga de metodos es una de las maneras en
que Java implementa el polimorfismo.
Cuando se llama a un metodo sobrecargado, el compilador actua justo sobre la version cuyo tipo de parametros
coincida con los de la llamada. As, se podra definir la siguiente clase Desplazamiento que permitira desplazarse a distintos objetos:
class Desplazamiento {
void desplazar(Ave A) {
System.out.println("Las aves vuelan");
}
void desplazar(Persona P) {
System.out.println("Las personas caminan");
}
...
}
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

39

3.5. CLASES
NOTA: No se debe confundir la sobrecarga de los metodos con la redefinicion de estos. En el primer caso, sobrecargar un metodo consiste en definir dos o mas metodos dentro de la misma clase con el mismo nombre, mientras
que redefinir (override ) un metodo, es darle una nueva definicion. En este caso el metodo debe tener exactamente
los mismos argumentos en tipo y numero que el metodo redefinido y solo puede ocurrir en el caso de una clase
heredada.
No existe una regla exacta para saber si un metodo se debe sobrecargar o no. Realmente, la idea es aprovechar
las ventajas que ofrece esta forma de polimorfismo, as que lo normal es sobrecargar aquellos metodos que esten
intrnsecamente relacionados, como es el caso del ejemplo anterior, pero no se debe confundir. Por ejemplo, el
metodo sqrt(), aunque se llama igual, calcula de forma totalmente diferente la raz cuadrada de un numero entero que la de uno en punto flotante. Aqu, aunque se aplique sobrecarga al metodo, realmente no se respetara el
proposito para el que se creo el polimorfismo.

3.4.6.

Caractersticas Adicionales de los Lenguajes Orientados a Objetos

Ademas de las caractersticas que se mencionaron anteriormente como esenciales de los lenguajes de programacion orientados a objetos, es deseable que estos cumplan tambien con las siguientes:
Tipificacion Fuerte: Esto es, que durante la fase de diseno e implementacion, se declare que tipo de datos
soportara cada variable.
Manejo de Excepciones: Dentro de la misma definicion del lenguaje se debera establecer la forma de
detectar y manipular excepciones(errores) que puedan surgir durante la ejecucion de un programa.
Generalidad: Se refiere principalmente a que las clases se definan lo mas generalizadas posible, para que
sean facilmente reusables. Para generar este tipo de clases, normalmente se definen parametros formales,
que son instanciados por parametros reales.
Multitarea: Es conveniente que el lenguaje permita la creacion de procesos que se ejecuten de forma simultanea independientemente del sistema operativo.
Persistencia: Los objetos deben poder permanecer, si as se desea, despues de la ejecucion de un programa.
Datos Compartidos: Los objetos pueden necesitar referirse a la misma localidad de memoria (memoria
compartida) o bien comunicarse mediante mensajes.

3.5.

Clases

Clase: Es un molde o bien prototipo en donde se definen los atributos (variables) y las acciones (metodos)
comunes de una entidad.
Este es el paradigma que propone la programacion orientada a objetos, la abstraccion de los elementos que constituyen a un objeto del mundo fsico, esto es, atributos y comportamiento, y la representacion de estos elementos por
medio de objetos de software, formados por variables y metodos, que permitan la manipulacion de tales variables.
Cabe mencionar, que ademas de representar los objetos fsicos del mundo real por medio de objetos, tambien se
pueden modelar objetos abstractos, por ejemplo las acciones de un usuario al interactuar con la maquina.
Se puede definir a una clase como una descripcion generica de un grupo de objetos que comparten caractersticas comunes. Dichas caractersticas son especificadas en sus atributos y comportamientos. En otras palabras, una
clase es un molde o modelo en donde se especifican las caractersticas que definen a un objeto de manera general.
A partir de una clase se pueden definir objetos particulares. En programacion orientada a objetos, se dice que un
objeto es una instancia de la clase, es decir, un objeto es un caso particular del conjunto de objetos que comparten
caractersticas similares, definidas en la clase.
Como ejemplo se define la clase Persona, esta clase tendra ciertos atributos, por ejemplo edad, sexo y nombre
40

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION
entre otros. Las acciones o comportamientos que se pueden definir para esta clase son, por ejemplo, respirar, caminar, comer, etcetera. Estas son, en este caso, las caractersticas que definen a la clase Persona. Un objeto instanciado de esta clase podra ser Juan Perez, de sexo masculino y de 35 anos de edad, quien se encuentra caminando.
Estos atributos son conocidos formalmente en programacion orientada a objetos como variables de instancia por
que contienen el estado de un objeto particular en un momento dado, en este caso Juan Perez. As mismo, los
comportamientos son llamados metodos de instancia, porque muestran el comportamiento de un objeto particular
de la clase.
Esto se podra escribir en Java como:
public class EjemploClase {
public static void main(String[] args) {
Persona JuanPerez = new Persona();
JuanPerez.edad= new Integer(35);
JuanPerez.sexo= "Masculino";
JuanPerez.nombre= "Juan P
erez";
JuanPerez.caminar();
JuanPerez.imprimir();
}
}
class Persona {
Integer edad;
String sexo; // Masculino o Femenino
String nombre;
String estado;
void comer() {
estado= "Comiendo";
}
void caminar() {
estado= "Caminando";
}
void imprimir() {
System.out.println("Este es "+nombre+ "una persona de sexo "+ sexo+ ",");
System.out.println("de "+ edad+ "a
nos y que ahora est
a "+ estado);
}
}
Hay que tener cuidado de no confundir un objeto con una clase, una gelatina de frutilla y una gelatina de limon
son objetos de la misma clase (o del mismo molde), pero con atributos (o sabores) diferentes.

3.5.1.

Atributos

Son los datos y variables, que al definirse dentro de la clase se llaman variables instancia de la clase. Se llaman
as porque cada instancia de la clase, es decir, cada objeto particular que se cree, contiene su propia copia de estas
variables (generalmente).

3.5.2.

Metodos

Son las funciones de la clase que actuan sobre las variables de la instancia de ella y definen su comportamiento.
Otra de las ventajas de Java es la flexibilidad y potencia que les proporciona.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

41

3.5. CLASES
La expresion general de la declaracion de un metodo es la siguiente:
acceso tipo nombreMetodo(par
ametros) {
//cuerpo del m
etodo
}
donde acceso indica el tipo de proteccion asignado a este metodo (public , protected o private ), tipo es
el valor que devuelve el metodo, puede ser un tipo primitivo o un tipo de clase o void en caso de que no devuelva
ninguno. Los parametros, cuando los hay, se especifican por la pareja tipo - identificador. Esta lnea es lo
que se conoce como el header , signatura o firma del metodo. Java no soporta parametros opcionales .
Salvo los metodos estaticos(ver seccion 3.7.1) o de clase, se aplican siempre a un objeto de la clase por medio del
operador punto. Dicho objeto es su argumento implcito. Los metodos tienen visibilidad directa de las variables
miembro del objeto que es su argumento implcito, es decir, pueden acceder a ellas sin cualificarlas con un nombre
de objeto y el operador punto .
El valor de retorno puede ser un valor de un tipo primitivo o una referencia. En cualquier caso, no puede haber mas
que un u nico valor de retorno (que puede ser un objeto o un arreglo). Se puede devolver tambien una referencia a
un objeto por medio de un nombre de interfaz. El objeto devuelto debe pertenecer a una clase que implemente esa
interfaz. Se puede devolver como valor de retorno un objeto de la misma clase que el metodo o de una subclase,
pero nunca de una superclase.
Los metodos pueden definir variables locales. Su visibilidad llega desde la definicion hasta el final del bloque
en el que han sido definidas. No hace falta inicializarlas en el punto que se definen, sin embargo, el compilador
no permite utilizarlas sin haberlas inicializado. A diferencia de las variables miembro, las variables locales no se
inicializan por defecto.
Si en el header del metodo se incluye la palabra native no hay que incluir el codigo o implementacion del metodo. Este codigo debera estar en una librera dinamica (DLL). Estas libreras son archivos de funciones compiladas
normalmente en lenguajes distintos a Java. Esta es la forma de poder utilizar conjuntamente funciones realizadas
en otros lenguajes desde codigo escrito en Java.
Paso de Parametros a Metodos
En Java los parametros de los tipos primitivos se pasan siempre por valor. El metodo recibe una copia del
parametro actual. Si se modifica esta copia, el parametro original que se incluyo en la llamada no es modificado.
La forma de modificar dentro de un metodo una variable de un tipo primitivo, es incluirla como variable miembro
en una clase y pasar como parametro una referencia a un objeto de dicha clase. Las referencias se pasan tambien
por valor, pero a traves de ellas se pueden modificar los objetos referenciados.
En Java no se pueden pasar metodos como parametros a otros metodos (en C/C++ se pueden pasar punteros a
funcion como parametros). Lo que se puede hacer en Java es pasar una referencia a un objeto y dentro de la
funcion utilizar los metodos de ese objeto.
Si un metodo devuelve this (ver seccion 3.6.2), es decir, un objeto de la clase, o una referencia a otro objeto, ese
objeto puede concatenarse con otra llamada a otro metodo de la misma o de diferente clase y as sucesivamente.
En este caso apareceran varios metodos en la misma sentencia unidos por el operador punto (.). Por ejemplo, la
siguiente sentencia:
String s = "Curso Java ".trim().substring(1,4);
es correcta porque trim() devuelve String y substring() tambien. As, se evita escribir:
String s1 = "Curso Java ";
String s2 = s1.trim();
String s = s2.substring(1,4);
La secuencia de ejecucion, cuando se concatenan varias llamadas a metodos, es de izquierda a derecha.
42

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION
El Operador return
Ya se comento anteriormente que la llamada a un metodo podra acabar con la devolucion de un valor por parte
de esta. Este valor puede ser de un tipo primitivo, o una referencia a un objeto. En cualquier caso, de la devolucion
de este valor se encarga el operador return. Ejemplo:
return retValue;

3.5.3.

Constructores

Un punto clave de la Programacion Orientada a Objetos(POO) es el evitar informacion incorrecta por no


haber sido correctamente inicializadas las variables. Java no permite que haya variables miembro que no esten
inicializadas. Asimismo, si se crean varias instancias de la misma clase, puede acabar resultando muy pesado el
tener que inicializar todas las variables miembro para cada instancia. Por todo ello, Java ofrece el uso de un metodo
especial llamado el constructor de la clase.
Un constructor es un metodo que se llama automaticamente, cada vez que se crea un objeto de una clase y su
principal mision es la de reservar espacio de memoria al objeto y la de inicializar todas las variables miembro.
Aunque se ha dicho que el constructor es como un metodo, este tiene caractersticas especficas como que se tiene
que llamar igual que la clase y que no devuelve ningun valor (ni siquiera void ). Esto se debe a que el tipo que
devuelve el constructor es su argumento implcito, es decir, la clase en s misma. Pero, s se le puede dotar de un
parametro de restriccion, aunque si se declara como private ninguna otra clase podra crear una instancia de
esta clase.
Un constructor puede llamar a otro constructor previamente definido en la misma clase, por medio de la palabra
this . En este contexto, la palabra this solo puede aparecer en la primera sentencia de un constructor.
El constructor de una subclase puede llamar al constructor de su superclase por medio de la palabra super ,
seguida de los parametros apropiados entre parentesis. De esta forma, un constructor solo tiene que inicializar por
s mismo las variables no heredadas.
Sobrecarga de Constructores
Es aqu donde realmente se aprecian los beneficios del polimorfismo. El constructor de una clase es el que
inicializa los valores que el programador crea conveniente cuando esta se instancia. Pues bien, sobrecargando el
constructor, se consigue dotar a la clase de flexibilidad. Por ejemplo, como mnimo, se debera tener en cuenta que
podra no pasarsele parametros al constructor, cuando este lo espera, debido a un fallo en alguna otra parte de la
aplicacion (se refiere a cualquier otra clase que llame a esta). Es por ello que siempre es recomendable definir al
menos dos constructores: el especfico de la aplicacion que se este disenando y el estandar. El siguiente ejemplo
lo dejara mucho mas claro:
class Box{
double width;
double height;
double depth;
// El siguiente es el constructor espec
fico
Box(double w, double h, double d) {
width= w; height= h; depth= d;
}
// pero podr
a ser que no le llegaran par
ametros
// por fallar la otra clase (m
etodo) que lo invoque
Box() {
width= height= depth= -1; //-1 indica volumen no existente
}
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

43

3.5. CLASES

// e incluso se puede pensar que se quiere construir un cubo,


// entonces, por qu
e introducir 3 valores? ;)
Box(double valor) {
width= height= depth= valor;
}
double volume() {
return width* height* depth;
}
}
Como se ve, de cara a flexibilizar una clase es fundamental el polimorfismo a la hora de implementar los constructores.

3.5.4.

Destructores

Aunque los objetos son dinamicamente asignados mediante el operador new (ver seccion 3.6.1), en Java no
hay destructores especficos como en C++. El sistema se ocupa automaticamente de liberar la memoria de los
objetos que ya han perdido la referencia, esto es, objetos que ya no tienen ningun nombre que permita acceder
a ellos, por ejemplo, por haber llegado al final del bloque en el que haban sido definidos, porque a la referencia
se le ha asignado el valor null o porque a la referencia se le ha asignado la direccion de otro objeto. A esta
caracterstica de Java se le llama garbage collection (recoleccion de basura).
En Java, es normal que varias variables de tipo referencia apunten al mismo objeto. Java lleva internamente un
contador de cuantas referencias hay sobre cada objeto. El objeto podra ser borrado cuando el numero de referencias
sea cero.
Nunca se sabe cuando se activara el recolector de basura (depende mucho de la implementacion del sistema de
ejecucion de Java) pero mientras no falte memoria, es muy probable que nunca se active. Si se quiere llamar
explcitamente al garbage collector, se puede usar el metodo System.gc(), aunque esto solo es tomado por la
JVM como una sugerencia.

El Metodo finalize()
Algunas veces un objeto necesitara realizar algunas acciones antes de que sea destruido y que no sean las
propias de liberalizacion de memoria, sino de liberar recursos como el manejador de un archivo, una conexion
de red o memoria reservada para funciones nativas. Hay que tener en cuenta, que el recolector de basura solo
libera la memoria reservada con new . Si por ejemplo, se ha reservado memoria con funciones nativas en C (por
ejemplo, utilizando la funcion malloc()), esta memoria hay que liberarla explcitamente utilizando el metodo
finalize().
Un finalizador es un metodo, sin valor de retorno (void ), ni argumentos y que siempre se llama finalize().
Los finalizadores se llaman de modo automatico siempre que hayan sido definidos por el programador de la clase.
Para realizar su tarea correctamente, un finalizador debera terminar siempre llamando al finalizador de su superclase.
Es importante saber, que lo u nico seguro, es que el metodo finalize() se llama justo antes del recolector de
basura pero no hay manera de saber cuando, o incluso si es llamado, por lo que lo mas conveniente es que el
programador realice de manera explcita la liberacion de recursos crticos mediante otros metodos que el mismo
llame.
El metodo System.runFinalization() sugiere a la JVM, que ejecute los finalizadores de los objetos pendientes, los que han perdido su referencia.
44

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION

3.6.

Objetos

Objeto: Unidad de software conformada por atributos y metodos especficos.


El objeto, es el concepto principal sobre el cual se fundamenta la tecnologa orientada a objetos. Un objeto puede
ser visto como una entidad que posee atributos y efectua acciones. En el mundo real, podemos encontrar cientos
de ejemplos que cumplen con esta definicion, algunos de ellos son: una bicicleta, un automovil, una persona, una
computadora, etcetera.
Estos objetos son casos particulares de entidades llamadas clases, en donde se definen las caractersticas comunes
de tales objetos. Un caso particular es el ejemplo del objeto automovil, se pueden mencionar como atributos de
este: el modelo, el color, la marca, el numero de placas, entre otros. Algunas acciones que es capaz de realizar un
automovil son: ir en reversa, virar, frenar, acelerar y cambiar la velocidad. Este objeto automovil, es una instancia
particular de la entidad automovil. En terminos de la programacion orientada a objetos, se dice que todo objeto
tiene un estado (atributos) y un comportamiento (acciones). La programacion orientada a objetos permite modelar
estos objetos del mundo real en objetos de software de forma eficaz. Un objeto de software mantiene sus atributos
o estado en variables e implementa las acciones o comportamientos por medio de metodos o funciones. Suponga
que se quiere desarrollar una aplicacion que simule un vehculo. Se tendra entonces un objeto vehculo consttuido
por variables en las cuales se podra almacenar numero de serie, color, velocidad actual, etcetera. Junto a esto, se
tendra un conjunto de funciones que implementaran las acciones para frenar, virar, cambiar la velocidad, etcetera.

3.6.1.

Operador new

Para obtener una instancia o ejemplar de la clase se siguen dos pasos:


Se declara una variable del tipo de la clase. Esta sera la que posea la referencia del objeto, pero en este
punto, el valor de la variable es null y cualquier intento de acceder a ella producira un error. Por ejemplo,
String Doce;
Doce = String.valueOf(12);
Obtener una copia fsica, real de la clase, es decir, crear el objeto. Para ello, se emplea el operador new .
Dicho operador asigna memoria de manera dinamica, esto es, en tiempo de ejecucion, al objeto y devuelve
una referencia de e l, que se guardara en la variable que se crea en el paso anterior. Por ejemplo,
String Doce = new String("12");
El espacio de memoria que se reserva, se calcula a partir de la descripcion de la clase y luego se llama al constructor
de esta o a un constructor por defecto de Java si la clase carece de e l.

3.6.2.

Objeto this

Normalmente, dentro del cuerpo de un metodo de un objeto, se puede acceder directamente a las variables
miembros del objeto. Sin embargo, algunas veces no se querra tener ambiguedad sobre el nombre de la variable
miembro y uno de los argumentos del metodo que tengan el mismo nombre.
Por ejemplo, el siguiente constructor de la clase HSBColor inicializa alguna variable miembro de un objeto de
acuerdo a los argumentos pasados al constructor. Cada argumento del constructor tiene el mismo nombre que la
variable del objeto cuyo valor contiene el argumento.
class HSBColor {
int luminosidad;
int saturacion;
int brillo;
HSBColor (int luminosidad, int saturacion, int brillo) {
this .luminosidad= luminosidad;
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

45

3.6. OBJETOS
this .saturacion= saturacion;
this .brillo= brillo;
}
}
Se debe utilizar this en este constructor para evitar la ambiguedad entre el argumento luminosidad y la variable
miembro luminosidad (y as con el resto de los argumentos). Escribir luminosidad = luminosidad; no tendra
sentido. Los nombres de argumentos tienen mayor precedencia y ocultan a los nombres de las variables miembro
con el mismo nombre. Para referirse a la variable miembro, se debe hacer explcitamente a traves del objeto actual
this .
Tambien se puede utilizar this para llamar a uno de los metodos del objeto actual. Esto solo es necesario si
existe alguna ambiguedad con el nombre del metodo y se utiliza para intentar hacer el codigo mas claro.
El objeto this , tambien puede ser usado como valor de retorno de un metodo para, por ejemplo, permitir la
concatenacion de llamadas a metodos. Ejemplo:
class A {
A hacer() {
...
return this ;
}
}
this se utiliza tambien para llamar a un constructor desde otro (ver seccion 3.5.3).

3.6.3.

Objeto super

Hay veces que se quiere crear una superclase que mantenga el detalle de su implementacion para ella sola,
es decir, se quiere que sus datos miembros sean privados. En este caso, no habra manera de que una subclase
accediera o inicializara directamente estas variables por su cuenta. Puesto que la encapsulacion es un atributo
primordial de la POO, Java ha tenido en cuenta una manera de proporcionar una solucion a este problema.
Cuando quiera que sea que una clase necesite referirse a su superclase inmediata, lo podra hacer mediante el
empleo de super .
super , en este contexto, se puede emplear de dos formas:
Llamar al constructor de su superclase.
class B extends A {
B() {
super (); // llama al constructor de A
}
}
Acceder a un miembro de la superclase que haya sido escondido por un miembro de una subclase.
class A {
int a;
}
class B extends A {
int a;
void ejecutar() {
a= 2; // Modifica el atributo a propio
super .a= 3; // Modifica el atributo a del padre
}
}
46

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION
Llamada al Constructor de su Superclase
Ya se comento que un constructor de una clase puede llamar por medio de la palabra this a otro constructor
previamente definido en la misma clase. En este contexto, la palabra this solo puede aparecer en la primera
sentencia de un constructor. Como ejemplo de esto, se cita el ejemplo de la sobrecarga de constructores de la
seccion 3.5.3, en donde el constructor sin parametros se podra reemplazar por una llamada al constructor de un
parametro, como sigue:
Box() {
this (-1); // llama al constructor de un par
ametro.
}
De forma analoga, el constructor de una clase derivada puede llamar al constructor de su superclase por medio de
super(). Entre parentesis van los argumentos apropiados para uno de los constructores de la superclase. De esta
forma, un constructor solo tiene que inicializar directamente las variables no heredadas.
La llamada al constructor de la superclase debe ser la primera sentencia del constructor, excepto si se llama a otro
constructor de la misma clase con this(). Si el programador no la incluye, Java incluye automaticamentre una
llamada al constructor por defecto de la superclase, super(). Esta llamada en cadena a los constructores de las
superclases llega hasta el origen de la jerarqua de clases, esto es, al constructor de Object.
Acceso a los Miembros de su Superclase
En este caso, super actua algo as como this , excepto que siempre se refiere a la superclase de la subclase
en la que se usa. En este caso, su empleo se justifica para solucionar el problema de que la clase derivada pise
un miembro (variable o metodo) de su superclase por llamarlo de la misma manera. Por ejemplo:
class Madre {
int i;
}
class Hija extends Madre {
int i; //esta variable esconde la de su superclase
Hija(int a, int b) {
super .i= a; //es la variable de la clase Madre
i= b; //variable de Hija
}
void show() {
imprimir("i en Madre: "+ super .i);
imprimir("i en Hija: "+ i);
}
}
class UsoDeSuper {
public static void main(String args[]) {
Hija subOb = new Hija(1,2);
subOb.show(); //muestra: i en Madre: 1
//i en Hija: 2
}
}
Ejemplo del uso de super ():
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

47


3.7. MODIFICADORES DE ATRIBUTOS Y METODOS
class Madre {
int i,j;
Madre(int a, int b) {
i=a;
j=b;
}
void show() {
imprimir("i y j: "+ i+
}

+ j);

}
class Hija extends Madre {
int k;
Hija(int a, int b, int c) {
super (a,b);
k=c;
}
void show() {
// llamada al m
etodo show() de Madre
// esto es la manera de diferenciar
// entre un m
etodo de una superclase
// y uno redefinido por su hija
super .show(); //i y j: 1 2
imprimir("k: "+ k); //k: 3
}
}
class Redefine {
public static void main(String args[]) {
Hija subOb = new Hija(1,2,3);
subOb.show();//redefine show() de Madre
}
}
Por u ltimo, para concluir este tema, queda aclarar cuando se llaman los construtores si se tiene una jerarqua de
clases derivadas.
La respuesta, es que los constructores se llaman en orden de derivacion, desde la superclase hacia la subclase.

3.7.

Modificadores de Atributos y Metodos

3.7.1.

El Modificador static

Hay veces que se desea definir un miembro de una clase para ser usado independientemente de cualquier objeto
de esa clase. Normalmente, a un miembro de una clase se accede solo si se ha instanciado un objeto de dicha clase.
No obstante, es posible crear un miembro que pueda ser usado por s mismo, sin necesidad de referenciar a una
instancia especfica. Para crear tales tipos de miembros se emplea el modificador static .
Cuando un miembro se declara con esta palabra reservada, se puede acceder a e l antes de que cualquier objeto de
su clase sea creado, y sin referenciar a ningun objeto. Se pueden declarar estaticos tanto metodos como variables.
48

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION
El ejemplo mas claro de un miembro estatico es el main(). Se declara de esta manera porque se debe llamar antes
de que cualquier objeto sea declarado.
Atributos Estaticos
Los atributos de instancia declarados como estaticos (tambien llamados de clase ) son, esencialmente, variables globales. Cuando se crean objetos especficos de esa clase no se hace ninguna copia de los atributos estaticos.
Lo que ocurre, es que todas las instancias de esa clase comparten el mismo atributo. Estos atributos tienen sentido,
principalmente, cuando varias instancias de la misma clase necesitan llevar el control o estado del valor de un dato.
Tambien se podra utilizar para definir constantes.
Para llamar a este tipo de atributos se suele utilizar el nombre de la clase (no es imprescindible, pues se puede
utilizar tambien el nombre de cualquier objeto de esa clase), porque de esta forma queda mas claro, seguida de un
. y el atributo. Por ejemplo:
class Constantes {
static double PI = 3.14156;
}
class UsoStatic {
public static void main(String args[]) {
System.out.println("Pi := "+ Constantes.PI);
}
}
Los atributos miembro estaticos se crean en el momento en que pueden ser necesarios: cuando se va a crear el
primer objeto de la clase, en cuanto se llama a un metodo estatico o en cuanto se utiliza un atributo estatico de
dicha clase. Lo importante es que las atributos miembro estaticos se inicializan siempre antes que cualquier objeto
de la clase.
Metodos Estaticos
Tambien llamados de clase , pueden recibir objetos de su clase como argumentos explcitos, pero no tienen
argumento implcito ni pueden utilizar la referencia this . Para llamar a estos metodos se suele emplear el nombre
de la clase, en vez del nombre de un objeto de la clase. Los metodos y variables de clase son lo mas parecido que
Java tiene a las funciones y variables globales de C/C++.
Las restricciones que tiene un metodo estatico son:
1. Solo pueden llamar otro metodo estatico
2. Solo deben acceder a datos estatico
3. No se pueden referir a this o super de ninguna manera
Si se necesita hacer algun tipo de computacion para inicializar los atributos estaticos, se puede declarar tambien
un bloque estatico, el cual se ejecutara solo una vez, cuando se carga.
class Estatica {
static int a= 3;
static int b;
static void show(int x) {
System.out.println("x = "+ x);
System.out.println("a = "+ a);
System.out.println("b = "+ b);
}
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

49


3.7. MODIFICADORES DE ATRIBUTOS Y METODOS

static {
System.out.println("Bloque est
atico inicializado");
b= a* 4; //se ve que, aunque declarada como static
//b se inicializa en tiempo de ejecuci
on
}
public static void main(String args[]) {
show(15);
}
}
Tan pronto como Estatica se carga, todas las sentencias del bloque estatico se ejecutan. Primero, a se inicializa
a 3, luego se ejecuta el bloque estatico y, por u ltimo, b se inicializa al valor asignado.

3.7.2.

El Modificador final

Un atributo que se declara como final , previene que su contenido sea modificado. Esto significa, que se debe
inicializar un atributo final cuando se declara. No obstante, Java permite separar la definicion de la inicializacion.
Esta u ltima, se puede hacer mas tarde, en tiempo de ejecucion, llamando a metodos o en funcion de otros datos.
El atributo final as definido es constante, pero no tiene porque tener el mismo valor en todas las ejecuciones
del programa, pues depende de como haya sido inicializado. Esto es lo mas parecido a las constantes de otros
lenguajes de programacion. Por ejemplo:
final float PI = 3.14156;
Aunque basicamente este operador se emplea para crear constantes en Java, tambien se puede definir una clase
o un metodo como final . En el primer caso, una clase final no puede tener clases derivadas. Esto se hace
por motivos de seguridad y de eficiencia, porque cuando el compilador sabe que los metodos no van a ser redefinidos puede hacer optimizaciones adicionales. En el segundo, un metodo declarado como final , no puede ser
redefinido por una clase que derive de su propia clase.

3.7.3.

El Modificador abstract

Es posible que con la herencia se cree una familia de clases con una interfaz comun. En esos casos, es posible,
y hasta probable, que la clase raz de las demas no sea una clase u til, y que hasta se desee que el usuario nunca
haga instancias de ella, porque su utilidad es inexistente. No se quieren implementar sus metodos, solo declararlos,
para crear una interfaz comun. Entonces, se declaran sus metodos como abstractos:
public abstract void mi metodo();
Como se ve, se declara el metodo pero no se implementa, ya que se sustituye el codigo que debera ir entre llaves
por un punto y coma. Cuando existe un metodo abstracto se debe declarar la clase abstracta, o el compilador
dara un error. Al declarar como abstracta una clase se asegura que el usuario no pueda crear instancias de ella:
abstract class Mam
fero {
String especie, color;
public abstract void mover();
}
class Gato extends Mam
fero {
int numero patas;
public void mover() {
System.out.println("El gato es el que se mueve");
50

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION
}
}
public class Abstractos {
public static void main(String[] args) {
Gato bisho = new Gato();
bisho.mover();
}
}
En este ejemplo de herencia, parece absurdo pensar que se vaya a crear instancias de Mam
fero, sino de alguna
de sus clases derivadas. Por eso, se decidio declararlo abstracto.

3.7.4.

El Modificador transient

Por defecto, las variables miembro son una parte persistente del estado de un objeto. Las variables que forman
parte persistente del estado del objeto deben guardarse cuando el objeto es serializado (ver seccion 4.5.5). Se puede
utilizar la palabra clave transient para indicar a la JVM que la variable indicada no es una parte persistente del
objeto.
Al igual que otros modificadors de variables en el sistema Java, se puede utilizar transient en una clase o
declaracion de variable de ejemplar como esta.
class TransientExample {
transient int var;
...
}
Este ejemplo declara una variable entera llamada var que no es una parte persistente del estado de la clase
TransientExample.

3.7.5.

El Modificador volatile

Si una clase contiene una variable miembro que es modificada de forma asncrona, mediante la ejecucion de
hilos concurrentes, se puede utilizar la palabra clave volatile de Java para notificar esto al sistema Java.
La siguiente declaracion de variable es un ejemplo de como declarar que una variable va a ser modificada de forma
asncrona por hilos concurrentes.
class VolatileExample {
volatile int contador;
. . .
}

3.8.

Clases Internas

Una clase interna, es una clase definida dentro de otra clase, conocida como clase contenedora, en alguna
variante de la siguiente forma general:
class ClaseContenedora {
...
class ClaseInterna {
...
}
...
}
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

51

3.8. CLASES INTERNAS


El alcance de una clase interna esta limitado por el alcance de la clase que la contiene. As, si una clase B esta englobada dentro de una clase A, entonces B es vista por A, pero no fuera de esta u ltima. Una clase interna tiene
acceso a los miembros (atributos o metodos), incluyendo los privados, de la clase que la contiene. No obstante, la
clase contenedora no tiene acceso a los miembros de la clase interna. Por ejemplo:
public class Contenedora {
private int a= 2;
public Contenedora() {
System.out.println("a dentro de Contenedora vale: "+ a);
Inner inner = new Inner();
}
class Inner {
public Inner() {
a= a*a;
System.out.println("a en inner class: "+ a);
}
}
public static void main(String args[]) {
Contenedora cont = new Contenedora();
}
}
Ademas de su utilidad en s, las clases internas se utilizan mucho en el modelo de eventos introducido en la version
de Java 1.1 y que se vera en la seccion 6.3.
Hay que senalar que, la maquina virtual de java no sabe de la existencia de clases internas. Por ello, el compilador
convierte estas clases en clases globales, contenidas en archivos .class cuyo nombre es del estilo
ClaseContenedora$ClaseInterna.class. Esta conversion inserta variables ocultas, metodos y argumentos
en los constructores.
Hay cuatro tipos de clases internas:
Clases internas estaticas
Clases internas miembro
Clases internas locales
Clases anonimas

3.8.1.

Clases Internas Estaticas

Se conocen tambien con el nombre de clases anidadas (nested classes). Las clases internas estaticas solo
pueden ser creadas dentro de otra clase al maximo nivel, es decir, directamente en el bloque de definicion de la
clase contenedora y no en un bloque mas interno. Este tipo de clases internas, se definen utilizando la palabra
static .
Debido a su caracter estatico, estas clases no pueden acceder a los miembros de su clase contenedora directamente
sino a traves de un objeto. En cierta forma, las clases internas estaticas se comportan como clases normales. Para
utilizar su nombre desde fuera de la clase contenedora, hay que precederlo por el nombre de la clase contenedora
y el operador punto (.). Este tipo de relacion entre clases, se puede utilizar para agrupar varias clases dentro de
una clase mas general.
Las clases internas estaticas pueden ver y utlizar los miembros estaticos de la clase contenedora. No se necesitan
objetos de la clase contenedora para crear objetos de la clase interna estatica. Los metodos de la clase interna
52

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION
estatica, no pueden acceder directamente a los objetos de la clase contenedora. En caso de que los haya, deben
disponer de una referencia a dichos objetos, como cualquier otra clase.
El hecho de que las clases contenedoras no puedan acceder directamente a sus clases internas estaticas, hace que
estas u ltimas se empleen rara vez.

3.8.2.

Clases Internas Miembro

Llamadas tambien simplemente clases internas, son clases definidas al maximo nivel de la clase contenedora,
sin la palabra static . Este tipo de clase interna, no puede tener variables miembro estaticas. Tienen una nueva
sintaxis para las palabras reservadas this , new y super , que se vera mas adelante.
La caracterstica principal de estas clases internas, es que cada objeto de la clase interna, existe siempre dentro de
uno y solo un objeto de la clase contenedora. Un objeto de la clase contenedora, puede estar relacionado con uno
o mas objetos de la clase interna. Tener esto presente es muy importante para entender las caractersticas que se
explican a continuacion:
Los metodos de la clase interna ven directamente las variables miembro del objeto de la clase contenedora, sin
necesidad de cualificarlos, cosa que no ocurre al reves. Esto ocurre porque existe una relacion uno a varios que
existe entre los objetos de la clase contenedora y los de la clase interna.
Otras clases diferentes de las clases contenedora e interna, pueden utilizar directamente los objetos de la clase
interna, sin cualificarlos, con el objeto o el nombre de la clase contenedora. De hecho, se puede seguir accediendo
a los objetos de la clase interna aunque se pierda la referencia al objeto de la clase contenedora con el que estan
asociados.
Una clase interna miembro puede contener otra clase interna miembro, hasta el nivel que se desee (aunque no se
considera buena tecnica de programacion utilizar muchos niveles).
En la clase interna, la palabra this , se refiere al objeto de la propia clase interna. Para acceder al objeto de la
clase contenedora se utiliza ClaseContenedora.this .
Para crear un nuevo objeto de la clase interna, se puede utilizar new, precedido por la referencia al objeto de la
clase contenedora que contendra el nuevo objeto: unObjeto.new (). El tipo del objeto es el nombre de la clase
contenedora seguido del nombre de la clase interna, como por ejemplo:
Contenedora.Interna objetoInterna = objetoContenedora.new Interna(...);
Imaginemos ahora que B es una clase interna de A y que C es una clase interna de B. La creacion de objetos de las
tres clases se puede hacer del siguiente modo:
A a = new A(); //se crea un objeto de la clase A
A.B b = a.new B(); //b es un objeto de la clase interna B
//dentro de a
A.B.C c = b.new C(); //c es un objeto de la clase interna C
//dentro de b
Nunca se puede crear un objeto de la clase interna sin una referencia a un objeto de la clase contenedora. Los
constructores de la clase interna tienen, como argumento oculto, una referencia al objeto de la clase contenedora.
El nuevo significado de la palabra super es algo complicado: Si una clase deriva de una clase interna, su constructor no puede llamar a super() directamente. Ello hace que el compilador no pueda crear un constructor por
defecto. Al constructor hay que pasarle una referencia a la clase contenedora de la clase interna superclase, y con
esa referencia llamar a ref.super().
Las clases internas pueden derivar de otras clases diferentes de la clase contenedora. En este caso, conviene tener
en cuenta lo siguiente.
Las clases internas constituyen como una segunda jerarqua de clases en Java: por una parte estan en la clase
contenedora y ven sus variables; por otra parte pueden derivar de otra clase que no tenga nada que ver con la clase
contenedora. Es muy importante evitar conflictos con los nombres. En caso de conflicto entre un nombre heredado y un nombre en la clase contenedora, el nombre heredado tiene prioridad. En caso de conflicto de nombres,
Java obliga a utilizar la referencia this con un nuevo significado: para referirse al atributo o metodo miembro
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

53

3.8. CLASES INTERNAS


heredado se utiliza this .name, mientras que se utiliza ClaseContenedora.this .name para el miembro de
la clase contenedora.
Si una clase contenedora deriva de una super-clase que tiene una clase interna, la clase interna de la subclase puede
a su vez derivar de la clase interna de la super-clase y redefinir todos los metodos que necesite.
Todo esto expuesto aqu, son todas las posibilidades que puede tener el uso de una clase interna, pero como en
todo, esto es solo cultura general.
Como restricciones de estas clases internas miembro se tiene:
No pueden tener el mismo nombre que la clase contenedora.
Tampoco pueden tener miembros estaticos, ni atributos, ni metodos, ni clases.
Ejemplo:
//clase contenedora
class A {
int i=1; //variable miembro
public A(int i) { this .i=i; } //constructor
//los m
etodos de la clase contenedora necesitan una
//referencia a los objetos de la clase interna
public void printA(B objetoB) {
System.out.println("i="+i+", objetoB.j="+objetoB.j);//s

lo acepta
}
//la clase interna puede tener cualquier visibilidad. Con private
//da error porque main() no puede acceder a la clase interna
protected class B {
int j=2;
public B(int j) { this .j=j; } //constructor
public void printB() {
System.out.println("i="+i+ ", j"+ j);
//s sabe que es j
}
}//fin clase B
}//fin clase contenedora A
class ClaseInterna {
public static void main(String args[]) {
A a1 = new A(11);
A a2 = new A(12);
println("a1.i="+a1.i+ ", a2.i="+ a2.i);
//forma de crear objetos de la clase interna
//asociados a un objeto de la clase contenedora
A.B b1 = a1.new B(-10), b2 = a1.new B(-20);
//referencia directa a los objetos b1 y b2 (sin cualificar).
println("b1.j="+b1.j+ ", b2.j="+ b2.j);
//los m
etodos de la clase interna pueden acceder directamente
54

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION
//a las variables miembro del objeto de la clase contenedora
b1.printB(); //escribe: i=11 j=-10
b2.printB(); //escribe: i=11 j=-20
//los m
etodos de la clase contenedora deben recibir referencias
//a los propios objetos de la clase interna, para que puedan
//identificarlos.
a1.printA(b1); a1.printA(b2);
A a3 = new A(13);
A.B b3 = a3.new B(-30);
println("b3.j="+ b3.j);
a3 = null ;
b3.printB(); //escribe: i=13 j=-30
a3 = new A(14); //se crea un nuevo objeto asociado a la
//referencia a3
//b3 sigue asociado al anterior objeto de la clase contenedora
b3.printB(); //escribe: i=13 j=-30
}//fin main()
public static void println(String str) {
System.out.println(str);
}
}//fin clase ClaseInterna

3.8.3.

Clases Internas Locales

Estas clases no se declaran dentro de otra clase al maximo nivel, sino dentro de un bloque de codigo, normalmente en un metodo, aunque tambien se pueden crear en un inicializador estatico o en un constructor.
Las principales caractersticas de las clases locales son las siguientes:
Como las variables locales, las clases locales solo son visibles y utilizables en el bloque de codigo en el que
estan definidas. Los objetos de la clase local deben ser creados en el mismo bloque en que dicha clase ha
sido definida. De esta forma se puede acercar la definicion al uso de la clase.
Las clases internas locales tienen acceso a todas las variables miembro y metodos de la clase contenedora.
Pueden ver tambien los miembros heredados, tanto por la clase interna local como por la clase contenedora.
Las clases locales pueden utilizar las variables locales y argumentos de metodos visibles en ese bloque de
codigo, pero solo si son final (en realidad la clase local trabaja con sus copias de las variables locales y
por eso se exige que sean final y no puedan cambiar).
Un objeto de una clase interna local, solo puede existir en relacion con un objeto de la clase contenedora,
que debe existir previamente.
La palabra this se puede utilizar en la misma forma que en las clases internas miembro, pero no las
palabras new y super .

3.8.4.

Clases Anonimas

Las clases anonimas son muy similares a las clases internas locales, pero sin nombre. En las clases internas
locales, primero se define la clase y luego se crean uno o mas objetos. En las clases anonimas se unen estos dos
pasos: como la clase no tiene nombre solo se puede crear un u nico objeto, ya que las clases anonimas no pueden
definir constructores. Estas clases se utilizan con mucha frecuencia para definir clases y objetos que gestionen los
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

55

3.9. INTERFACES
eventos de los distintos componentes de la interfaz de usuario como se vera en la seccion 6.3. Existen tres maneras
de definir una clase anonima:
Requieren una extension de la palabra clave new . Se definen en una expresion de Java, incluida en una
asignacion o en la llamada a un metodo. Se incluye la palabra new seguida de la definicion de la clase
anonima, entre llaves ....
Otra forma de definirlas es mediante la palabra new seguida del nombre de la clase de la que hereda
(sin extends ) y la definicion de la clase anonima entre llaves .... El nombre de la super-clase puede ir
seguido de argumentos para su constructor (entre parentesis, que con mucha frecuencia estaran vacos pues
se utilizara un constructor por defecto).
Una tercera forma de definirlas es con la palabra new seguida del nombre de la interface que implementa (sin implements ) y la definicion de la clase anonima entre llaves .... En este caso la clase anonima
deriva de Object. El nombre de la interface va seguido por parentesis vacos, pues el constructor de
Object no tiene argumentos.
Para las clases anonimas, el compilador produce archivos con un nombre del tipo ClaseContenedora$1.class,
asignando un numero correlativo a cada una de las clases anonimas.
En este tipo de clase, se deben respetar los aspectos tipograficos, pues al no tener nombre dichas clases, suelen
resultar difciles de leer e interpretar. Por lo tanto, cuando se usen, seguir los siguientes consejos:
Poner la palabra new en la misma lnea que el resto de la expresion.
Las llaves se abren en la misma lnea que new , despues del cierre del parentesis de los argumentos del
constructor.
El cuerpo de la clase anonima se debe sangrar respecto a las lneas anteriores de codigo para que resulte
claramente distinguible.
El cierre de las llaves va seguido por el resto de la expresion en la que se ha definido la clase anonima.
Ejemplo de definicion de una clase anonima derivada de ActionListener:
objeto.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
...
}
});

3.9.

Interfaces

La primera y mas conocida funcion del uso de interfaces, es la de resolver el problema de la herencia multiple
presente en otros lenguajes, como por ejemplo C++. Las interfaces de Java, al separar la forma del como (la
declaracion del codigo que lo implementa) permiten la herencia multiple sin los problemas tpicos que se pueden
plantear, para decidir que implementacion usar, cuando una clase hereda de dos que tienen implementaciones
distintas para la misma signatura(o header) de un metodo. Esta claro que tampoco es una solucion magica
(simplemente no se hereda el codigo, as que no hay que decidir cual se coge), pero es una solucion. Pero esta no
podra ser la u nica razon para el uso de interfaces, ya que tampoco es la mas usada (en realidad se usa bastante
poco si se exceptuan los componentes graficos que implementan varias interfaces de oyentes de eventos). Ademas,
los manuales de la buena programacion dicen que las interfaces son para modelar las relaciones tiene un, no
es un, aunque esto no siempre se as.
Otra funcion, es cuando se necesita cierto polimorfismo, es decir, cuando se necesita que una clase pudiera tener
con los mismos metodos o atributos distintos comportamientos, por ejemplo, una clase que pudiera almacenarse
en una base de datos o en un archivo de texto, solo cambiando el objeto que la hace persistente. Siempre que
56

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION
todos implementen la misma interfaz, la clase puede almacenarse en cualquier tipo de dispositivo sin cambiar los
metodos necesarios.
Una tercera razon, quizas menos relacionada con la programacion en primera instancia, pero que es de enorme
importancia para el diseno (para el buen diseno) de aplicaciones, es que las interfaces de Java son (o pueden ser)
el contrato entre distintas partes de una aplicacion, o entre los distintos programadores de una aplicacion.
Si se discuten y disenan buenas interfaces entre los distintos componentes de la aplicacion en la primera parte del
desarrollo, los diferentes grupos de trabajo pueden trabajar en paralelo, sin tener que preocuparse de lo que hacen
o ya han hecho el resto, y para los tests, es bastante facil escribir un par de clases de prueba que implementen
esas interfaces. De esta forma, la integracion entre las distintas partes de la aplicacion ya esta hecha desde un
principio, sin tener que andar consultando sobre que metodos se dispone para llevar a cabo una labor, y los grupos
de desarrollo solo tienen que preocuparse de la implementacion de su parte.
Ademas, el uso de interfaces, debido a la propia naturaleza de Java, hace que sea tremendamente facil encontrar
las clases que se ven afectadas por un cambio brusco en alguna parte de la aplicacion, ya que lo hara el compilador
solo.

3.9.1.

Declaracion de una Interfaz

Como mnimo, una declaracion de interfaz contiene la palabra clave interface y el nombre de la interfaz
que se va a crear.
interface Contable {
. . .
}
Nota: Por convencion, los nombres de interfaces empiezan con una letra mayuscula al igual que las clases. Frecuentemente los nombres de interfaces terminan en able o ible.
Una declaracion de interfaz puede tener otros dos componentes: el especificador de acceso public y una lista
de superinterfaces. Una interfaz puede extender otras interfaces, como una clase puede extender o subclasificar
otra clase. Sin embargo, mientras que una clase solo puede extender una superclase, las interfaces pueden extender
a cualquier numero de interfaces. As, una declaracion completa de interfaz se parecera a esto.
[public ] interface NombreDeInterface [extends ListaDeSuperInterfaces] {
. . .
}
El especificador de acceso public , indica que la interfaz puede ser utilizada por todas las clases en cualquier
paquete. Si la interfaz no se especifica como publica, solo sera accesible para las clases definidas en el mismo
paquete que la interfaz.
La clausula extends es similar a la utilizada en la declaracion de una clase, sin embargo, una interfaz puede
extender varias interfaces (mientras una clase solo puede extender una), y una interfaz no puede extender clases.
Esta lista de superinterfaces es un lista delimitada por comas de todas las interfaces extendidas por la nueva
interfaz.
Una interfaz hereda todas las constantes y metodos de sus superinterfaces, a menos que la interfaz oculte una
constante con el mismo nombre o redeclare un metodo con una nueva declaracion.
El Cuerpo de una Interfaz
El cuerpo de la interfaz contiene las declaraciones de metodos para los metodos definidos en la interfaz.
Ademas de las declaraciones de los metodos, una interfaz puede contener declaraciones de constantes.
Nota: Las declaraciones de miembros en una interfaz no permiten el uso de algunos modificadores y desaconsejan
el uso de otros. No se podran utilizar transient , volatile , o synchronized en una declaracion de miembro en una interfaz. Tampoco se podra utilizar los especificadores private y protected cuando se declaren
miembros de una interfaz.
Todos los valores constantes definidos en una interfaz son implcitamente publicos, estaticos y finales. El uso de
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

57

3.9. INTERFACES
estos modificadores en una declaracion de constante en una interfaz esta desaconsejado por falta de estilo. Similarmente, todos los metodos declarados en una interfaz son implcitamente publicos y abstractos.
Este codigo define una interfaz llamada Colecci
on que contiene un valor constante y tres declaraciones de metodos.
interface Colecci
on {
int MAXIMO = 500;
void agregar(Object obj);
void borrar(Object obj);
Object buscar(Object obj);
int contadorActual();
}
La interfaz anterior puede ser implementada por cualquier clase que represente una coleccion de objetos como
pueden ser pilas, vectores, etc...
Se observa que cada declaracion de metodo esta seguida por un punto y coma (;), porque una interfaz no proporciona implementacion para los metodos declarados dentro de e l.

3.9.2.

Uso de una Interfaz

Para utilizar una interfaz se debe escribir una clase que lo implemente. Una clase declara todas las interfaces
que implementa en su declaracion de clase. Para declarar que una clase implementa una o mas interfaces, se utiliza
la palabra clave implements seguida por una lista delimitada por comas con las interfaces implementadas por la
clase.
Por ejemplo, considere la interfaz Colecci
on presentado en la seccion anterior. Ahora, suponga que quiere escribir una clase que implemente una pila FIFO (primero en entrar, primero en salir). Como una pila FIFO contiene
otros objetos, tiene sentido que implemente la interfaz Colecci
on. La clase PilaFIFO declara que implementa
la interfaz Colecci
on de esta forma.
class PilaFIFO implements Colecci
on {
void agregar(Object obj) {
. . .
}
void borrar(Object obj) {
. . .
}
Object buscar(Object obj) {
. . .
}
int contadorActual() {
. . .
}
}
As se garantiza que proporciona implementacion para los metodos agregar(), borrar(), buscar()
y contadorActual().
Por convencion, la clausula implements sigue a la clausula extends si es que esta existe.
Observe que las firmas de los metodos de la interfaz Colecci
on implementados en la clase PilaFIFO deben
corresponder exactamente con las firmas de los metodos declarados en la interfaz Colecci
on, sino se produce un
error de compilacion.
58

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION

3.10.

Paquetes

En Java, es posible agrupar varias clases en una estructura llamada paquete. Un paquete no es mas que un
conjunto de clases, generalmente relacionadas entre s de alguna manera. Es habitual disenar una aplicacion, distribuyendo su funcionalidad entre varios paquetes, cuyas clases se comunican entre s a traves de interfaces bien
definidas.
El uso de paquetes aporta varias ventajas frente a la programacion sin paquetes. En primer lugar, permite encapsular funcionalidad, en unidades con un cierto grado de independencia, ocultando los detalles de implementacion.
De esta forma, se pueden conseguir disenos (e implementaciones) mas limpios y elegantes.
Por otra parte, se potencia la reutilizacion de las clases desarrolladas. Es posible definir interfaces de uso de cada
paquete, para que otros paquetes o aplicaciones puedan utilizar la funcionalidad implementada.
Ademas, el uso de paquetes permite la reutilizacion de los nombres de las clases, ya que el espacio de nombres
de un paquete, es independiente del de otros. El lenguage Java impone la restriccion de que una clase debe tener
un nombre u nico, dentro del paquete al cual pertenece. Sin embargo, es posible que dos clases tengan el mismo
nombre, siempre y cuando pertenezcan a paquetes distintos.

3.10.1.

Uso de Paquetes

Para incluir una clase dentro de un paquete, u nicamente hay que utilizar una sentencia package al principio
del archivo fuente. Por ejemplo:
package prueba;
public class Prueba {
...
}
O con subpaquetes:
package prueba.prueba2;
public class Prueba {
...
}

3.10.2.

Nombre de Paquetes y Clases

El nombre completo de la clase (fully qualified name) esta compuesto por el nombre del paquete al cual
pertenece la clase, ademas del nombre de la propia clase.
Los nombres completos de las clases del ejemplo anterior son prueba.Prueba y prueba.prueba2.Prueba.
Dado que prueba y prueba.prueba2 son paquetes distintos (aunque prueba.prueba2 sea un subpaquete de
prueba), no hay colision de nombres entre prueba.Prueba y prueba.prueba2.Prueba. Sin embargo, aunque
el compilador permita usar el mismo nombre de esta forma, no es una practica aconsejable, porque el codigo
tiende a ser confuso y propenso a errores.
En cuanto al nombre de los paquetes, Sun propuso en su momento un convenio para facilitar el uso de paquetes de
terceros. Este convenio no es en absoluto obligatorio, aunque s es aconsejable seguir alguno, para mantener mnimamente organizadas las clases. Segun el convenio propuesto por Sun, el nombre de los paquetes desarrollados
por una compana, se forma a partir del nombre del dominio DNS que esa compana tiene registrado, invirtiendo
el orden de sus miembros.
Por ejemplo, un paquete de gestion de stocks llamado manager desarrollado por IBM, podra llamarse
com.ibm.stocks.manager.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

59

3.10. PAQUETES

3.10.3.

Uso de Otros Paquetes

Para usar clases de otros paquetes, no hay mas que utilizar sentencias import , antes de la declaracion de la
clase. Por ejemplo:
import java.lang.*;
import java.util.Vector;
Con el primer import , se le indica al compilador que se importan todas las clases del subpaquete java.lang.
(Este paquete contiene clases esenciales en la mayora de aplicaciones Java, por lo que el compilador lo importa
automaticamente, aunque no se incluya una lnea como en este caso).
Con el segundo import , se indica que solo se quiere importar la clase Vector del subpaquete java.util.
Es posible utilizar una clase sin que este includa en un import , siempre y cuando se utilice su nombre completo.
Por ejemplo:
java.util.Vector vector = new java.util.Vector(100, 10);
La ventaja de utilizar una sentencia import , es que la lnea anterior se puede reducir a:
Vector vector = new Vector(100, 10);

3.10.4.

Estructura Jerarquica de Directorios

Los archivos .class pertenecientes a paquetes y subpaquetes deben estar organizados de forma adecuada
para que tanto el compilador como la maquina virtual puedan utilizarlos. Para ello, cada paquete se ubica en un
directorio. Cada subpaquete se ubica en un directorio de nivel inferior, y as sucesivamente. Ademas, el nombre
de cada directorio debe ser el del propio paquete.
Por ejemplo, las clases del paquete prueba, deben estar situadas en un directorio llamado prueba. Dentro de este,
debe haber un subdirectorio llamado prueba2, en el que se deben situar las clases del paquete prueba.prueba2.
As, cada (sub)paquete se corresponde con un (sub)directorio, y viceversa.
No existen restricciones en cuanto a donde debe estar situado el primer nivel, pero una vez situado en algun directorio, los niveles descendientes deben respetar la jerarqua.
En el ejemplo anterior, se podra situar el directorio prueba, en el directorio raz del a rbol de directorios (por
ejemplo C:/), en un directorio de primer nivel (por ejemplo, C:/java), en uno de segundo, etc.
En algunos tutoriales, libros y manuales, a este primer nivel donde estan situados los directorios se le llama
codebase.
Si nuestro codebase es C:/java/codebase, debe haber un directorio C:/java/codebase/prueba y otro
C:/java/codebase/prueba/prueba2.

3.10.5.

Ejecucion de las Clases

A la hora de ejecutar una aplicacion Java, tener en cuenta algunas cosas. En primer lugar, hay que indicar el
nombre completo de la clase a ejecutar.
Por ejemplo, si se tiene una clase Manager que pertenece al paquete com.ibm.manager, la orden para ejecutarla
sera:
java com.ibm.manager.Manager
Para que el anterior comando funcione, es necesario que el directorio actual desde el que se lanza la orden, sea el
codebase (por ejemplo, C:/java/codebase, si la clase Manager esta en
C:/java/codebase/com/ibm/manager/Manager.class). Si se esta en otro directorio, es posible evitar el
tener que cambiar de directorio, indicando a la maquina virtual que directorio debe tomar como codebase, con
una orden como:
java -classpath C:/java/codebase com.ibm.manager.Manager
60

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

ORIENTADA A OBJETOS
CAPITULO 3. PROGRAMACION
Puede ser que en el a rbol de directorios, se tengan todas las clases juntas a partir de un u nico directorio codebase,
o que se tengan separadas en varios. Puede ser que se tengan unas clases a partir de C:/java/codebase y otras
a partir de D:/clases, por ejemplo.
Para facilitar la ejecucion de las clases y evitar el tener que incluir parametros demasiado largos en las invocaciones a la maquina virtual, es posible definir una variable de entorno llamada CLASSPATH que contenga todos los
directorios codebase del sistema.
Utilizando esta variable, es posible invocar y utilizar clases que esten en cualquier parte, sin tener que pasarle un
parametro -classpath a la maquina virtual.
Por ejemplo, con CLASSPATH = C:/java/codebase;D:/clases es posible utilizar clases que esten situadas en
esos dos directorios. En el ejemplo anterior, ya no es necesario el parametro -classpath, por lo que el comando:
java com.ibm.manager.Manager
puede ser ejecutado desde cualquier directorio. (No es posible suprimir com, com.ibm o com.ibm.manager,
puesto que forman parte del nombre completo de la clase).

Michael Moossen

Departamento de Informatica. U.T.F.S.M.

61

3.10. PAQUETES

62

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

Captulo 4

Programacion con la API Estandar


En este captulo se veran varios aspectos importantes de la programacion con Java, como la manipulacion
eficiente de cadenas de caracteres con la clase StringBuffer, manejo de fechas y funciones matematicas, y
tambien temas especficos como la conectividad a bases de datos y el manejo de archivos.

4.1.

Manejo de Strings

En esta seccion, se veran algunos detalles del manejo de cadenas de caracteres o strings. Se veran primero
algunas caractersticas de la clase String, luego la funcionalidad de la clase StringBuffer, que permite aumentar el rendimiento en el manejo de strings, y finalmente la clase StringTokenizer que es una herramienta clave
para descomponer strings.

4.1.1.

La Clase String

La clase String representa cadenas de caracteres. Todos los literales de cadenas de caracteres, como "abc",
son implementados como instancias de esta clase.
Los objetos de tipo String son constantes, sus valores no pueden ser modificados una vez creados. La clase
StringBuffer soporta strings mutables. Ejemplos de un string:
String str = "abc";
Que es equivalente a:
char data[] = {a, b, c};
String str = new String(data);
A continuacion, algunos ejemplos del uso de strings:
System.out.println("abc");
String cde = "cde";
System.out.println("abc"+ cde);
String c = "abc".substring(2,3);
String d = cde.substring(1, 2);
La clase String incluye metodos para examinar los caracteres individuales de la secuencia, para comparar strings,
para buscar strings, para extraer substrings, y para crear copias en mayusculas o minusculas. A continuacion, una
breve descripcion de los principales metodos de la clase, para realizar estas funcionalidades:
char charAt(int index)
Retorna el caracter en la posicion especifcada por index. index debe ser un valor entre cero y length()-1.
63

4.1. MANEJO DE STRINGS


int compareTo(String anotherString)
Compara el string actual con otro en forma lexicografica. El resultado es un entero negativo si este string
precede al parametro, un numero positivo si el parametro precede este string o cero si son iguales.
int indexOf(String str, int fromIndex)
Retorna la posicion de la primera ocurrencia del parametro en el string actual, a partir de la posicion indicada
por fromIndex. Si no se encuentra ninguna ocurrencia se devuelve -1.
int length()
Retorna el largo del string en caracteres.
String replace(char oldChar, char newChar)
Retorna un nuevo string que resulta de reemplazar todas las ocurrencias de oldChar por newChar en el
string actual.
String substring(int beginIndex, int endIndex)
Retorna un nuevo string formado por los caracteres del string original desde la posicion beginIndex inclusive hasta la posicion endIndex exclusive. Si beginIndex es negativo, o endIndex es mayor que length(),
o si beginIndex es mayor que endIndex se produce un IndexOutOfBoundsException.
String toLowerCase()
Convierte todos los caracteres de este string a caracteres en minuscula.
String toUpperCase()
Convierte todos los caracteres de este string a caracteres en mayuscula.
String trim()
Remueve espacios en blanco(y caracteres de control) tanto del principio como del final del string.

4.1.2.

La Clase StringBuffer

Un StringBuffer implementa una secuencia de caracteres mutables, es como un string, pero que puede ser
modificado. En cualquier instante del tiempo, su contenido es una secuencia de caracteres bien definida, pero su
largo y contenido pueden ser cambiados a traves de la invocacion de algunos metodos. StringBuffer es usado
por el compilador, para implementar el operador de concatenacion binario +. Por ejemplo, el codigo:
String x = "a"+ 4 + "c";
Se compila como si fuese:
String x = new StringBuffer().append("a").append(4).append("c").toString();
Lo cual crea, un nuevo StringBuffer inicialmente vaco, luego se le concatena la representacion en string de
cada operando uno a uno, y finalmente se convierte el StringBuffer en un String.
Las principales operaciones que pueden ser invocadas por un StringBuffer, son los metodos insert() y
append(), los cuales estan sobrecargados para permitir la manipulacion de practicamente cualquier tipo de dato.
El metodo append() siempre agrega su parametro al final del buffer, y el metodo insert() lo hace en la posicion
especifcada.
Por ejemplo, si z es un StringBuffer cuyo contenido actual es "start", entonces la llamada z.append("le")
dejara el contenido de z en "startle". As tambien, la llamada z.insert(4, "le") producira "starlet".
En general, si sb es una instancia de un StringBuffer, entonces sb.append(x) tiene el mismo efecto que
sb.insert(sb.length(), x).
Cada StringBuffer tiene una capacidad. Mientras el largo de la cadena de caracteres que almacene no exceda
esta capacidad, no es necesario reservar mas espacio de memoria. Si en cambio, esta capacidad se sobrepasa,
automaticamente se ajustara la memoria reservada por el StringBuffer.
64

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION

4.1.3.

La Clase StringTokenizer

La clase StringTokenizer permite separar un string en varios tokens.


El conjunto de delimitadores (los caracteres que separan los tokens) deben ser especificados al momento de la
creacion.
Una instancia de un StringTokenizer se puede comportar de dos maneras, dependiendo si fue creado con el
modificador returnDelims con el valor verdadero o falso.
Si es falso, los caracteres delimitadores sirven para separar los tokens. Un token es una secuencia maxima de
caracteres consecutivos que no son delimitadores.
Si es verdadero, los caracteres delimitadores son tambien considerados tokens. por lo tanto, un token es un caracter
delimitador o una secuencia maxima de caracteres consecutivos que no son delimitadores.
Un objeto StringTokenizer mantiene internamente la posicion del string ya procesada. As, algunas operaciones
permiten seguir procesando el string y cambiar este estado interno.
El siguiente ejemplo demuestra el uso de un StringTokenizer:
StringTokenizer st = new StringTokenizer("this is a test");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
Se obtiene como salida:
this
is
a
test

4.2.

Utilidades

4.2.1.

Iteradores

Existe una interfaz llamada Iterator. Un objeto que implementa esta interfaz, genera una serie de elementos,
de a uno a la vez. Llamadas sucesivas al metodo next() retorna elementos sucesivos de la serie. El metodo
hasNext() indica si aun quedan elementos en la serie.
Por ejemplo, para iterar por sobre todos los elementos de un vector:
for (Iterator it = V.iterator(); it.hasNext(); ) {
System.out.println(it.next());
}
Java provee los mecanismos para iterar sobre los elementos de un Vector, las claves y valores de un Hashtable,
entre otros.

4.2.2.

Vectores

La clase Vector implementa un arreglo de objetos mutable. Como un arreglo, contiene componentes que
pueden ser accesados usando un ndice entero. Sin embargo, el tamano de un vector puede variar segun se necesite
para acomodar los objetos agregados o removidos despues que el vector fue creado.
Cada vector trata de optimizar la administracion de memoria, manteniendo variables de capacidad e incremento
de capacidad. La capacidad es siempre, por lo menos del tamano del vector, siendo usualmente un poco mayor, ya
que cada vez que se debe aumentar la capacidad del vector, esta lo hace en bloques de tamano dado por la variable
de incremento de capacidad. Una aplicacion, tambien podra aumentar explcitamente la capacidad de un vector,
antes de agregar una gran cantidad de objetos, para as diminuir la sobrecarga de la administracion de memoria.
A continuacion, una breve descripcion de los metodos mas importantes de esta clase:
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

65

4.2. UTILIDADES
void addElement(Object obj)
Agrega el objeto especifcado al final del vector, incrementando su tamano en uno. Su capacidad tambien es
incrementada si es necesario.
boolean removeElement(Object obj)
Elimina la ocurrencia del objeto(con menor ndice) en el vector. Todos los elementos posteriores al elemento
eliminado, quedan con su ndice disminudo en uno.
String toString()
Retorna la representacion de este vector, conteniendo la representacion en string de cada elemento.
boolean isEmpty()
Prueba si este vector tiene elementos.
Iterator iterator()
Retorna un iterador, para iterar sobre los elementos del vector.
int indexOf(Object elem, int index)
Retorna el ndice del objeto buscado a partir del ndice indicado. Si no se encuentra, retorna -1.
Object elementAt(int index)
Retorna el elemento en la posicion indicada.
void setElementAt(Object obj, int index)
Reemplaza el elemento en la posicion indicada.

4.2.3.

La Clase Hashtable

Esta clase implementa una interfaz, que mapea nombres clave a valores. Cualquier objeto distinto de null
puede ser usado como clave o valor.
Para guardar y obtener objetos exitosamente de un Hashtable, los objetos usados como clave, deben implementar
los metodos hashCode() y equals().
Una instancia de Hashtable tiene dos parametros que afectan su rendimiento: la capacidad inicial y el factor de
carga. La capacidad es el numero de posiciones disponibles en la tabla, y el factor de carga, es una medida de
que tan llena puede estar la tabla antes de que incremente su capacidad automaticamente. Cuando la cantidad de
elementos en la tabla excede el producto entre el factor de carga y la capacidad actual, la capacidad es incrementada
llamando al metodo rehash().
Generalmente, el factor de carga por defecto (0.75) ofrece un buen compromiso entre costos de tiempo y espacio.
Valores mayores reducen la perdida de espacio, pero incrementan el costo de tiempo de accceso a los elementos.
La capacidad inicial controla el compromiso entre espacio perdido y la necesidad de reestructurar la tabla. No
sera necesario reestructurar la tabla, si la capacidad inicial es mayor que el numero de elementos maximo que
tendra la tabla, dividido por su factor de carga. Sin embargo, al asignar a la capacidad inicial un valor muy grande,
se puede perder mucho espacio.
El siguiente ejemplo crea un Hashtable de numeros, usando los nombres de los numeros como clave:
Hashtable numbers = new Hashtable();
numbers.put("one", new Integer(1));
numbers.put("two", new Integer(2));
numbers.put("three", new Integer(3));
Para obtener el numero, se usa el siguiente codigo:
Integer n = (Integer)numbers.get("two");
if (n != null ) {
System.out.println("two = "+ n);
}
66

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
A continuacion, una descripcion breve de los metodos mas importantes de esta clase:
Object put(Object key, Object value)
Mapea la clave especificada al valor especificado en la tabla. Ni la clave ni el valor pueden ser null . El
valor puede ser obtenido llamando al metodo get() con la clave original. Este metodo retorna el valor
previo especificado por la clave en la tabla, o null si no exista.
Object get(Object key)
Retorna el valor al cual esta mapeada la clave especificada en la tabla, o null si la clave no esta mapeada
a ningun valor de la tabla.
Object remove(Object key)
Realiza la misma operacion que get(), pero ademas remueve la clave y su valor correspondiente de la tabla.
String toString()
Retorna una representacion de string del objeto, en la forma de un conjunto de entradas de la forma "clave
= valor", usando el metodo toString() de cada objeto.

4.2.4.

La Clase System

La clase System contiene diversos atributos y metodos u tiles. Es una clase estatica, que no puede ser instanciada.
Algunas de las funcionalidades que provee esta clase son: Flujos de datos de entrada, salida y error estandares; y
acceso a propiedades del sistema, entre otras.
Los flujos de datos estandares se definen como:
static final InputStream in;
static final PrintStream out, err;
Cada uno de estos flujos de datos esta siempre abierto y listo para recibir y enviar datos. Tipicamente estos flujos
de datos corresponden a la entrada a traves del teclado y la salida a traves de pantalla. Ejemplo:
System.out.println(data)
Estos son los metodos mas importantes de esta clase:
static String getProperty(String key)
Retorna la propiedad del sistema indicada por la clave especificada. El apendice B muestra un listado de
propiedades validas en la J2SE 1.4.
static String setProperty(String key, String value)
Establece la propiedad del sistema indicada, al valor especificado. Retorna el valor de la propiedad del
sistema, o null si no existe ninguna, con la clave especificada.
static void setIn(InputStream in)
static void setOut(PrintStream out)
static void setErr(PrintStream err)
Estos metodos reasignan los flujos estandares. Por ejemplo, para redireccionar la salida estandar a un archivo, basta esta lnea:
System.setOut(new PrintStream(new FileOutputStream(new File("c:/out.log"))));
As, el metodo System.out.println() escribe en el archivo "c:/out.log".
static void exit(int status)
Este metodo termina la ejecucion de la JVM. El argumento sirve como codigo del estado de la ejecucion;
por convencion, un valor distinto de cero indica un error de ejecucion.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

67


4.3. FUNCIONES MATEMATICAS

4.3.

Funciones Matematicas

Java tambien provee de un sin numero de funciones matematicas, distribudas en varias clases:

4.3.1.

La Clase Abstracta Number

Esta clase abstracta es la superclase de todas las clases encapsuladora de numeros como Byte y Long. Las
subclases de Number deben proveer metodos para convertir el valor numerico representado a byte , double ,
float , int , long y short . Por ejemplo,
int intValue()
Debe retornar el numero especificado como un int . Notar que esto puede producir aproximaciones y truncamientos.
Ademas, todas las clases encapsuladoras de numeros, como Integer o Float, proveen los siguientes metodos
(se muestran los metodos de la clase Double):
static double parseDouble(String s) throws NumberFormatException
Retorna un nuevo double inicializado al valor representado por el string especificado.
static Double valueOf(String s) throws NumberFormatException
Retorna un nuevo objeto Double inicializado al valor representado por el string especificado. El string es
interpretado como una representacion de un valor punto flotante. Espacio en blanco al inicio o final del
string son ignorados.
Por otra parte, las clases encapsuladoras de numeros decimales, como Float y Double, proveen las siguientes
constantes(se muestran los metodos de la clase Double):
static final double NaN
Esta constante representa un valor no numerico(Not-a-Number) de tipo Double, y es igual al valor calculado
como:
Double.longBitsToDouble(0x7ff8000000000000L)
static final double POSITIVE INFINITY
Esta constante representa el valor + de tipo Double, y es igual al valor calculado como:
Double.longBitsToDouble(0x7ff0000000000000L)
static final double NEGATIVE INFINITY
Esta constante representa el valor de tipo Double, y es igual al valor calculado como:
Double.longBitsToDouble(0xfff0000000000000L)

4.3.2.

La Clase Math

Esta clase contiene metodos para realizar operaciones numericas basicas, como por ejemplo funciones trigonometricas, logaritmo, exponencial y raz cuadrada.
A diferencia de la clase StrictMath, las funciones de esta clase no definen un resultado bit-a-bit concordante con
el estandar. Esta relajacion permite implementaciones de mejor rendimiento cuando no se requiere reproduccion
estricta.
Por defecto, muchas de las funciones de esta clase simplemente delegan la funcionalidad a las funciones equivalentes en StrictMath.
Para ayudar a asegurar la portabilidad de los programas Java, la definicion de muchas de las funciones de
StrictMath, requiere que produzcan el mismo resultado que ciertos algoritmos publicos. Estos algoritmos estan
publicados en netlib, bajo el paquete llamado Freely Distributable Math Library(fdlibm). Esta librera puede
68

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
ser encontrada en http://metalab.unc.edu/. Las funciones matematicas de Java fueron definidas con respecto
a la version del 4 de Enero de 1995.
Esta clase contiene las siguientes constantes matematicas:
static final double E
El valor de tipo double mas cercano que cualquier otro al valor de e, la base del algoritmo natural.
static final double PI
El valor de tipo double mas cercano que cualquier otro al valor de , la razon entre la circunferencia de
un circulo y su diametro.
A continuacion, una breve descripcion de los metodos mas importantes de esta clase:
static double sin(double a)
Retorna el seno trigonometrico de un a ngulo. Tambien existen las funciones tirgonometricas cos(), tan(),
asin(), acos() y atan().
static double abs(double a)
Retorna el valor absoluto de un valor double . El calculo exacto es:
Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)
Tambien existen versiones de este metodo para float , int y long .
static int max(int a, int b)
Retorna el mayor de los dos valores enteros. Tambien existen versiones de este metodo para float , double
y long .
static long min(long a, long b)
Retorna el menor de los dos valores. Tambien existen versiones de este metodo para float , double e
int .
static double random()
Retorna un valor mayor o igual a cero y menor que uno. Los valores retornados son escogidos pseudoaleatoriamente con una distrubcion (aproximadamente) uniforme en este rango.
static double floor(double a)
Retorna el mayor valor double que no es mayor que el argumento y que es igual a un entero matematico.
static double ceil(double a)
Retorna el menor valor double que no es menor que el argumento y que es igual a un entero matematico.
Notar que Math.ceil(x) es exactamente lo mismo que Math.floor(-x).
static int round(float a)
Retorna el entero mas cercano al argumento. El resultado es igual al valor de la expresion:
(int )Math.floor(a + 0.5f)
static double sqrt(double a)
Retorna la raz cuadrada positiva de un valor double .
static double log(double a)
Retorna el algoritmo natural (base e) de un valor double .
static double exp(double a)
Retorna el numero exponencial (e) elevado a la potencia indicada.
static double pow(double a, double b)
Retorna el valor del primer argumento elevado a la potencia indicada por el segundo.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

69

4.4. MANEJO DE FECHAS

4.3.3.

El paquete java.math

Este paquete provee clases para realizar aritmetica entera(BigInteger) y decimal(BigDecimal) de precision
arbitraria.
La clase BigInteger es analoga al tipo de dato int , excepto que provee precision arbitraria, por lo que no se
pueden producir errores de desbordamiento o perdida de precision. Ademas de las operaciones aritmeticas estandares, BigInteger provee de aritmetica modular, calculo del maximo comun denominador, prueba de primalidad,
generacion de numeros primos, manipulacion de bits, etc.
El siguiente ejemplo muestra nuevamente los numeros de Fibonacci, ahora usando precision arbitraria, lo que
permite obtener resultados precisos.
BigInteger fibonacci(long num) {
BigInteger sum = BigInteger.ZERO;
if (num == 1 || num == 2) {
sum = BigInteger.ONE;
}
else {
BigInteger f1 = BigInteger.ONE;
BigInteger f2 = BigInteger.ONE;
for (long i = 3; i <= num; i++) {
sum = f1.add(f2);
f1 = f2;
f2 = sum;
}
}
return sum;
}
As, se puede obtener el valor real de F20000 , y comprobar que tiene 4180 dgitos!!.
La clase BigDecimal, ademas de proveer las operaciones aritmeticas basicas, permite el control absoluto sobre el
comportamiento al redondear, permitiendo eligir entre ocho modos diferentes.
El siguiente ejemplo, muestra el valor de /e, con 2000 decimales de precision:
BigDecimal a = new BigDecimal(Math.PI);
a = a.divide(new BigDecimal(Math.E), 2000, BigDecimal.ROUND DOWN);
System.out.println(a);

4.4.

Manejo de Fechas

Antes de la aparicion del JDK 1.1, la clase Date tena dos funcionalidades adicionales a las actuales. Permita
la interpretacion de fechas como valores de ano, mes, da, hora, minuto y segundo. Tambien permita formatear
fechas y convertir strings en fechas. Desafortunadamente esta API no soportaba las nuevas funcionalidades de
internacionalizacion incorporada en el JDK 1.1, por lo que desde entonces, se debe usar la clase Calendar para
hacer conversiones entre fechas y campos, y la clase DateFormat para formatear fechas y convertir strings en
fechas.

4.4.1.

La Clase Date

La clase Date representa un instante especfico en el tiempo, con precision a la milesima de segundo.
Aunque la clase Date intenta reflejar la Hora Universal(UTC), puede que no sea exacta, dependiendo del entorno
del computador en que se ejecute la JVM. Casi cualquier sistema operativo moderno asume que un da es igual a
70

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
24 60 60 = 86400 segundos. En la UTC, sin embargo, cerca de cada ano par o dos, existe un segundo adicional,
llamado leap second, el cual se agrega como u ltimo segundo del da, siempre un 31 de Diciembre o un 30 de
Junio. Por ejemplo, el u ltimo minuto del ano 1995 tuvo 61 segundos.
A continuacion, una breve descripcion de los constructores mas u tiles de esta clase:
Date()
Crea un nuevo objeto que se inicializa de tal forma que represente la hora a la cual fue creado.
Date(long date)
Crea un nuevo objeto que se inicializa de tal forma que represente el numero especificado de milisegundos
desde la hora base estandar, llamada tambien e poca(epoch), actualmente Enero 1, 1970, 00:00:00 GMT.
Y una breve descripcion de los metodos mas importantes:
int compareTo(Date anotherDate)
Compara dos fechas. Retorna cero si las fechas son iguales, un valor menor que cero si esta fecha es menor
que el argumento; y un valor mayor que cero si esta fecha es mayor que el parametro.
long getTime()
Retorna el numero de milesimas de segundo desde Enero 1, 1970, 00:00:00 GMT representados por esta
fecha.
void setTime(long time)
Fija esta fecha de tal forma que represente el numero de milesimas de segundo desde Enero 1, 1970,
00:00:00 GMT.
String toString()
Convierte esta fecha a un string de la forma: dow mon dd hh:mm:ss zzz yyyy. Ver mas detalles de los
formatos en la seccion 4.4.3.

4.4.2.

La Clase GregorianCalendar

Esta clase es una subclase concreta de Calendar y provee el calendario estandar usado en casi todo el mundo. Esta implementacion considera una u nica discontinuidad, que corresponde a la fecha en que se instituyo el
calendario Gregoriano, en la mayora de los pases el 15 de octubre de 1582. As, antes del 4 de Octubre de 1582,
se usa el calendario Juliano y al da siguiente, el 15 de Octubre, se comienza a usar el calendario Gregoriano que
incorpora los anos bisiestos(los anos divisibles por cuatro, excepto los anos divisibles por 100 y no divisibles por
400, tienen un da mas: el 29 de Febrero).
Sin embargo, las fechas anteriores al ano 45 Antes de Cristo pueden no ser exactas debido a que no exista un
calendario estandar. Tambien, se pueden producir problemas con anos anteriores a 1583, ya que el ano nuevo se
celebraba el 25 de Marzo, as para evitar confusiones, este calendario siempre usa el 1 de Enero como ano nuevo.
A continuacion, un ejemplo ilustrativo de los principales usos de este calendario:
System.out.println("Current Time");
// create a Chile/Continental Time time zone
SimpleTimeZone pdt = new SimpleTimeZone(-4 * 60 * 60 * 1000, "Chile/Continental");
// create a GregorianCalendar with the Chile/Continental time zone
// and the current date and time
Calendar calendar = new GregorianCalendar(pdt);
calendar.setTime(new Date());
// print out a bunch of interesting things
System.out.println("ERA: "+ calendar.get(Calendar.ERA));
System.out.println("YEAR: "+ calendar.get(Calendar.YEAR));
System.out.println("MONTH: "+ calendar.get(Calendar.MONTH));
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

71

4.4. MANEJO DE FECHAS


System.out.println("WEEK OF YEAR: "+ calendar.get(Calendar.WEEK OF YEAR));
System.out.println("WEEK OF MONTH: "+ calendar.get(Calendar.WEEK OF MONTH));
System.out.println("DATE: "+ calendar.get(Calendar.DATE));
System.out.println("DAY OF MONTH: "+ calendar.get(Calendar.DAY OF MONTH));
System.out.println("DAY OF YEAR: "+ calendar.get(Calendar.DAY OF YEAR));
System.out.println("DAY OF WEEK: "+ calendar.get(Calendar.DAY OF WEEK));
System.out.println("DAY OF WEEK IN MONTH: "+ calendar.get(
Calendar.DAY OF WEEK IN MONTH));
System.out.println("AM PM: "+ calendar.get(Calendar.AM PM));
System.out.println("HOUR: "+ calendar.get(Calendar.HOUR));
System.out.println("HOUR OF DAY: "+ calendar.get(Calendar.HOUR OF DAY));
System.out.println("MINUTE: "+ calendar.get(Calendar.MINUTE));
System.out.println("SECOND: "+ calendar.get(Calendar.SECOND));
System.out.println("MILLISECOND: "+ calendar.get(Calendar.MILLISECOND));
System.out.println("ZONE OFFSET: "+ (calendar.get(
Calendar.ZONE OFFSET)/(60*60*1000)));
System.out.println("DST OFFSET: "+ (calendar.get(
Calendar.DST OFFSET)/(60*60*1000)));
System.out.println(calendar.getTime());
System.out.println("Current Time, plus 1day 5h32m");
calendar.add(Calendar.DATE, 1);
calendar.add(Calendar.HOUR, 5);
calendar.add(Calendar.MINUTE, 32);
System.out.println(calendar.getTime());

4.4.3.

La Clase SimpleDateFormat

Esta clase es una clase concreta para formatear(convertir una fecha en un string) y parsear(convertir un string
en una fecha) fechas.
Sintaxis de Formatos de Fecha
Para especificar el formato de fecha se usa un patron de fecha. Este patron, se puede formar por los siguientes
smbolos:
Smbolo
G
y
M
d
h
H
m
s
S
E
D
F
w
W
a
k
72

Descripcion
Descriptor de era
Ano
Mes del ano
Da del mes
Hora en am/pm (1-12)
Hora del da (0-23)
Minuto de hora
Segundo de minuto
Milesima de segundo
Da de la semana
Da del ano
Da de la semana del mes
Semana del ano
Semana del mes
Descriptor de am/pm
Hora del da (1-24)

Presentacion
Texto
Numero
Texto o Numero
Numero
Numero
Numero
Numero
Numero
Numero
Texto
Numero
Numero
Numero
Numero
Texto
Numero

Ejemplo
AD
1996
July o 07
10
12
0
30
55
978
Martes
189
2 (Segundo Lunes de Julio)
27
2
PM
24

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
Smbolo
K
z

Descripcion
Hora en am/pm (0-11)
Zona horaria
Escape para texto
Comilla simple

Presentacion
Numero
Texto
Delimitador
Literal

Ejemplo
0
Hora Estandar del Pacfico
dd de MMMM de yyyy

la cantidad de smbolos en el patron determinan el formato:


Texto: Cuatro o mas smbolos significa descripcion completa, menos de cuatro, usa la forma corta si existe una.

Numero:
La cantidad de smbolos indica el numero mnimo de dgitos. Numeros menores seran completados con
ceros a la izquierda. Solo el ano es manejado en forma especial, si la cantidad de y es 2, el ano se trunca
a dos dgitos.

Texto o Numero:
Tres smbolos o mas, significa texto, sino numero.
Ejemplos:
Patron de Formato
"yyyy.MM.dd G athh:mm:ss z"
"EEE, MMM d, yy"
"h:mm a"
"hh oclocka, zzzz"
"K:mm a, z"
"yyyyy.MMMMM.dd GGG hh:mm aaa"

Resultado
1996.07.10 AD at 15:08:56 PDT
Wed, July 10, 96
12:08 PM
12 oclock PM, Pacific Daylight Time
0:00 PM, PST
1996.July.10 AD 12:08 PM

Codigo de ejemplo:
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm");
Date currentTime1 = new Date();
String dateString = formatter.format(currentTime1);
// Parse the previous string back into a Date.
ParsePosition pos = new ParsePosition(0);
Date currentTime2 = formatter.parse(dateString, pos);
En el ejemplo, la fecha currentTime2 es igual a la fecha currentTime1.

4.4.4.

La Clase SimpleTimeZone

Esta clase es una subclase concreta de TimeZone, que representa una zona horaria para ser usada con el
calendario Gregoriano.
Su principal funcionalidad es el siguiente constructor:
SimpleTimeZone(int rawOffset, String ID);
Que construye un SimpleTimeZone con el desplazamiento indicado en milesimas de segundo, de la Hora Media
en Greenwich(GMT) e identificador de la zona horaria. Todos los identificadores disponibles pueden ser obtenidos
con el metodo TimeZone.getAvailableIDs(). Normalmente, se debera usar el metodo TimeZone.getDefault()
para crear un TimeZone. Ejemplo,
SimpleTimeZone pdt = new SimpleTimeZone(-4 * 60 * 60 * 1000, "Chile/Continental");
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

73

4.5. ENTRADA Y SALIDA DE DATOS

4.5.

Entrada y Salida de Datos

4.5.1.

Archivos y Directorios

Un objeto de la clase File puede representar un archivo o un directorio. Tiene los siguientes constructores:
File(String name)
File(String dir, String name)
File(File dir, String name)
Para crear un objeto que encapsule un archivo, se puede dar el nombre de un archivo, el nombre y el directorio, o
solo el directorio, como path absoluto y como path relativo al directorio actual. Ejemplos:
File f1 = new File("c:/windows/notepad.exe");
File f2 = new File("c:/windows"); // Un directorio
File f3 = new File(f2, "notepad.exe"); // Es igual a f1
Notar que Java interpreta el slash(/) en forma correcta, es decir, como un backslash.
Para saber si el archivo existe se puede llamar al metodo exists().
Si File representa un archivo que existe, los siguientes metodos dan informacion acerca de e l:
boolean isFile()
Retorna true si el archivo existe y no es un directorio.
long length()
Retorna el tamano del archivo en bytes.
long lastModified()
Retorna la fecha de la u ltima modificacion del archivo.
boolean canRead()
Retorna true si el archivo se puede leer.
boolean canWrite()
Retorna true si el archivo se puede escribir.
boolean delete()
Intenta borrar el archivo, si tiene e xito, retorna true .
boolean renameTo(File newFile)
Intenta renombrar el archivo actual por el parametro, retorna true si tiene e xito.
Si File representa un directorio, se pueden utilizar los siguientes metodos:
boolean isDirectory()
Retorna true si existe el directorio.
boolean mkdir()
Intenta crear el directorio, si tiene e xito retorna true .
boolean delete()
Intenta borrar el directorio, si tiene e xito retorna true .
String[] list()
Devuelve una lista de archivos que se encuentran en el directorio.
Por u ltimo, los siguientes metodos devuelven el path del archivo de distintas maneras.
74

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
String getPath()
Devuelve el path que contiene el objeto File.
String getName()
Devuelve el nombre del archivo.
String getAbsolutePath()
Devuelve el path absoluto (concatenando el relativo al actual).
String getParent()
Devuelve el directorio padre.
El siguiente codigo de ejemplo, muestra todas las funcionalidades de la clase File:
import java.io.File;
import java.util.Date;
class FileExample {
public static void main(String[] args) {
File InFile = new File(args[0]);
if (!InFile.exists()) {
System.out.println("Archivo "+ InFile.getAbsolutePath() + "no Existe.");
System.exit(1);
}
if (InFile.isFile()) {
showFile(InFile);
System.exit(0);
}
if (InFile.isDirectory()) {
showDir(InFile);
System.exit(0);
}
System.out.println("Error Indeterminado:");
System.out.println(InFile.getAbsolutePath());
System.out.println("No es ni Archivo, ni Directorio.");
System.exit(2);
}
public static void showFile(File F) {
System.out.println("Directorio Padre: "+ F.getParent());
System.out.println("Nombre: "+ F.getName());
System.out.println("Tama
no: "+ F.length() + " Bytes");
System.out.println("Fecha Modificaci
on: "+ (new Date(F.lastModified())));
System.out.println("Puede ser le
do: "+ F.canRead());
System.out.println("Puede ser escrito: "+ F.canWrite());
}
public static void showDir(File F) {
System.out.println("Directorio Padre: "+ F.getParent());
System.out.println("Nombre: "+ F.getName());
System.out.println("Contiene "+ F.list().length + " Entradas.");
for (int i=0; i<F.list().length; i++) {
System.out.println(F.list()[i]);
}
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

75

4.5. ENTRADA Y SALIDA DE DATOS


}
}

4.5.2.

Lectura y Escritura en Archivos de Texto

Existen las clases FileReader y FileWriter (extendiendo las clases Reader y Writer) que permiten leer y
escribir caracteres desde archivos de texto. Se puede construir un objeto de cualquiera de estas dos clases a partir
de un string que contenga el nombre del archivo, o un objeto de la clase File que represente dicho archivo. Por
ejemplo, el codigo:
FileReader fr1 = new FileReader("archivo.txt");
es equivalente a:
File f = new File("archivo.txt");
FileReader fr2 = new FileReader(f);
Si no se encuentra el archivo indicado, los constructores de FileReader pueden lanzar una excepcion
java.io.FileNotFoundException.
Los constructores de FileWriter pueden lanzar java.io.IOException. Si no encuentran el archivo indicado,
crean uno nuevo. Por defecto, esta clase comienza a escribir al comienzo del archivo, reemplazando su contenido
anterior. Para escribir detras de lo que ya existe en el archivo (append), se utiliza un segundo argumento de tipo
boolean con valor true :
FileWriter fw = new FileWriter("archivo.txt", true );
Para terminar, un ejemplo que copia el contenido del archivo "a1.txt" al archivo "a2.txt":
FileReader in = new FileReader("a1.txt");
FileWriter out = new FileWriter("a2.txt");
int c;
while ((c = in.read()) != -1)
out.write(c);
in.close();
out.close();
Esto esta bien si se desea trabajar con caracteres, pero es bastante poco amigable si se desean leer strings o
numeros, por lo tanto se introducen otras clases que permiten un manejo mas facil y eficiente de archivos de texto.
Se puede crear un objeto BufferedReader para leer de un archivo de texto de la siguiente manera:
BufferedReader br = new BufferedReader(new FileReader("archivo.txt"));
Utilizando el objeto de tipo BufferedReader con el metodo readLine() se puede leer el archivo de lnea en
lnea:
String Linea = br.readLine();
As, ya se ha ledo una lnea del archivo. Y que hacer con una lnea entera? En eso ayuda la clase
StringTokenizer vista en la seccion 4.1.3 que da la posibilidad de separar la lnea en las palabras (tokens)
que la forman, y cuando sea preciso, se pueden convertir las palabras en numeros.
En el caso de archivos, es muy importante utilizar un buffer, puesto que la tarea de escribir en disco es muy lenta
respecto a los procesos del programa y realizar las operaciones de lectura de golpe y no de una en una, hace mucho mas eficiente el acceso. Por ejemplo, a continuacion se lee un archivo completo que se guarda en la variable
texto:
76

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
String texto = new String();
try {
BufferedReader entrada = new BufferedReader(new FileReader("archivo.txt"));
String s;
while ((s = entrada.readLine()) != null )
texto += s;
entrada.close();
}
catch (java.io.FileNotFoundException fnfex) {
System.out.println("Archivo no encontrado: "+ fnfex);
}
En cambio, La clase PrintWriter es mas practica para escribir un archivo de texto, porque posee los metodos
print() y println(), al igual que System.out.
Un objeto PrintWriter se puede crear a partir de un BufferedWriter (para disponer de buffer), que se crea a
partir del FileWriter al que se le pasa el nombre del archivo. Despues, escribir en el archivo es tan facil como
en pantalla. El siguiente ejemplo, ilustra lo anterior:
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("archivo.txt"));
PrintWriter salida = new PrintWriter(bw);
salida.println("Hola, soy la primera l
nea");
salida.close();
// Modo append
bw = new BufferedWriter(new FileWriter("archivo.txt", true ));
salida = new PrintWriter(bw);
salida.print("Y yo soy la segunda.");
double b = 123.45;
salida.println(b);
salida.close();
}
catch (java.io.IOException ioex) {
ioex.printStackTrace();
}

4.5.3.

Lectura y Escritura en Archivos Binarios

Para la manipulacion de archivos binarios, Java provee las clases FileInputStream y FileOutputStream
para leer y escribir bytes. Su uso es identico al de las clases FileReader y FileWriter, por lo tanto a continuacion, solo un ejemplo de su uso para copiar archivos.
FileInputStream in = new FileInputStream(new File("a1.txt"));
FileOutputStream out = new FileOutputStream(new File("a2.txt"));
int c;
while ((c = in.read()) != -1)
out.write(c);
in.close();
out.close();
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

77

4.5. ENTRADA Y SALIDA DE DATOS

4.5.4.

Archivos de Acceso Aleatorio

La clase RandomAccessFile implementa las interfaces DataInput y DataOutput y por lo tanto puede
usarse para leer y escribir. Se puede crear con un nombre de archivo o un objeto File. Cuando se crea un
RandomAccessFile, se debe indicar si solo se quiere leer o tambien se quiere escribir en el archivo (se tiene
que poder leer un archivo para poder escribirlo). La siguiente lnea de codigo crea un RandomAccessFile que lee
el archivo llamado "archivo.txt":
new RandomAccessFile("archivo.txt", "r");
Y esta abre el mismo archivo, tanto para lectura como para escritura:
new RandomAccessFile("archivo.txt", "rw");
Despues de haber abierto el archivo, se pueden usar los metodos comunes read() o write() para realizar operaciones de entrada y/o salida sobre el archivo.
RandomAccessFile soporta la nocion de puntero de archivo. Este puntero indica la posicion actual en el archivo,
cuando el archivo se crea por primera vez, el puntero de archivo es cero, indicando el principio del archivo. Las
llamadas a los metodos read() y write() ajustan la posicion del puntero de archivo segun el numero de bytes
ledos o escritos.
Ademas de los metodos de entrada y salida normales que implcitamente mueven el puntero de archivo cuando
ocurre una operacion, RandomAccessFile contiene tres metodos que manipulan explcitamente el puntero de
archivo:
int skipBytes(int n) throws IOException
Mueve el puntero hacia adelante el numero de bytes especificado.
void seek(long pos)
Mueve el puntero de archivo a la posicion anterior al byte especificado.
long getFilePointer() throws IOException
Devuelve la posicion actual (byte) del puntero de archivo.

4.5.5.

Serializacion de Objetos

El paquete java.io tiene otros dos streams de bytes ObjectInputStream y ObjectOutputStream que
funcionan como los otros streams de entrada y salida. Sin embargo, son especiales porque pueden leer y escribir
objetos.
La clave para escribir objetos es representar su estado de una forma suficientemente serializada para reconstruir el
objeto cuando es ledo. Por eso, leer y escribir objetos es un proceso llamado serializacion de objetos.
La serializacion de objetos, es esencial para construir todo, excepto aplicaciones temporales. Se Puede usar la
serializacion de objetos de las siguientes formas:
Invocacion Remota de Metodos(RMI): Comunicacion de objetos mediante sockets.
Persistencia de Peso Ligero: El archivo de un objeto para una invocacion posterior en el mismo programa.
Como programador Java, se necesita conocer la serializacion de objetos desde dos puntos de vista. Primero, saber
como serializar objetos, escribiendolos en un ObjectOutputStream y luego, leerlos usando un ObjectInputStream.
Segundo, saber como escribir una clase para que sus objetos puedan ser serializados.
Escribir en un ObjectOutputStream
Escribir objetos a un stream es un proceso sencillo. Por ejemplo,
78

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
FileOutputStream out = new FileOutputStream("theTime");
ObjectOutputStream s = new ObjectOutputStream(out);
s.writeObject("Today");
s.writeObject(new Date());
s.flush();
ObjectOutputStream es un stream de proceso, por eso debe construirse sobre otro stream. Este codigo construye un ObjectOutputStream sobre un FileOutputStream, para serializar el objeto a un archivo llamado
"theTime".
Luego, el string Today y un objeto Date se escriben en el stream con el metodo writeObject() de
ObjectOutputStream.
Si un objeto se refiere a otro objeto, entonces todos los objetos que son alcanzables desde el primero, son escritos
al mismo tiempo, para mantener la relacion entre ellos. As, el metodo writeObject() al serializar el objeto
especificado, sigue sus referencias a otros objetos recursivamente, y los escribe todos.
El stream ObjectOutputStream implementa la interfaz DataOutput, que define muchos metodos para escribir
tipos de datos primitivos, como writeInt(), writeFloat(), o writeUTF(). Por lo tanto, se pueden usar estos
metodos para escribir tipos de datos primitivos a un ObjectOutputStream.
El metodo writeObject() lanza una excepcion NotSerializableException, si el objeto dado no es serializable. Un objeto es serializable solo si la clase implementa la interfaz Serializable.
Leer desde un ObjectInputStream
Una vez que se han escrito objetos y tipos de datos primitivos en un stream, se deseara leerlos y reconstruir los
objetos. Esto tambien es sencillo. Aqu esta el codigo que lee el string y el objeto Date, que se escribieron en el
archivo llamado "theTime" del u ltimo ejemplo.
FileInputStream in = new FileInputStream("theTime");
ObjectInputStream s = new ObjectInputStream(in);
String today = (String)s.readObject();
Date date = (Date)s.readObject();
Como ObjectOutputStream, ObjectInputStream debe construirse sobre otro stream. En este ejemplo, los objetos fueron serializados en un archivo, por eso el codigo construye un ObjectInputStream sobre un
FileInputStream. Luego, el codigo usa el metodo readObject() de ObjectInputStream, para leer el string
y el objeto Date desde el archivo. Los objetos deben ser ledos desde el stream en el mismo orden en que se
esribieron. Observese que el valor de retorno de readObject() es un objeto, que es convertido y asignado a un
tipo especfico.
El metodo readObject() deserializa el siguiente objeto en el stream y revisa sus referencias a otros objetos
recursivamente, para deserializar todos los objetos que son alcanzables desde e l. De esta forma, se mantiene la
relacion entre los objetos.
El stream ObjectInputStream implementa la interfaz DataInput, que define metodos para leer tipos de datos
primitivos. Los metodos de DataInput son comparables a los definidos en DataOutput para escribir tipos de
datos primitivos. Entre ellos se incluyen readInt(), readFloat(), y readUTF(). Estos metodos se usan para
leer tipos de datos primitivos desde un ObjectInputStream.

Proporcionar Serializacion de Objetos Propios


Un objeto es serializable solo si su clase implementa la interfaz Serializable. As, si se quiere serializar
un ejemplar de una clase propia, la clase debe implementar esta interfaz. Esta es una interfaz vaca. Es decir, no
contiene ninguna declaracion de metodo; su proposito es simplemente identificar las clases cuyos objetos son serializables.
No se tiene que escribir ningun metodo. La serializacion de un objeto de esta clase la maneja el metodo
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

79

4.6. CONECTIVIDAD A BASE DE DATOS (JDBC)


defaultWriteObject() de ObjectOutputStream. Este metodo, escribe cualquier cosa necesaria para reconstruir el objeto de la clase, incluyendo lo siguiente:
La clase del Objeto.
Los valores para todos los miembros no-transient y no-static , incluyendo los miembros que se
refieren a otros objetos.

4.6.

Conectividad a Base de Datos (JDBC)

A continuacion, se presentan los diferentes conceptos implicados en el establecimiento y control de una conexion con bases de datos dentro de una aplicacion Java usando Java Database Connection (JDBC).
Para que Java pueda conectarse a una Base de datos, se necesita un driver JDBC para el RDBMS usado. Como
la API JDBC esta predominantemente compuesta por interfaces, se necesita obtener una implementacion de un
driver JDBC real, para poder conectarse con una base de datos usando JDBC. Si la base de datos no permite el
uso de JDBC, siempre se puede usar el driver puente JDBC-ODBC para conectarse con cualquier base de datos (o
fuente de datos) que soporte el protocolo ODBC.

4.6.1.

Introduccion a los Drivers JDBC

Una inspeccion casual del API JDBC muestra rapidamente la dominacion de las interfaces dentro de la API,
lo que podra llevar al usuario a preguntarse donde se realiza el trabajo. Realmente esta es solo una aproximacion
que tocan los desarrolladores JDBC, porque la implementacion real es la proporcionada por los vendedores de
Drivers JDBC, que a su vez proporcionan las clases que implementan las interfaces necesarias. Con todos los
drivers disponibles, elegir uno puede ser dficil. Afortunadamente, Sun Microsystems mantiene una base de datos
con mas de 150 drivers JDBC de una amplia variedad de vendedores. Esta debera ser la primera parada despues
de seleccionar una base de datos. Ver http://industry.java.sun.com/products/jdbc/drivers.
Desde una perspectiva de programacion, hay dos clases principales responsables para el establecimiento de una
conexion con una base de datos. La primera clase es DriverManager, que es una de las clases que realmente
proprociona la API JDBC. DriverManager, es responsable de manejar un almacen de drivers registrados, esencialmente abstrayendo los detalles del uso de un driver, para que el programador no tenga que tratar con ellos
directamente. La segunda clase es la real del Driver JDBC. Estas son proporcionadas por vendedores independientes. La clase Driver de JDBC, es la responsable de establecer la conexion y de manejar todas las comunicaciones
con la base de datos. Los drivers JDBC vienen en cuatro tipos diferentes:
Drivers de Tipo 1
Los drivers del tipo uno tienen algo en comun: todos usan el puente JDBC-ODBC, que esta incluido como parte
estandar del JDK. Los drivers del tipo uno son diferentes al driver ODBC (Open DataBase Connectivity) adjunto
al puente JDBC-ODBC. Para conectar con una fuente de datos diferente, simplemente se tiene que registrar una
fuente de datos ODBC diferente, usando el Administrador ODBC, al nombre de la fuente de datos apropiada.
Como ODBC se ha estado utilizando desde hace bastante tiempo (mas que el lenguaje Java), los drivers ODBC son
abundantes. Esto hace de este tipo de drivers una buena eleccion para aprender a conectar programas Java a bases
de datos. De hecho, hay drivers ODBC que permiten asignar fuentes de datos ODBC a una aplicacion Microsoft
Excel o archivos de texto plano. Sin embargo, el nivel extra de indireccion, puede resultar en una perdida de
rendimiento, ya que el JDBC es transferido dentro de ODBC, que luego es transferido en el protocolo especfico
de la base de datos.
Otro problema potencial de los drivers del tipo uno, es su utilizacion en aplicaciones distribuidas. Como el propio
puente no soporta comunicacion distribuida, la u nica forma de que los drivers del tipo uno puedan trabajar a traves
de la red es, si el propio driver ODBC soporta interaccion remota. Para drivers ODBC sencillos, esta no es una
opcion, y mientras que las grandes bases de datos tienen drivers ODBC que pueden trabajar de forma remota, no
pueden competir con el mejor rendimiento de los drivers JDBC puro Java.
80

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
El nombre de clase para el driver puente JDBC-ODBC es sun.jdbc.odbc.JdbcOdbcDriver y la URL JDBC
toma la forma jdbc:odbc:dsn, donde dsn es el Data Source Name (nombre de la fuente de datos) usado para
registrar la base de datos con el Administrador ODBC.
Drivers de Tipo 2
Los drivers del tipo dos tambien son conocidos como drivers Java parciales, porque traducen directamente
el API JDBC en un API especfico de la base de datos. El computador que esta ejecutando la JVM debe tener
las libreras cliente apropiadas para la base de datos, que podran incluir codigo binario nativo, instalado y ejecutandose. Para una aplicacion distribuida, este requerimietno puede introducir problemas extra con las licencias,
as como posibles pesadillas con los problemas de distribucion de codigo. Por ejemplo, usar un modelo del tipo
dos, restringe a los desarrolladores a utilizar plataformas y sistemas operativos soportados por la librera cliente
de la base de datos.
Sin embargo, este modelo puede funcionar eficientemente, cuando la base cliente esta fuertemente controlada.
Esto ocurre tpicamente en LANs corporativas.
Drivers de Tipo 3
Los dos u ltimos tipos de drivers, son drivers puro Java. El beneficio de los drivers puro Java es su facil despliegue en entornos altamente distribuidos.
Los drivers del tipo tres son drivers puro Java que transforman el API JDBC en un protocolo independiente de
la base de datos. El driver JDBC no comunica directamente con la base de datos; comunica con un servidor de
capa media, que a su vez comunica con la base de datos. Este nivel extra de indireccion proporciona flexibilidad,
ya que se puede acceder a diferentes bases de datos desde el mismo codigo, porque el servidor de la capa media
oculta los detalles a la aplicacion Java. Para cambiar a una base de datos diferente, solo se necesita cambiar los
parametros en el servidor de la capa media. (Un punto a tener en cuenta es que, el formato de la base de datos a la
que se esta accediendo, debe ser soportado por el servidor de la capa media).
El lado negativo de los drivers del tipo tres, es que el nivel extra de indireccion puede perjudicar el rendimiento
general del sistema. Por otro lado, si una aplicacion necesita interactuar con una variedad de formatos de bases de
datos, un driver del tipo tres, es una aproximacion adecuada debido al hecho de que se usa el mismo driver JDBC,
sin importar la base de datos subyacente.
Drivers de Tipo 4
Los drivers del tipo cuatro, son drivers puro Java que se comunican directamente con la base de datos. Muchos
programadores consideran e ste el mejor tipo de driver, ya que normalmente proporciona un rendimiento o ptimo y
permite al desarrollador utilizar las funcionalidades especficas de la base de datos. Por supuesto este acoplamiento
puede reducir la flexibilidad, especialmente si se necesita cambiar la base de datos subyacente en una aplicacion.
Este tipo de driver se usa frecuentemente en applets y otras aplicaciones altamente distribuidas.

4.6.2.

Registrar un Driver JDBC: La Clase DriverManager

El primer paso en el proceso de crear una conexion entre una aplicacion Java y una base de datos es el registro
de un driver JDBC con la JVM en la que se esta ejecutando la aplicacion Java. En el mecanismo de conexion
tradicional, la conexion y toda la comunicacion con la base de datos, es controlada por un objeto DriverManager.
Para establecer una conexion, se debe registrar un driver JDBC adecuado para la base de datos objetivo, con
el objeto DriverManager. La especificacion JDBC, dice que los drivers JDBC se registran automaticamente a
s mismos con el objeto DriverManager cuando se cargan en la JVM.
Registrar un driver es tan simple, como cargar la clase del driver en la JVM, lo que puede hacerse de muchas
maneras. Una forma es, con el ClassLoader: Class.forName(), es la mas conocida y la que se usara en este
documento. Ejemplo:
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

81

4.6. CONECTIVIDAD A BASE DE DATOS (JDBC)


try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
} catch (ClassNotFoundException e) {
System.err.println(e.getMessage());
}
Esta alternativa debera funcionar bien en todas las JVMs. Es necesario manejar flujos alternativos, ya que
Class.forName() puede lanzar una excepcion ClassNotFoundException, por eso se debe envolver el codigo
de registro en un manejador de excepcion apropiado.

4.6.3.

La Conexion: La Clase Connection y URLs de Conexion

Una vez que un Driver JDBC se ha registrado con el DriverManager, puede usarse para establecer una
conexion a una base de datos. Pero como selecciona DriverManager el driver correcto, dado que puede haberse
registrado mas de un driver? (Ademas, una sola JVM puede soportar multiples aplicaciones concurrentes, que
podran conectarse con diferentes bases de datos con diferentes drivers). La tecnica es bastante simple: cada driver
JDBC usa una URL JDBC especfica (que tiene un formato parecido al de una direccion Web) como un significado
de auto-identificacion. El formato de la URL es especfico del driver JDBC. Pero todos incluyen un localizador
especfico del driver para especificar de forma u nica la base de datos con la que una aplicacion quiere interactuar.
Dependiendo del tipo de driver, este localizador incluye un nombre de host, un puerto, y un nombre de sistema de
base de datos.
Cuando se encuentra con una URL especfica, el DriverManager itera sobre la coleccion de drivers registrados
hasta que uno de ellos reconoce la URL especficada. Si no se encuentra ningun driver adecuado, se lanza una
SQLException. La siguiente lista presenta varios ejemplos especficos de URLs JDBC reales:
jdbc:odbc:dsn
jdbc:oracle:thin:@localhost:1521:database
jdbc:db2:database
Muchos drivers, incluyendo el driver puente JDBC-ODBC, acepta parametros adicionales al final de la URL como
un nombre de usuario y una password.
El metodo para obtener una conexion a una base de datos, dando una URL JDBC especfica, es llamar a
getConnection() sobre el objeto DriverManager. Este metodo tiene varias formas:
DriverManager.getConnection(url);
DriverManager.getConnection(url, username, password);
DriverManager.getConnection(url, dbproperties);
Aqu, url es un objeto String que es la URL JDBC, username y password son objetos String que representan
el nombre de usuario y la password que la aplicacion JDBC debera usar para conectarse con la fuente de datos; y
dbproperties es un objeto Properties de Java, que encapsula todos los parametros (posiblemente incluyendo
nombre de usuario y la password) que requiere un driver JDBC para hacer una conexion con e xito.
As, se puede crear una conexion concreta a la Base de Datos con el siguiente codigo:
Connection con = null ;
try {
con = DriverManager.getConnection("jdbc:odbc:dsn");
} catch (SQLException e) {
System.err.println(e.getMessage());
}
El metodo getConnection() puede lanzar una SQLException, si se produce algun error al conectarse a la base
de datos.
82

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION

4.6.4.

Ejecutar una Instruccion SQL: La Clase Statement

Un objeto Statement es el que enva sentencias SQL al controlador de la base de datos. Simplemente, se crea
un objeto Statement y se ejecuta, suministrando el metodo SQL apropiado con la sentencia SQL que se quiere
enviar. Para una sentencia que retorne registros, el metodo a ejecutar es executeQuery(). Para sentencias que
crean o modifican estructuras, el metodo a utilizar es executeUpdate().
Se toma un ejemplar de una conexion activa para crear un objeto Statement. En el siguiente ejemplo, se utiliza
el objeto con, de la seccion anterior, para crear el objeto stmt.
Statement stmt = null ;
try {
stmt = con.createStatement();
} catch (SQLException e) {
System.err.println(e.getMessage());
}
En este momento stmt existe, pero no tiene ninguna sentencia SQL que pasarle al controlador de la base de datos.
Se necesita ejecutar un metodo que ejecute codigo SQL. Por ejemplo, en el siguiente fragmento de codigo, se
utiliza executeUpdate() con una sentencia SQL, que crea una nueva tabla:
try {
stmt.executeUpdate("CREATE TABLE COFFEES "+
"(COF NAME VARCHAR(32), SUP ID INTEGER, PRICE FLOAT, "+
"SALES INTEGER, TOTAL INTEGER)");
} catch (SQLException e) {
System.err.println(e.getMessage());
}
Se utilizo el metodo executeUpdate() porque la sentencia SQL es una sentencia DDL (Data Definition Language). Las sentencias que crean, modifican o eliminan estructuras son todas ejemplos de sentencias DDL y se
ejecutan con el metodo executeUpdate(). Como se podra esperar de su nombre, el metodo executeUpdate()
tambien se utiliza para ejecutar sentencias SQL que actualizan registros en una tabla, como INSERT y UPDATE .
El siguiente codigo inserta una fila de datos. Se utilizara el mismo objeto stmt que se creo en el ejemplo anterior.
Observe que se utilizan comillas simples alrededor del nombre del cafe, porque esta anidado dentro de las comillas dobles. Para la mayora de los controladores de bases de datos, la regla general es alternar comillas dobles y
simples.
try {
stmt.executeUpdate(
"INSERT INTO COFFEES "+
"VALUES (Colombian, 101, 7.99, 0, 0)");
} catch (SQLException e) {
System.err.println(e.getMessage());
}
Si no se desea seguir usando un objeto Statement, es necesario ejecutar el metodo close() para liberar los
recursos.

4.6.5.

Obtencion de Resultados: La Interfaz ResultSet

El metodo mas utilizado para ejecutar sentencias SQL es executeQuery(). Este metodo se utiliza, principalmente para ejecutar sentencias SELECT , que comprenden la amplia mayora de las sentencias SQL.
JDBC devuelve los resultados en un objeto ResultSet, por eso se necesita declarar un ejemplar de la clase
ResultSet para contener los resultados. El siguiente codigo presenta el objeto ResultSet, al que se le asigna el
resultado de una consulta.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

83

4.6. CONECTIVIDAD A BASE DE DATOS (JDBC)


ResultSet rs = null ;
try {
rs = stmt.executeQuery("SELECT COF NAME, PRICE FROM COFFEES");
} catch (SQLException e) {
System.err.println(e.getMessage());
}
La variable rs, que es un ejemplar de ResultSet, contiene las filas de cafes y sus precios. Para acceder a los
nombres y los precios, se recorren las filas y se recuperan los valores de acuerdo con sus tipos. El metodo next()
mueve un cursor a la siguiente fila y hace que esa sea la actual. Como el cursor inicialmente se posiciona justo
antes de la primera fila de un objeto ResultSet, primero se debe llamar al metodo next() para mover el cursor
a la primera fila y convertirla en la fila actual. Sucesivas invocaciones del metodo next(), moveran el cursor de
fila en fila.
La interfaz ResultSet provee de una serie de metodos getXXX() del tipo apropiado, que se utilizan para recuperar el valor de cada columna. Por ejemplo, la primera columna de cada fila de rs es COF NAME, que almacena
un valor del tipo VARCHAR de SQL. El metodo para recuperar un valor VARCHAR es getString(). La segunda
columna de cada fila almacena un valor del tipo FLOAT de SQL, y el metodo para recuperar valores de ese tipo
es getFloat(). El siguiente codigo accede a los valores almacenados en la fila actual de rs, e imprime una lnea
con el nombre seguido por tres espacios y el precio. Cada vez que se llama al metodo next(), la siguiente fila se
convierte en la actual, y el bucle continua hasta que no haya mas filas por visitar en rs.
String query = "SELECT COF NAME, PRICE FROM COFFEES";
try {
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String s = rs.getString("COF NAME");
float n = rs.getFloat("PRICE");
System.out.println(s + "
" + n);
}
} catch (SQLException e) {
System.err.println(e.getMessage());
}
La salida se parecera a esto.
Colombian
7.99
8.99
French Roast
Espresso
9.99
8.99
Colombian Decaf
9.99
French Roast Decaf
El metodo getString() es invocado sobre el objeto rs, por eso getString() recuperara el valor almacenado
en la columna COF NAME de la fila actual de rs. El valor recuperado por getString() se ha convertido desde un
VARCHAR de SQL a un String de Java y se ha asignado al objeto s.
La situacion es similar con el metodo getFloat() excepto en que recupera el valor almacenado en la columna
PRICE, que es un FLOAT de SQL, y lo convierte a un float de Java antes de asignarlo a la variable n.
JDBC ofrece dos formas para identificar la columna de la que un metodo getXXX() obtiene un valor. Una forma
es dar el nombre de la columna, como se ha hecho anteriormente. La segunda forma, es dar el ndice de la columna
(el numero de columna), con un 1 significando la primera columna, un 2 para la segunda, etc. Si se utilizara el
numero de columna, en vez del nombre de columna el codigo anterior quedara as:
String s = rs.getString(1);
float n = rs.getFloat(2);
84

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
Tener en cuenta que el numero de columna se refiere al numero de columna en la hoja de resultados, y no en la
tabla original.
En suma, JDBC permite utilizar tanto el nombre como el numero de la columna como argumento a un metodo
getXXX(). Utilizar el numero de columna es un poco mas eficiente, y hay algunos casos donde es necesario
utilizarlo.
La siguiente tabla muestra que metodo getXXX() se recomienda usar para cada tipo de dato SQL.
Tipo de dato SQL
TINYINT
SMALLINT
INTEGER
BIGINT
REAL
FLOAT
DOUBLE
DECIMAL
NUMERIC
BIT
CHAR
LONGCARCHAR
BINARY
VARBINARY
LONGVARBINARY
DATE
TIME
TIMESTAMP
VARCHAR

Metodo Recomendado
getByte()
getShort()
getInt()
getLong()
getFloat()
getDouble()
getDouble()
getBigDecimal()
getBigDecimal()
getBoolean()
getString()
getString()
getAsciiStream()
getBytes()
getBytes()
getDate()
getTime()
getTimeStamp()
getString()

Si no se desea seguir usando un objeto ResultSet, es necesario ejecutar el metodo close() para liberar los
recursos.

4.6.6.

Manejo de Transacciones

Hay veces en que no se quiere que una sentencia tenga efecto, a menos que otra tambien suceda. Por ejemplo,
cuando se actualiza la cantidad de cafe vendida semanalmente, tambien se deseara actualizar la cantidad total
vendida hasta la fecha. Sin embargo, no se deseara actualizar una, sin actualizar la otra; de otro modo, los datos
seran inconsistentes. La forma para asegurarse que ocurren las dos acciones o que no ocurre ninguna, es utilizar
una transaccion. Una transaccion es un conjunto de una o mas sentencias que se ejecutan como una unidad, por
eso, o se ejecutan todas o no se ejecuta ninguna.
Cuando se crea una conexion, esta en modo de auto-entrega. Esto significa que cada sentencia SQL individual es
tratada como una transaccion y sera automaticamente entregada justo despues de ser ejecutada.
La forma de permitir que dos o mas sentencia sean agrupadas en una transaccion, es desactivar el modo de autoentrega. Esto se demuestra en el siguiente codigo, donde con es una conexion activa.
con.setAutoCommit(false );
Una vez que se ha desactivado la auto-entrega, no se entregara ninguna sentencia SQL hasta que se llame explcitamente al metodo commit(). Todas las sentencias ejecutadas despues de la llamada al metodo
setAutoCommit(false ) y antes de la llamada al metodo commit(), seran incluidas en la transaccion actual y
seran entregadas juntas como una unidad. El siguiente codigo, en el que con es una conexion activa, ilustra una
transaccion.
con.setAutoCommit(false );
Statement updateSales = con.createStatement();
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

85

4.6. CONECTIVIDAD A BASE DE DATOS (JDBC)


updateSales.executeUpdate("UPDATE COFFEES SET SALES = 50 "+
"WHERE COF NAME LIKE Colombian");
Statement updateTotal = con.createStatement("UPDATE COFFEES "+
"SET TOTAL = TOTAL + 50 WHERE COF NAME LIKE Colombian");
updateTotal.executeUpdate();
con.commit();
con.setAutoCommit(true );
En este ejemplo, el modo auto-entrega se desactiva para la conexion con, lo que significa que las dos sentencias
updateSales y updateTotal seran entregadas juntas cuando se llame al metodo commit(). Siempre que se
llame al metodo commit() (bien automaticamente, cuando esta activado el modo auto-commit o explcitamente
cuando esta desactivado), todos los cambios resultantes de las sentencias de la transaccion seran permanentes. En
este caso, significa que las columnas SALES y TOTAL para el cafe Colombian han sido cambiadas a 50 (si TOTAL
ha sido 0 anteriormente) y mantendra este valor hasta que se cambie con otra sentencia de actualizacion.
La lnea final del ejemplo anterior, activa el modo auto-commit, lo que significa que cada sentencia sera de nuevo
entregada automaticamente cuando este completa. Se vuelve, por lo tanto al estado por defecto, en el que no se
tiene que llamar al metodo commit(). Es conveniente desactivar el modo auto-commit, solo mientras se quiera
estar en modo de transaccion. De esta forma, se evita bloquear la base de datos durante varias sentencias.
Ademas de agrupar las sentencias para ejecutarlas como una unidad, las transaciones pueden ayudar a preservar la
integridad de los datos de una tabla. Por ejemplo, suponga que un empleado se ha propuesto introducir los nuevos
precios de los cafes en la tabla COFFEES, pero se retrasa algunos das. Mientras tanto, los precios han subido, y
hoy el propietario esta introduciendo los nuevos precios. Finalmente, el empleado empieza a introducir los precios,
ahora desfasados, al mismo tiempo que el propietario intenta actualizar la tabla. Despues de insertar los precios
desfasados, el empleado se da cuenta de que ya no son validos y llama el metodo rollback() de la conexion
para deshacer sus efectos. El metodo rollback() aborta la transaccion y restaura los valores que haba antes de
intentar la actualziacion. Al mismo tiempo, el propietario esta ejecutando una sentencia SELECT e imprime los
nuevos precios. En esta situacion, es posible que el propietario imprima los precios que mas tarde seran devueltos
a sus valores anteriores, haciendo que los precios impresos sean incorrectos.
Esta clase de situaciones puede evitarse utilizando transaciones. Si un controlador de base de datos soporta transaciones, y casi todos lo hacen, proporcionara algun nivel de proteccion contra conflictos, que pueden surgir cuando
dos usuarios acceden a los datos a la misma vez.
Para evitar conflictos durante una transaccion, un controlador de base de datos utiliza bloqueos, mecanismos para
bloquear el acceso de otros a los datos que estan siendo accedidos por una transaccion. Una vez activado, el bloqueo permanece hasta que la transaccion sea entregada o anulada. Por ejemplo, un controlador de base de datos
podra bloquear una fila de una tabla, hasta que la actualizacion se haya entregado. El efecto de este bloqueo es
evitar que un usuario obtenga una lectura sucia, esto es, que lea un valor antes de que sea permanente (acceder a
un valor actualizado que no haya sido entregado, se considera una lectura sucia, porque es posible que el valor sea
devuelto a su valor anterior).
La forma en que se configuran los bloqueos, esta determinado por lo que se llama, nivel de aislamiento de transaccion, que puede variar desde no soportar transaciones en absoluto, a soportar todas las transaciones que fuerzan
unas reglas de acceso estrictas.
Un ejemplo de nivel de aislamiento de transaccion, es TRANSACTION READ COMMITTED, que no permite que se
acceda a un valor hasta que haya sido entregado. En otras palabras, si el nivel de aislamiento de transaccion se
selecciona a TRANSACTION READ COMMITTED, el controlador de la base de datos no permitira que ocurran lecturas
sucias. La interfaz Connection incluye cinco valores que representan los niveles de aislamiento de transaccion
que se pueden utilizar en JDBC.
Normalmente, no se necesita cambiar el nivel de aislamiento de transaccion; se puede utilizar el valor por defecto
del controlador. JDBC permite averiguar el nivel de aislamiento de transaccion del controlador de la base de datos
(utilizando el metodo getTransactionIsolation()) y permite configurarlo a otro nivel (utilizando el metodo
setTransactionIsolation()). Sin embargo, hay que tener en cuenta, que aunque JDBC permite seleccionar
un nivel de aislamiento, hacer esto no tendra ningun efecto, a no ser que el driver del controlador de la base de
datos lo soporte.
86

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION

4.7.

Hilos y Sincronizacion

Los procesadores y los sistemas operativos modernos permiten procesamiento multitarea, es decir, la realizacion simultanea de dos o mas actividades (al menos aparentemente). En la realidad, un computador con una sola
CPU no puede realizar dos actividades a la vez. Sin embargo, los sistemas operativos actuales son capaces de
ejecutar varios programas simultaneamente aunque solo se disponga de una CPU: reparten el tiempo entre dos
(o mas) actividades, o bien utilizan los tiempos muertos de una actividad (por ejemplo, operaciones de lectura de
datos desde el teclado) para trabajar en la otra. En computadores con dos o mas procesadores la multitarea es real,
ya que cada procesador puede ejecutar un hilo o thread diferente.
Un proceso es un programa ejecutandose de forma independiente y con un espacio propio de memoria. Un sistema operativo multitarea es capaz de ejecutar mas de un proceso simultaneamente. Un thread o hilo es un flujo
secuencial simple dentro de un proceso. Un u nico proceso puede tener varios hilos ejecutandose. Por ejemplo,
el programa Netscape puede ser un proceso, mientras que cada una de las ventanas que se pueden tener abiertas
simultaneamente mostrando paginas HTML, estara formada por al menos un hilo.
Un sistema multitarea da realmente la impresion de estar haciendo varias cosas a la vez, y eso es una gran ventaja
para el usuario. Sin el uso de threads, hay tareas que son practicamente imposibles de ejecutar, particularmente las
que tienen tiempos de espera importantes entre etapas.
Los threads o hilos permiten organizar los recursos del computador de forma que pueda haber varios programas
actuando en paralelo. Un hilo puede realizar cualquier tarea que pueda realizar un programa normal y corriente.
Los threads pueden ser daemon o no daemon. Son daemon aquellos hilos que realizan en background (en un segundo plano) servicios generales, esto es, tareas que no forman parte de la esencia de un programa y que se estan
ejecutando mientras no finalice una aplicacion. Un thread daemon podra ser, por ejemplo aquel que esta comprobando permanentemente si el usuario pulsa un boton. Un programa Java finaliza cuando solo quedan corriendo
threads de tipo daemon. Por defecto, y si no se indica lo contrario, los threads son del tipo no daemon.

4.7.1.

Creacion de Hilos

En Java hay dos formas de crear nuevos threads. La primera de ellas consiste en crear una nueva clase que
herede de la clase java.lang.Thread y sobrecargar el metodo run() de dicha clase. El segundo metodo, consiste
en declarar una clase que implemente la interfaz java.lang.Runnable, la cual declarara el metodo run();
posteriormente se crea un objeto de tipo Thread, pasandole como argumento al constructor, el objeto creado de la
nueva clase (la que implementa la interfaz Runnable).
A continuacion se presentan dos ejemplos de creacion de threads con cada uno de los dos metodos citados.
Creacion de Threads especializando la Clase Thread
Considerese el siguiente ejemplo de declaracion de una nueva clase:
public class SimpleThread extends Thread {
// constructor
public SimpleThread(String str) {
super(str);
}
// redefinici
on del m
etodo run()
public void run() {
for (int i=0;i<10;i++)
System.out.println("Este es el thread : "+ getName());
}
}
En este caso, se ha creado la clase SimpleThread, que hereda de Thread. En su constructor se utiliza un string
(opcional) para poner nombre al nuevo thread creado, y mediante super() se llama al constructor de la super-clase
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

87


4.7. HILOS Y SINCRONIZACION
Thread. Asimismo, se redefine el metodo run(), que define la principal actividad del thread, para que escriba 10
veces el nombre del thread creado.
Para poner en marcha este nuevo thread, se debe crear un objeto de la clase SimpleThread, y llamar al metodo
start(),heredado de la super-clase Thread, que se encarga de llamar a run(). Por ejemplo:
SimpleThread miThread = new SimpleThread("Hilo de prueba");
miThread.start();
Creacion de Threads implementando la Interfaz Runnable
Esta segunda forma tambien requiere que se defina el metodo run(), pero ademas es necesario crear un objeto
de la clase Thread para lanzar la ejecucion del nuevo hilo. Al constructor de la clase Thread se le debe pasar una
referencia del objeto de la clase que implementa la interface Runnable.
Posteriormente, cuando se ejecute el metodo start() del thread, este llamara al metodo run() definido en
la nueva clase. A continuacion, se muestra el mismo estilo de clase que en el ejemplo anterior, implementada
mediante la interface Runnable:
public class SimpleRunnable implements Runnable {
// se crea un nombre
String nameThread;
// constructor
public SimpleRunnable(String str) {
nameThread = str;
}
// definici
on del m
etodo run()
public void run() {
for (int i=0;i<10;i++)
System.out.println("Este es el thread : "+ nameThread);
}
}
El siguiente codigo crea un nuevo thread y lo ejecuta por este segundo procedimiento:
SimpleRunnable p = new SimpleRunnable("Hilo de prueba");
// se crea un objeto de la clase Thread pas
andole el objeto Runnable como argumento
Thread miThread = new Thread(p);
// se arranca el objeto de la clase Thread
miThread.start();
Este segundo metodo cobra especial interes con applets, ya que cualquier applet debe heredar de la clase
java.applet.Applet, y por lo tanto ya no puede heredar de Thread.
La eleccion de una u otra forma derivar de Thread o implementar Runnable depende del tipo de clase que
se vaya a crear. As, si la clase a utilizar ya hereda de otra clase (por ejemplo un applet), no quedara mas remedio
que implementar Runnable, aunque normalmente es mas sencillo heredar de Thread.

4.7.2.

Ciclo de Vida de un Thread

En la seccion anterior se ha visto como crear nuevos objetos que permiten incorporar en un programa la
posibilidad de realizar varias tareas simultaneamente. Un thread puede presentar cuatro estados distintos:
Nuevo (New): El thread ha sido creado pero no inicializado, es decir, no se ha ejecutado todava el metodo
start(). Se producira un mensaje de error (IllegalThreadStateException) si se intenta ejecutar cualquier metodo de la clase Thread distinto de start().
88

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
Ejecutable (Runnable): El thread puede estar ejecutandose, siempre y cuando se le haya asignado un determinado tiempo de CPU. En la practica, puede no estar siendo ejecutado en un instante determinado, en beneficio
de otro thread.
Bloqueado (Blocked o Not Runnable): El thread podra estar ejecutandose, pero alguna actividad interna suya
se lo impide, como por ejemplo, una espera producida por una operacion de escritura o lectura de datos por
teclado(E/S). Si un thread esta en este estado, no se le asigna tiempo de CPU.
Muerto (Dead): La forma habitual de que un thread muera es finalizando el metodo run(). Tambien puede
llamarse al metodo stop() de la clase Thread, aunque dicho metodo es considerado peligroso y no se debe
utilizar.
A continuacion se explicaran con mayor detenimiento los puntos anteriores.
Ejecucion de un Nuevo thread
La creacion de un nuevo thread no implica necesariamente que se empiece a ejecutar codigo. Hace falta
iniciarlo con el metodo start(), ya que de otro modo, cuando se intenta ejecutar cualquier metodo del thread
distinto del metodo start() se obtiene en tiempo de ejecucion el error IllegalThreadStateException.
El metodo start() se encarga de llamar al metodo run() de la clase Thread. Si el nuevo thread se ha creado
heredando de la clase Thread, la nueva clase debera redefinir el metodo run() heredado. En el caso de utilizar
una clase que implemente la interfaz Runnable, el metodo run() de la clase Thread se ocupa de llamar al metodo
run() de la nueva clase.
Una vez que el metodo start() ha sido llamado, se puede decir que el thread ya esta corriendo (running), lo cual
no quiere decir que se este ejecutando en todo momento, pues ese thread tiene que compartir el tiempo de CPU
con los demas threads que tambien esten corriendo.
Detener un Thread Temporalmente
El sistema operativo se ocupa de asignar tiempos de CPU a los distintos threads que se esten ejecutando
simultaneamente. Aun en el caso de disponer de un computador con mas de un procesador (2 o mas CPUs), el
numero de threads simultaneos suele siempre superar el numero de CPUs, por lo que se debe repartir el tiempo de
forma que parezca que todos los procesos corren a la vez (quizas mas lentamente), aun cuando solo unos pocos
pueden estar ejecutandose en un instante de tiempo.
Los tiempos de CPU que el sistema continuamente asigna a los distintos threads en estado runnable, se utilizan
en ejecutar el metodo run() de cada thread. Por diversos motivos, un thread puede en un determinado momento
renunciar voluntariamente a su tiempo de CPU y otorgarselo al sistema para que se lo asigne a otro thread. Esta
renuncia se realiza mediante el metodo yield().
Es importante que este metodo sea utilizado por las actividades que tienden a monopolizar la CPU. El metodo
yield() viene a indicar, que en ese momento no es muy importante para ese thread el ejecutarse continuamente,
y por lo tanto tener ocupada la CPU. En caso de que ningun thread este solicitando CPU para una actividad
intensiva, el sistema volvera casi de inmediato a asignar nuevo tiempo al thread que fue generoso con los demas.
Por ejemplo, en un Pentium II 400 Mhz es posible llegar a mas de medio millon de llamadas por segundo al
metodo yield(), dentro del metodo run(), lo que significa que llamar al metodo yield() apenas detiene al
thread, sino que solo ofrece el control de la CPU para que el sistema decida si hay alguna otra tarea que tenga
mayor prioridad.
Si lo que se desea es parar o bloquear temporalmente un thread (pasar al estado Bloqueado), existen varias formas
de hacerlo:
Ejecutando el metodo sleep() de la clase Thread. Esto detiene el thread un tiempo preestablecido. Generalmente, el metodo sleep() se llama desde el metodo run().
Ejecutando el metodo wait() heredado de la clase Object, a la espera de que suceda algo que es necesario para poder continuar. El thread volvera nuevamente a la situacion de runnable, mediante los metodos
notify() o notifyAll(), que se deberan ejecutar cuando cesa la condicion que tiene detenido al thread.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

89


4.7. HILOS Y SINCRONIZACION
Cuando el thread esta esperando para realizar operaciones de Entrada/Salida(E/S).
Cuando el thread esta tratando de llamar a un metodo synchronized de un objeto, y dicho objeto esta bloqueado por otro thread.
Un thread pasa automaticamente del estado Bloqueado a Corriendo cuando cesa alguna de las condiciones anteriores o cuando se llama a notify() o notifyAll().
La clase Thread dispone tambien de un metodo stop(), pero no se debe utilizar, ya que puede provocar bloqueos
del programa(deadlock). Hay una u ltima posibilidad para detener un thread, que consiste en ejecutar el metodo
suspend(). El thread volvera a ser ejecutable de nuevo ejecutando el metodo resume(). Esta u ltima forma tampoco se aconseja, por razones similares a la utilizacion del metodo stop().
El metodo sleep() de la clase Thread recibe como argumento el tiempo en milisegundos que ha de permanecer detenido. Adicionalmente, se puede incluir un numero entero con un tiempo adicional en nanosegundos. Las
declaraciones de estos metodos son las siguientes:
static void sleep(long millis) throws InterruptedException
static void sleep(long millis, int nanosecons) throws InterruptedException
Considerese el siguiente ejemplo:
System.out.println("Contador de segundos");
int count=0;
public void run() {
try {
sleep(1000);
System.out.println(count++);
} catch (InterruptedException e) {}
}
Se observa que el metodo sleep() puede lanzar una InterruptedException que ha de ser capturada. As, se ha
hecho en este ejemplo, aunque luego no se gestiona esa excepcion. La forma preferible de detener temporalmente
un thread, es la utilizacion conjunta de los metodos wait() y notifyAll(). La principal ventaja del metodo
wait() frente a los metodos anteriormente descritos, es que libera el bloqueo del objeto, por lo que el resto de
threads que se encuentran esperando para actuar sobre dicho objeto, pueden llamar a sus metodos. Hay dos formas
de llamar a wait():
Indicando el tiempo maximo que debe estar detenido (en milisegundos y con la opcion de indicar tambien
nanosegundos), de forma analoga a sleep(). A diferencia del metodo sleep(), que simplemente detiene
el thread el tiempo indicado, el metodo wait() establece el tiempo maximo que debe estar detenido. Si
en ese plazo se ejecutan los metodos notify() o notifyAll() que indican la liberacion de los objetos
bloqueados, el thread continuara sin esperar a concluir el tiempo indicado. Las dos declaraciones del metodo
wait() son como siguen:
final void wait(long timeout) throws InterruptedException
final void wait(long timeout, int nanos) throws InterruptedException
Sin argumentos, en cuyo caso el thread permanece detenido hasta que sea reinicializado explcitamente
mediante los metodos notify() o notifyAll().
final void wait() throws InterruptedException
Las llamadas a los metodos wait() y notify() han de estar incluidas en un metodo synchronized , ya
que de otra forma se obtendra una excepcion del tipo IllegalMonitorStateException, en tiempo de
ejecucion. El uso tpico de wait(), es el de esperar a que se cumpla alguna determinada condicion, ajena al
propio thread. Cuando esta se cumpla, se utiliza el metodo notifyAll() para avisar a los distintos threads
que pueden utilizar el objeto.
90

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
Finalizar un Thread
Un thread finaliza cuando el metodo run() devuelve el control, por haber terminado lo que tena que hacer
(por ejemplo, un bucle for que se ejecuta un numero determinado de veces) o por haberse dejado de cumplir una
condicion (por ejemplo, por un bucle while en el metodo run()).
Para saber si un thread esta vivo o no, es u til el metodo isAlive() de la clase Thread, que devuelve true si
el thread ha sido inicializado y no detenido, y false si el thread es todava nuevo(no ha sido inicializado) o ha
finalizado.

4.7.3.

Sincronizacion

La sincronizacion nace de la necesidad de evitar que dos o mas threads traten de acceder a los mismos recursos
al mismo tiempo. As, por ejemplo, si un thread tratara de escribir en un archivo, y otro thread estuviera al mismo
tiempo tratando de borrarlo, se producira una situacion no deseada. Otro caso en el que hay que sincronizar
threads, se produce cuando un thread debe esperar a que esten preparados los datos que le debe suministrar otro
thread. Para solucionar estos tipos de problemas es importante poder sincronizar los distintos threads.
Las secciones de codigo de un programa que acceden a un mismo recurso(un mismo objeto de una clase, un
archivo del disco, etc.) desde dos threads distintos, se denominan secciones crticas. Para sincronizar dos o mas
threads, hay que utilizar el modificador synchronized en aquellos metodos del objeto-recurso con los que
puedan producirse situaciones conflictivas. De esta forma, Java bloquea(asocia un bloqueo o lock) el recurso
sincronizado. Por ejemplo:
public synchronized void metodoSincronizado() {
// acceder, por ejemplo, a las variables de un objeto
...
}
La sincronizacion previene las interferencias solamente sobre un tipo de recurso: la memoria reservada para un
objeto. Cuando se prevea que unas determinadas variables de una clase pueden tener problemas de sincronizacion,
se deberan declarar como private (o protected ). De esta forma, solo podran estar accesibles a traves de
metodos de la clase, que deberan estar sincronizados.
Es importante tener en cuenta que si se sincronizan algunos metodos de un objeto pero otros no, el programa
puede no funcionar correctamente. La razon, es que los metodos no sincronizados pueden acceder libremente a
las variables miembro, ignorando el bloqueo del objeto.
Solo los metodos sincronizados comprueban si un objeto esta bloqueado. Por lo tanto, todos los metodos que
accedan a un recurso compartido deben ser declarados synchronized . De esta forma, si algun metodo accede a
un determinado recurso, Java bloquea dicho recurso, de forma que el resto de threads no puedan acceder al mismo
hasta que el primero en acceder termine de realizar su tarea.
Bloquear un recurso u objeto significa que sobre ese objeto no pueden actuar simultaneamente dos metodos sincronizados.
Existen dos niveles de bloqueo de un recurso. El primero, es a nivel de objetos, mientras que el segundo es a nivel
de clases. El primero se consigue declarando todos los metodos de una clase como synchronized . Cuando
se ejecuta un metodo synchronized sobre un objeto concreto, el sistema bloquea dicho objeto, de forma que
si otro thread intenta ejecutar algun metodo sincronizado de ese objeto, este segundo metodo se mantendra a la
espera hasta que finalice el anterior (y desbloquee por lo tanto el objeto). Si existen varios objetos de una misma
clase, como los bloqueos se producen a nivel de objeto, es posible tener distintos threads ejecutando metodos sobre
diversos objetos de una misma clase.
El bloqueo de recursos a nivel de clases se corresponde con los metodos y las variables de clase o estaticas. Si lo
que se desea es conseguir que un metodo bloquee simultaneamente una clase entera, es decir, todos los objetos
creados de una clase, es necesario declarar este metodo como synchronized static . Durante la ejecucion de
un metodo declarado de esta segunda forma, ningun metodo sincronizado tendra acceso a ningun objeto de la clase
bloqueada.
La sincronizacion puede ser problematica y generar errores. Un thread podra bloquear un determinado recurso de
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

91


4.7. HILOS Y SINCRONIZACION
forma indefinida, impidiendo que el resto de threads accedan al mismo.
Para evitar esto u ltimo, habra que utilizar la sincronizacion solo donde sea estrictamente necesario.
Es conveniente tener presente, que si dentro de un metodo sincronizado se utiliza el metodo sleep() de la clase
Thread, el objeto bloqueado permanecera en ese estado durante el tiempo indicado en el argumento de dicho metodo. Esto implica que otros threads no podran acceder a ese objeto durante ese tiempo, aunque en realidad no exista
peligro de simultaneidad, ya que durante ese tiempo el thread que mantiene bloqueado el objeto no realizara cambios. Para evitarlo es conveniente sustituir sleep() por el metodo wait() de la clase java.lang.Object heredado automaticamente por todas las clases. Cuando se llama al metodo wait() (siempre debe hacerse desde un
metodo o bloque synchronized ) se libera el bloqueo del objeto y por lo tanto es posible continuar utilizando
ese objeto a traves de metodos sincronizados. El metodo wait() detiene el thread hasta que se llame al metodo notify() o notifyAll() del objeto, o finalice el tiempo indicado como argumento del metodo wait(). El
metodo notify() lanza una senal indicando al sistema que puede activar uno de los threads que se encuentren
bloqueados esperando para acceder al objeto. El metodo notifyAll() lanza una senal a todos los threads que
estan esperando la liberacion del objeto.
Los metodos notify() y notifyAll() deben ser llamados desde el thread que tiene bloqueado el objeto para
activar el resto de threads que estan esperando la liberacion de un objeto. Un thread se convierte en propietario del
bloqueo de un objeto, ejecutando un metodo sincronizado del objeto.
Los bloqueos de tipo clase, se consiguen ejecutando un metodo de clase sincronizado (synchronized static
). Veanse las dos funciones siguientes: put() inserta un dato y get() lo recoge:
public synchronized int get() {
while (available == false ) {
try {
// Espera a que put() asigne el valor y lo comunique con notify()
wait();
} catch (InterruptedException e) { }
}
available = false ;
// notifica que el valor ha sido le
do
notifyAll();
// devuelve el valor
return contents;
}
public synchronized void put(int value) {
while (available == true ) {
try {
// Espera a que get() lea el valor disponible antes de darle otro
wait();
} catch (InterruptedException e) { }
}
// ofrece un nuevo valor y lo declara disponible
contents = value;
available = true ;
// notifica que el valor ha sido cambiado
notifyAll();
}
El bucle while de la funcion get() continua ejecutandose hasta que el metodo put() haya suministrado un
nuevo valor y lo indique con avalaible = true . En cada iteracion del while , la funcion wait() hace que el
hilo que ejecuta el metodo get() se detenga hasta que se produzca un mensaje de que algo ha sido cambiado (en
este caso, con el metodo notifyAll() ejecutado por put()). El metodo put() funciona de forma similar.
Existe tambien la posibilidad de sincronizar una parte del codigo de un metodo sin necesidad de mantener blo92

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CON LA API ESTANDAR

CAPITULO 4. PROGRAMACION
queado el objeto desde el comienzo hasta el final del metodo. Para ello se utiliza la palabra clave synchronized
indicando entre parentesis, el objeto que se desea sincronizar. Por ejemplo, si se desea sincronizar el propio thread
en una parte del metodo run(), el codigo podra ser:
public void run() {
while (true ) {
...
synchronized (this ) { // El objeto a sincronizar es el propio thread
... // C
odigo sincronizado
}
try {
sleep(500); // Se detiene el thread durante 0.5 segundos pero el objeto
// es accesible por otros threads al no estar sincronizado
} catch (InterruptedException e) {}
}
}
Un thread puede llamar a un metodo sincronizado de un objeto para el cual ya posee el bloqueo, volviendo a
adquirirlo. Por ejemplo:
public class VolverAAdquirir {
public synchronized void a() {
b();
System.out.println("Estoy en a()");
}
public synchronized void b() {
System.out.println("Estoy en b()");
}
}
El anterior ejemplo obtendra como resultado:
Estoy en b()
Estoy en a()
debido a que se ha podido acceder al objeto con el metodo b() al ser el thread que ejecuta el metodo a() propietario con anterioridad del bloqueo del objeto.
La sincronizacion es un proceso que lleva bastante tiempo a la CPU, luego se debe minimizar su uso, ya que el
programa sera mas lento.

4.7.4.

Prioridades

Con el fin de conseguir una correcta ejecucion de un programa, se establecen prioridades en los threads, de
forma que se produzca un reparto eficiente de los recursos disponibles. As, en un determinado momento, interesara que un determinado proceso acabe lo antes posible sus calculos, de forma que habra que otorgarle mas
recursos (mas tiempo de CPU). Esto no significa que el resto de los procesos no requieran tiempo de CPU, sino
que necesitaran menos. La forma de llevar a cabo esto, es gracias a las prioridades.
Cuando se crea un nuevo thread, este hereda la prioridad del thread, desde el cual ha sido inicializado. Las prioridades viene definidas por variables miembro de la clase Thread, que toman valores enteros, que oscilan entre
la maxima prioridad MAX PRIORITY (normalmente tiene el valor 10) y la mnima prioridad MIN PRIORITY (valor
1), siendo la prioridad por defecto NORM PRIORITY (valor 5). Para modificar la prioridad de un thread se utiliza el
metodo setPriority(). Se obtiene su valor con getPriority().
El algoritmo de distribucion de recursos en Java escoge por norma general, aquel thread que tiene una prioridad
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

93


4.7. HILOS Y SINCRONIZACION
mayor, aunque no siempre ocurra as, para evitar que algunos procesos queden dormidos. Cuando hay dos o mas
threads de la misma prioridad (y ademas, dicha prioridad es la mas elevada), el sistema no establecera prioridades
entre los mismos, y los ejecutara alternativamente dependiendo del sistema operativo en el que este siendo ejecutado. Si dicho sistema operativo soporta el time-slicing (reparto del tiempo de CPU), como por ejemplo lo hace
Windows 95/98/NT, los threads seran ejecutados alternativamente.
Un thread puede en un determinado momento renunciar a su tiempo de CPU y otorgarselo a otro thread de la
misma prioridad, mediante el metodo yield(), aunque en ningun caso a un thread de prioridad inferior.

4.7.5.

Grupos de Thread

Todo hilo de Java debe formar parte de un grupo de hilos (ThreadGroup). Puede pertenecer al grupo por
defecto o a uno explcitamente creado por el usuario. Los grupos de threads proporcionan una forma sencilla de
manejar multiples threads como un solo objeto. As, por ejemplo, es posible parar varios threads con una sola
llamada al metodo correspondiente. Una vez que un thread ha sido asociado a un grupo, no puede cambiar de
grupo.
Cuando se arranca un programa, el sistema crea un ThreadGroup llamado main. Si en la creacion de un nuevo
thread no se especifica a que grupo pertenece, automaticamente pasa a pertenecer al grupo del thread desde el
que ha sido creado. Si en dicho programa no se crea ningun ThreadGroup adicional, todos los threads creados
perteneceran al grupo main (en este grupo se encuentra el metodo main()).
Para conseguir que un thread pertenezca a un grupo concreto, hay que indicarlo al crear el nuevo thread, segun
uno de los siguientes constructores:
Thread(ThreadGroup grupo, Runnable destino)
Thread(ThreadGroup grupo, String nombre)
Thread(ThreadGroup grupo, Runnable destino, String nombre)
A su vez, un ThreadGroup debe pertenecer a otro ThreadGroup. Como ocurra en el caso anterior, si no se
especifica ninguno, el nuevo grupo pertenecera al ThreadGroup desde el que ha sido creado (por defecto al grupo
main). La clase ThreadGroup tiene dos posibles constructores:
ThreadGroup(ThreadGroup parent, String nombre);
ThreadGroup(String name);
el segundo de los cuales toma como padre el grupo al cual pertenezca el thread desde el que se crea
(Thread.currentThread()). Existen numerosos metodos para trabajar con grupos de threads a disposicion del
usuario, como por ejemplo, getMaxPriority(), setMaxPriority(), getName(), getParent() y parentOf().
En la practica los ThreadGroups no se suelen utilizar demasiado. Su uso practico se limita a efectuar determinadas
operaciones de forma mas simple que de forma individual. Vease el siguiente ejemplo:
ThreadGroup miThreadGroup = new ThreadGroup("Mi Grupo de Threads");
Thread miThread = new Thread(miThreadGroup, "un thread para mi grupo");
donde se crea un grupo de threads(miThreadGroup) y un thread que pertenece a dicho grupo(miThread).

94

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

Captulo 5

Java e Internet
5.1.

Trabajo en Red

El entorno Java es altamente considerado por su capacidad para escribir programas que utilizan e interactuan
con los recursos de Internet y la World Wide Web. De hecho, los navegadores que soportan Java utilizan esta
capacidad del entorno Java, hasta el extremo de transportar y ejecutar applets a traves de la red.

5.1.1.

Conceptos Basicos

Cuando se escriben programas Java que se comunican a traves de la red, se esta programando en la llamada
capa de aplicacion. Tpicamente, no se necesita trabajar con las capas de transporte, ni los protocolos TCP y UDP;
en su lugar se utilizan las clases del paquete java.net. Estas clases porporcionan comunicacion de red independiente del sistema. Sin embargo, se necesita entender la diferencia entre TCP y UDP para decidir que clases se
deberan utilizar en que programas.
Cuando dos aplicaciones se quieren comunicar una con otra de forma fiable, establecen una conexion y se envan
datos a traves de la conexion. Esto es parecido a hacer una llamada de telefono se establece una comunicacion
cuando se marca el numero de telefono y la otra persona responde. Se envan y reciben datos cuando se habla por
el telefono y se escucha lo que le dice la otra persona. Al igual que la compania telefonica, TCP garantiza que los
datos enviados por una parte de la conexion, realmente llegan a la otra parte y en el mismo orden en el que fueron
enviados.
Las aplicaciones que requieren fiabilidad, o canales punto a punto para comunicarse, utilizan TCP. Hyper Text
Transfer Protocol (HTTP), File Transfer Protocol (ftp), y Telnet (telnet) son ejemplos de aplicaciones que requieren un canal de comunicacion fiable. El orden en que los datos son enviados y recibidos a traves de la red es crtico
para el e xito de estas aplicaciones cuando se utiliza HTTP para leer desde una URL, los datos deben recibirse
en el mismo orden en que fueron enviados, de otra forma se podra obtener un archivo HTML revuelto, un archivo
Zip corrupto o cualquier otra informacion no valida.
Para muchas aplicaciones, esta garanta de fiabilidad es crtica para el e xito de la transferencia de informacion
desde un punto de la conexion a otro. Sin embargo, otras formas de comunicacion, no necesitan que esta comunicacion sea tan estricta, y mas aun esta la conexion fiable puede entorpecer el servicio.
Considere, por ejemplo, un servicio de reloj que enva la hora actual a sus clientes cuando estos lo piden. Si el
cliente pierde un paquete, tiene sentido volver a enviar el paquete? No, porque la hora que recibira el cliente ya
no sera exacta. Si el cliente hace dos peticiones y recibe dos paquetes del servidor en distinto orden, realmente
no importa porque el cliente puede imaginarse que los paquetes no estan en orden y pedir otro. El canal fiable,
aqu no es necesario, ya que causa una degradacion del rendimiento, y podra entorpecer la utilidad del servicio.
Otro ejemplo de servicio que no necesita un canal de fiabilidad garantizada, es el comando ping. El u nico objetivo
del comando ping es comprobar la comunicacion entre dos computadores a traves de la red. De hecho, ping necesita conocer las cadas o los paquetes fuera de orden para determinar lo buena o mala que es la conexion. As un
canal fiable entorpecera este servicio.
95

5.1. TRABAJO EN RED


El protocolo UDP proporciona una comunicacion no garantizada entre dos aplicaciones en la red. UDP no esta basado en la conexion como TCP. UDP enva paquetes de datos, llamados datagramas, de una aplicacion a otra.
Enviar datagramas, es como enviar una carta a traves del servicio de correos: el orden de envo no es importante y
no esta garantizado, y cada mensaje es independiente de los otros.
Puertos
Generalmente, un computador tiene una sola conexion fsica con la red. Todos los datos destinados a un computador en particular, llegan a traves de una sola conexion. Sin embargo, los datos podran ser utilizados por
diferentes aplicaciones ejecutandose en el computador. Entonces, como sabe el computador a que aplicacion enviarle los datos? A traves del uso de puertos.
Los datos transmitidos por Internet estan acompanados por una informacion de direccion que identifica el computador y el puerto al que estan destinados. El computador esta identificado por su direccion IP de 32 bits; esta
direccion se utiliza para envar los datos al computador correcto en la red. Los puertos estan identificados por un
numero de 16 bits, que TCP y UDP utilizan para envar los datos a la aplicacion correcta.
En aplicaciones basadas en la conexion, una aplicacion establece una conexion con otra aplicacion, uniendo un
socket a un numero de puerto. Esto tiene el efecto de registrar la aplicacion con el sistema para recibir todos los
datos destinados a ese puerto. Dos aplicaciones no pueden utilizar el mismo puerto: intentar acceder a uno que ya
esta utilizado, provocara un error.
En comunicaciones basadas en datagramas, los paquetes de datagramas contienen el numero de puerto del destinatario.
Los numeros de puertos tienen un rango de 0 a 65535 (porque estan representados por un numero de 16 bits). Los
puertos entre los numeros 0 - 1023 estan restringidos reservados para servicios bien conocidos como HTTP, FTP
y otros servicios del sistema. Otras aplicaciones no deberan intentar usar estos puertos.
A traves de las clases del paquete java.net, los programas Java pueden utilizar TCP o UDP para comunicarse
a traves de Internet. Las clases URL, URLConnection, Socket, y SocketServer utilizan TCP para comunicarse a
traves de la red. Las clases DatagramPacket y DatagramServer utilizan UDP.

5.1.2.

URL

URL es un acronimo que viene de Uniform Resource Locator y es una referencia (una direccion) a un recurso
de Internet.
Algunas veces es mas sencillo (aunque no enteramente acertado) pensar en una URL como el nombre de un archivo
en la red, porque la mayora de las URLs se refieren a un archivo en alguna maquina de la red. Sin embargo, se
debe recordar que las URLs pueden apuntar a otros recursos de la red, como consultas a bases de datos, o salidas
de comandos.
Lo siguiente es un ejemplo de una URL.
http://java.sun.com/
Esta URL en particular, direcciona el sitio Web de Java hospedada por Sun Microsystems. La URL anterior, como
otras URLs, tiene dos componentes principales.
El idendificador de protocolo
El nombre del recurso
En el ejemplo, http es el identificador de protocolo y //java.sun.com/ es el nombre del recurso.
El identificador de protocolo indica el nombre del protocolo a utilizar para buscar ese recurso. El ejemplo utiliza
el protocolo Hyper Text Transfer Protocol (HTTP), que es utilizado tpicamente para servir documentos de hypertexto.
El nombre del recurso es la direccion completa al recurso. El formato del nombre del recurso depende completamente del protocolo utilizado, pero la mayora de los formatos de nombres de recursos contienen uno o mas de los
siguientes componentes.
96

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


Nombre del host
Nombre de la maquina donde reside el recurso.
Nombre de archivo
El path al archivo dentro de la maquina.

Numero
de puerto
El numero de puerto a usar (normalmente es opcional).
Referencia
Una referencia a una posicion marcada dentro del recurso; normalmente identifica una posicion especfica
dentro de un archivo (normalmente es opcional).
Para muchos protocolos, el nombre del host y el nombre del archivo son obligatorios y el numero de puerto y
la referencia son opcionales. Por ejemplo, el nombre del recurso para una URL HTTP debera especificar un
servidor en la red (el nombre del host o su direccion IP) y el path al documento en esa maquina (nombre de
archivo), y tambien puede especificar un numero de puerto y una referencia. En la URL mostrada anteriormente,
java.sun.com es el nombre del host, y la barra inclinada(slash) / es el path para el nombre del archivo
index.html.
Una URL absoluta contiene toda la informacion necesaria para alcanzar el recurso en cuestion. Tambien, existen
URLs relativas, que solo contienen la informacion suficiente para alcanzar el recurso en relacion a (o en el contexto
de) otra URL.
El paquete java.net contiene una clase llamada URL que utilizan los programas Java para representar una URL.
Los programas Java pueden construir un objeto URL, abrir una conexion con el, leer y escribir datos a traves de esa
conexion.
A continuacion, una breve descripcion de cada uno de los constructores de esta clase:
URL(String DirAbsoluta)
Este constructor, crea un objeto a partir de una URL absoluta. Ejemplo,
URL inf = new URL("http://www.inf.utfsm.cl/");
URL(URL URLContexto, String DirRelativa)
Permite crear una URL a partir de un contexto y una URL relativa. Por ejemplo,
URL inf = new URL("http://www.inf.utfsm.cl/");
URL personas = new URL(inf, "personas.html"); //URL a recurso
URL personasBottom = new URL(personas, "#BOTTOM"); //URL a referencia en recurso
URL(String Protocolo, String Host, String Direccion)
Este constructor, permite crear una URL a partir de sus componentes por separado, usando el puerto por
defecto. Ejemplo,
URL personas = new URL("http", "www.inf.utfsm.cl", "/personas.html");
URL(String Protocolo, String Host, int Puerto, String Direccion)
Permite crear una URl, a partir de los componentes de la URL, incluyendo un puerto. Por ejemplo,
URL personas = new URL("http", "www.inf.utfsm.cl", 80, "/personas.html");
Cada uno de los cuatro constructores de URL lanza una excepcion de tipo MalformedURLException, si los
argumentos del constructor son nulos o el protocolo es desconocido.
A continuacion, una breve descripcion de cada uno de los metodos mas importantes de esta clase.
getProtocol()
Devuelve el componente identificador de protocolo de la URL.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

97

5.1. TRABAJO EN RED


getHost()
Devuelve el componente nombre del host de la URL.
getPort()
Devuelve el componente numero del puerto de la URL. Este metodo devuelve un entero que es el numero
de puerto. Si el puerto no esta selccionado, devuelve -1.
getFile()
Devuelve el componente nombre de archivo de la URL.
getRef()
Obtiene el componente referencia de la URL.
toExternalForm()
Permite obtener una cadena que contiene la direccion URL completa.
toString()
Entrega el mismo resultado que toExternalForm().
Nota: No todas las direcciones URL contienen todos los componentes de una URL generica. La clase URL
proporciona estos metodos porque las URLs de HTTP, contienen todos estos componentes y quizas son las URLs
mas utilizadas.
Este pequeno programa de ejemplo, crea una URL partiendo de una especificacion y luego utiliza los metodos
accesores del objeto URL para analizar la URL.
import java.net.*;
import java.io.*;
class ParseURL {
public static void main(String[] args) {
URL aURL = null ;
try {
aURL = new URL("http://java.sun.com:80/tutorial/intro.html#DOWNLOADING");
System.out.println("protocol = "+ aURL.getProtocol());
System.out.println("host = "+ aURL.getHost());
System.out.println("filename = "+ aURL.getFile());
System.out.println("port = "+ aURL.getPort());
System.out.println("ref = "+ aURL.getRef());
} catch (MalformedURLException e) {
System.out.println("MalformedURLException: "+ e);
}
}
}
La salida mostrada por el programa:
protocol = http
host = java.sun.com
filename = /tutorial/intro.html
port = 80
ref = DOWNLOADING
Leer Directamente desde una URL
Despues de haber creado satisfactoriamente una URL, se puede llamar al metodo openStream() de la clase URL, para obtener un canal desde el que poder leer el contenido de la URL. El metodo retorna un objeto
98

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


java.io.InputStream por lo que se puede leer de la URL utilizando los metodos de InputStream.
Leer desde una URL es tan sencillo como leer de un canal de entrada. El siguiente programa utiliza openStream(),
para obtener un flujo de entrada a la URL http://www.yahoo.com/. Lee el contenido del canal de entrada y lo
muestra por pantalla.
import java.net.*;
import java.io.*;
class OpenStreamTest {
public static void main(String[] args) {
try {
URL yahoo = new URL("http://www.yahoo.com/");
BufferedReader br = new BufferedReader(
new InputStreamReader(yahoo.openStream()));
String inputLine;
while ((inputLine = br.readLine()) != null ) {
System.out.println(inputLine);
}
br.close();
} catch (MalformedURLException me) {
System.out.println("MalformedURLException: "+ me);
} catch (IOException ioe) {
System.out.println("IOException: "+ ioe);
}
}
}
Cuando se ejecute el programa, se deberan ver los comandos HTML y el contenido textual del archivo HTML
localizado en http://www.yahoo.com/.
Establecer una Conexion a una URL
Si se ha creado satisfactoriamente una URL, se puede llamar al metodo openConnection() de la clase URL,
para establecer una conexion a ella. Cuando se ha establecido una conexion a una URL, se habra inicializado un
enlace de comunicacion entre un programa y la URL a traves de la red. Por ejemplo, se puede crear una conexion
con el motor de busqueda de Yahoo con el siguiente codigo:
try {
URL yahoo = new URL("http://www.yahoo.com/");
yahoo.openConnection();
} catch (MalformedURLException e) { // nueva URL() fallada
. . .
} catch (IOException e) { // openConnection() fallada
. . .
}
Si es posible, el metodo openConnection() crea un nuevo objeto URLConnection, lo inicializa, se conecta con
la URL y devuelve el objeto URLConnection. En caso de error, por ejemplo, si el servidor de Yahoo esta apagado,
el metodo openConnection() lanza una excepcion IOException.
Si se ha utilizado satisfactoriamente openConnection() para inicializar la comunicacion con una URL, se tendra una referencia a un objeto URLConnection. La clase URLConnection contiene muchos metodos que permiten
comunicarse con la URL a traves de la red. URLConnection es una clase centrada sobre HTTP muchos de sus
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

99

5.1. TRABAJO EN RED


metodos son u tiles solo cuando trabajan con URLs HTTP. Sin embargo, la mayora de los protocolos permiten
leer y escribir desde una conexion.
Leer desde un Objeto URLConnection
El siguiente programa realiza la misma funcion que el mostrado en la seccion 5.1.2. Sin embargo, mejor que
abrir directamente un flujo desde la URL, este programa abre explcitamente una conexion a la URL, obtiene un
flujo de entrada sobre la conexion, y lee desde el flujo de entrada.
import java.net.*;
import java.io.*;
class ConnectionTest {
public static void main(String[] args) {
try {
URL yahoo = new URL("http://www.yahoo.com/");
URLConnection yahooConnection = yahoo.openConnection();
BufferedReader br = new BufferedReader(
new InputStreamReader(yahooConnection.getInputStream()));
String inputLine;
while ((inputLine = br.readLine()) != null ) {
System.out.println(inputLine);
}
br.close();
} catch (MalformedURLException me) {
System.out.println("MalformedURLException: "+ me);
} catch (IOException ioe) {
System.out.println("IOException: "+ ioe);
}
}
}
La salida de este programa debiera ser identica a la salida del programa que abra directamente el flujo desde
la URL. Se puede utilizar cualquiera de estas dos formas para leer desde una URL. Sin embargo, algunas veces
leer desde una URLConnection en vez de leer directamente desde una URL podra ser mas u til, ya que se puede
utilizar el objeto URLConnection para otras tareas (como escribir sobre la conexion URL) al mismo tiempo.
Escribir hacia una URLConnection
Muchas paginas HTML contienen formularios campos de texto y otros objetos que permiten introducir datos, que luego son enviados al servidor. Despues de ingresar la informacion requerida e iniciar la peticion pulsando
un boton, el navegador escribe los datos en la URL a traves de la red. Despues la otra parte de la conexion en el
servidor, los procesa, y le enva de vuelta una respuesta, normalmente en la forma de una nueva pagina HTML.
Los programas Java tambien pueden interactuar con el servidor. Solo deben poder escribir a una URL, as proporcionan los datos al servidor. Un programa puede hacer esto siguiendo los siguientes pasos:
Crear una URL.
Abrir una conexion con la URL.
Obtener un flujo de salida sobre la conexion. Este canal de salida esta conectado al flujo de entrada estandar
del servidor.
Escribir en el flujo de salida.
100

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


Cerrar el flujo de salida.
Hassan Schroeder, miembro del equipo de Java, escribio un script cgi-bin, llamado backwards, y esta disponible
en la Web site de Sun. Se puede utilizar este script para probar el siguiente programa de ejemplo.
El script lee una cadena de la entrada estandar, invierte la cadena, y escribe el resultado en la salida estandar. El
script requiere una entrada de la siguiente forma: string=string to reverse, donde string to reverse es
la cadena cuyos caracteres se quieren invertir.
Aqu hay un programa de ejemplo que ejecuta el script backwards, a traves de la red, utilizando un URLConnection.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

import java.io.*;
import java.net.*;
public class ReverseTest {
public static void main(String[] args) {
try {
if (args.length != 1) {
System.err.println("Usage: java ReverseTest string to reverse");
System.exit(1);
}
String stringToReverse = URLEncoder.encode(args[0]);
URL url = new URL("http://java.sun.com/cgi-bin/backwards");
URLConnection connection = url.openConnection();
connection.setDoOutput(true );
PrintWriter writer = new PrintWriter(connection.getOutputStream());
writer.println("string="+ stringToReverse);
writer.close();
BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
String inputLine;
while ((inputLine = reader.readLine()) != null ) {
System.out.println(inputLine);
}
reader.close();
} catch (MalformedURLException me) {
System.err.println("MalformedURLException: "+ me);
} catch (IOException ioe) {
System.err.println("IOException: "+ ioe);
}
}
}

Primero, el programa procesa los argumentos de la lnea de comandos, entre las lneas 07 y 11. Estas lneas aseguran que el usuario proporciona uno y solo un argumento en la lnea de comandos del programa y lo codifica. El
argumento de la lnea de comandos, es la cadena a invertir por el script cgi-bin backwards. El argumento de la lnea
de comandos, podra tener espacios u otros caractetes no alfanumericos. Estos caracteres deben ser codificados,
ya que algunos tienen significados especficos. Esto se consigue mediante la clase URLEncoder.
Luego, en la lnea 13, el programa crea el objeto url la URL para el script backwards en java.sun.com.
El programa crea una URLConnection, en la lnea 14, y abre un flujo de salida sobre esta conexion. El flujo
de salida esta filtrado a traves de un PrintWriter. La lnea 15 le indica a la conexion, que a continuacion se
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

101

5.1. TRABAJO EN RED


usara para enviar datos.
Luego, se llama al metodo getOutputStream() sobre la conexion. Si el protocolo no soporta salida, este metodo
lanza una excepcion de tipo UnknownServiceException. Si el procolo soporta salida, este metodo devuelve un
flujo de salida que esta conectado al flujo de entrada estandar de la URL en el lado del servidor la salida del
cliente es la entrada del servidor.
En las lneas 18 y 19, el programa escribe la informacion requerida al flujo de salida utilizando el metodo
println(). Como se puede ver, escribir datos a una URL es tan sencillo, como escribir datos en un flujo. Los
datos escritos en el flujo de salida en el lado del cliente, son la entrada para el script backwards en el lado del
servidor. El programa ReverseTest construye la entrada en la forma requirida por el script, mediante la concatenacion de string para codificar la cadena, y cierra el flujo.
Frecuentemente, como en este ejemplo, cuando se escribe en una URL, se esta pasando informacion al script que
lee la informacion que se escribe, se realiza alguna accion y luego se enva la informacion de vuelta mediante la
misma URL. Por lo que, se querra leer desde la URL, despues de haber escrito en ella. El programa ReverseTest
lo hace de esta forma, en las lneas desde la 21 hasta la 28.
Cuando se ejecute el programa ReverseTest utilizando Invierteme como argumento, se debiera ver esta salida:
Invierteme reversed is emetreivnI

5.1.3.

Sockets

Se utilizan las clases URL y URLConnection para comunicarse a traves de la red a un nivel relativamente
alto y para un proposito especfico: acceder a los recuros de Internet. Algunas veces los programas requieren una
comunicacion en la red a un nivel mas bajo, por ejemplo, el caso de una aplicacion cliente-servidor.
En aplicaciones cliente-servidor, el servidor proporciona algun servicio, como procesar consultas a bases de datos
o enviar los precios actualizados del stock. El cliente utiliza el servicio proporcionado por el servidor para algun
fin, mostrar los resultados de la consulta a la base de datos, o hacer recomendaciones de pedidos a un inversor.
La comunicacion que ocurre entre el cliente y el servidor debe ser fiable los datos no pueden perderse y deben
llegar al lado del cliente en el mismo orden en el que fueron solicitados.
TCP proporciona un canal de comunicacion fiable punto a punto, lo que utilizan para comunicarse las aplicaciones
cliente-servidor en Internet. Las clases Socket y ServerSocket del paquete java.net proporcionan un canal
de comunicacion independiente del sistema utilizando TCP.
Una aplicacion servidor normalmente escucha un puerto especfico, esperando una peticion de conexion de un
cliente. Cuando llega una peticion de conexion, el cliente y el servidor establecen una conexion dedicada sobre
la que pueden comunicarse. Durante el proceso de conexion, el cliente es asignado a un numero de puerto, y fija un socket a ella. El cliente se comunica con el servidor escribiendo y leyendo sobre el socket. Similarmente,
el servidor obtiene un nuevo numero de puerto local(necesita un nuevo puerto para poder continuar escuchando
peticiones de conexion del puerto original). El servidor tambien fija un socket a este puerto local y se comunica
mediante la lectura y escritura sobre e l.
El cliente y el servidor deben ponerse de acuerdo sobre el protocolo esto es, deben ponerse de acuerdo en el
lenguaje para transferir la informacion de vuelta a traves del socket.
El paquete java.net del entorno de desarrollo de Java proporciona una clase Socket que representa un
punto final de una comunicacion de dos vas, entre un programa y otro en la red. La clase Socket implementa el
lado del cliente de un enlace de dos vas. Si se esta escribiendo un programa servidor, tambien se estara interesado
en la clase ServerSocket, que implementa el lado del servidor en un enlace de dos vas.

Lectura y Escritura sobre Sockets


El siguiente programa es un ejemplo sencillo de como establecer una conexion entre un programa cliente y
otro servidor, utilizando sockets. La clase Socket del paquete java.net, es una implementacion independiente
de la plataforma de un cliente para un enlace de comunicacion de dos vas entre un cliente y un servidor. La clase
Socket se situa en la parte superior de una implementacion dependiente de la plataforma, ocultando los detalles
102

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


de los sistemas particulares, a un programa Java.
Este programa cliente, EchoTest, se conecta con el servicio echo de cualquier servidor Unix(en el puerto 7) mediante un socket. El cliente lee y escribe a traves del socket. EchoTest enva todo el texto ingresado en su entrada
estandar al servicio echo del servidor, escribiendo el texto en el socket. El servidor repite todos los caracteres
recibidos en su entrada desde el cliente de vuelta a traves del socket al cliente. El programa cliente lee y muestra
los datos pasados de vuelta desde el servidor.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

import java.io.*;
import java.net.*;
public class EchoTest {
public static void main(String[] args) {
Socket echoSocket = null ;
DataOutputStream os = null ;
BufferedReader br = null ;
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in));
try {
echoSocket = new Socket("localhost", 7);
os = new DataOutputStream(echoSocket.getOutputStream());
br = new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Host desconocido: localhost");
} catch (IOException e) {
System.err.println("Conexi
on rechazada");
}
if (echoSocket != null && os != null && br != null ) {
try {
String userInput;
while ((userInput = stdIn.readLine()) != null ) {
os.writeBytes(userInput);
os.writeByte(\n);
System.out.println("echo: "+ br.readLine());
}
os.close();
br.close();
echoSocket.close();
} catch (IOException e) {
System.err.println("Error en la Conexi
on");
}
}
}
}

Al revisar el codigo, se aprecia que las lneas 13 a la 16, dentro del primer bloque try del metodo main(), son
crticos establecen la conexion del socket entre el cliente y el servidor y abre un canal de entrada y un canal de
salida sobre el socket.
La lnea 13 crea un nuevo objeto Socket y lo llama echoSocket. El constructor Socket utilizado aqu(existen
otros) requiere el nombre de la maquina y el numero de puerto al que se quiere conectar. El programa de ejemplo
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

103

5.1. TRABAJO EN RED


utiliza la maquina localhost. El segundo argumento es el numero de puerto. El puerto numero 7 es el puerto por
el que escucha el servicio echo.
La lnea 14 del codigo, abre un canal de entrada sobre el socket, y las lneas 15 y 16 abren un canal de salida sobre
el mismo socket. EchoTest solo necesita escribir en el flujo de salida y leer del flujo de entrada para comunicarse
a traves del socket con el servidor.
La siguiente seccion de codigo, entre las lneas 25 y 31, lee desde el flujo de entrada estandar del programa, una
lnea a la vez. El programa escribe inmediatamente la entrada, seguida por un caracter de nueva lnea en el flujo
de salida conectado al socket.
La u ltima lnea del bucle while , la 30, lee una lnea de informacion desde el flujo de entrada conectado al socket. El metodo readLine() se bloquea hasta que el servidor haya devuelto toda la lnea. Cuando readLine()
retorna, el programa imprime la informacion en la salida estandar.
Este bloque continua El programa lee la entrada del usuario, la enva al servidor echo, obtiene una respuesta
desde el servidor, y la muestra hasta que el usuario ingrese un caracter de final de entrada.
Cuando el usuario ingresa un caracter de fin de entrada, el bucle while termina y el programa continua ejecutando las lneas 32 a la 34. Estas tres lneas de codigo cierran los flujos de entrada y salida conectados al socket, y
cierra la conexion del socket con el servidor. El orden es importante se deben cerrar los flujos conectados a un
socket antes de cerrar el socket mismo.
Este programa cliente tiene un comportamiento correcto y sencillo porque el servidor echo implementa un protocolo sencillo. El cliente enva texto al servidor, y el servidor lo devuelve. Cuando un programa cliente se comunique con un servidor mas complejo, como un servidor http, el programa cliente tambien sera mas complejo. Sin
embargo, las cosas basicas son las vistas en este programa:
1. Abrir un socket.
2. Abrir un flujo de entrada y otro de salida hacia el socket.
3. Leer y escribir a traves del socket de acuerdo al protocolo del servidor.
4. Cerrar los streams.
5. Cerrar el socket.
Solo el tercer paso sera diferente de un cliente a otro, dependiendo del servidor. Los otros pasos permanecen
inalterables.
El Lado Servidor de un Socket
Esta seccion muestra como escribir el lado del servidor de una conexion socket, implementando el servicio
echo.
El programa servidor esta implementado por una sola clase: EchoServer. EchoServer contiene el metodo
main() para el program servidor y realiza todo el trabajo duro, de escuchar el puerto, establecer conexiones,
leer y escribir a traves del socket. A continuacion el codigo:
01 import java.net.*;
02 import java.io.*;
03
04 class EchoServer {
05
public static void main(String[] args) {
06
ServerSocket serverSocket = null ;
07
08
try {
09
serverSocket = new ServerSocket(7);
10
} catch (IOException e) {
11
System.out.println("No es posible usar el Puerto 7, "+ e);
12
System.exit(1);
104

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 }

}
Socket clientSocket = null ;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.out.println("Error al esperar al Cliente, "+ e);
System.exit(1);
}
try {
BufferedReader br = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
PrintWriter pw = new PrintWriter(new BufferedOutputStream(
clientSocket.getOutputStream(), 1024), false );
String inputLine, outputLine;
while ((inputLine = br.readLine()) != null ) {
outputLine = inputLine;
pw.println(outputLine);
pw.flush();
}
pw.close();
br.close();
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

Este programa servidor empieza creando un nuevo objeto ServerSocket para escuchar en un puerto especfico,
el 7. Como se ve, en las lneas de la 8 a la 13.
ServerSocket es una clase java.net que proporciona una implementacion independiente del sistema del lado
del servidor de una conexion cliente/servidor. El constructor de ServerSocket lanza una excepcion cuando por
alguna razon, por ejemplo, que el puerto ya esta siendo utilizado, no puede escuchar en el puerto especificado. En
este caso, el EchoServer no tiene eleccion y termina su ejecucion.
Si el servidor se conecta con e xito con el puerto deseado, el objeto ServerSocket se crea y el servidor continua
con el siguiente paso, que es aceptar una conexion de un cliente. Como se ve en las lneas entre la 15 y la 21.
El metodo accept() se bloquea(espera) hasta que un cliente empiece y pida una conexion al puerto, que el
servidor esta escuchando. Cuando el metodo accept() establece con e xito la conexion con el cliente, devuelve
un objeto Socket que apunta a un puerto local nuevo. El servidor puede continuar con el cliente sobre este nuevo
Socket, en un puerto diferente del que estaba escuchando originalmente para las conexiones. Por eso, el servidor
puede continuar escuchando nuevas peticiones de clientes, a traves del puerto original del ServerSocket. Esta
version del programa de ejemplo no escucha mas peticiones de clientes. Sin embargo, una version modificada de
este programa, porpocionada mas adelante, si lo hace.
El codigo que hay dentro del siguiente bloque try implementa el lado del servidor de una comunicacion con el
cliente. Esta seccion del servidor es muy similar al lado del cliente (vista en el ejemplo EchoTest). Como se ve en
las lneas entre la 23 y la 36. Se abre un flujo de entrada y otro de salida sobre un socket. Luego, se lee y escribe a
traves del socket. Finalmente, se cierran las conexiones.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

105

5.1. TRABAJO EN RED

Soporte para Multiples


Clientes
El ejemplo EchoServer fue disenado para escuchar y manejar una sola peticion de conexion. Sin embargo,
pueden recibirse varias peticiones sobre el mismo puerto y consecuentemente sobre el mismo ServerSocket. Las
peticiones de conexiones de clientes se almacenan en el puerto, para que el servidor pueda aceptarlas de forma
secuencial. Sin embargo, puede servirlas simultaneamente a traves del uso de threads un thread para procesar
cada conexion de cliente.
El flujo logico basico en este tipo de servidores, es:
while (true ) {
<aceptar una conexi
on>;
<crear un thread para tratar a cada cliente>;
}
El thread lee y escribe en la conexion del cliente cuando sea necesario.
A continuacion, un programa en dos clases: EchoMultiServer y EchoMultiServerThread.
EchoMultiServer hace un bucle continuo, escuchando peticiones de conexion desde los clientes con un ServerSocket.
Cuando llega una peticion, se accepta, y se crea un objeto EchoMultiServerThread para procesarlo, manejando
el socket devuelto por accept(), y se arranca el thread. Luego el servidor vuelve a escuchar en el puerto las
peticiones de conexion.
El objeto EchoMultiServerThread se comunica con el cliente que esta leyendo y escribiendo a traves del socket.
Ahora se puede ejecutar el nuevo servidor y luego ejecutar varios clientes concurrentemente.
01 import java.net.*;
02 import java.io.*;
03
04 public class EchoMultiServer {
05
public static void main(String[] args) {
06
ServerSocket serverSocket = null ;
07
08
try {
09
serverSocket = new ServerSocket(7);
10
} catch (IOException e) {
11
System.out.println("No es posible usar el Puerto 7, "+ e);
12
System.exit(1);
13
}
14
15
while (true ) {
16
Socket clientSocket = null ;
17
try {
18
clientSocket = serverSocket.accept();
19
} catch (IOException e) {
20
System.out.println("Error al esperar al Cliente, "+ e);
21
continue ;
22
}
23
new EchoMultiServerThread(clientSocket).start();
24
}
25
26
try {
27
serverSocket.close();
28
} catch (IOException e) {
29
e.printStackTrace();
30
}
106

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


31
}
32 }
33
34 class EchoMultiServerThread extends Thread {
35
Socket socket = null ;
36
37
EchoMultiServerThread(Socket socket) {
38
super ("EchoMultiServerThread");
39
this .socket = socket;
40
}
41
42
public void run() {
43
try {
44
BufferedReader br = new BufferedReader(
45
new InputStreamReader(clientSocket.getInputStream()));
46
PrintWriter pw = new PrintWriter(new BufferedOutputStream(
47
clientSocket.getOutputStream(), 1024), false );
48
String inputLine, outputLine;
49
50
while ((inputLine = br.readLine()) != null ) {
51
outputLine = inputLine;
52
pw.println(outputLine);
53
pw.flush();
54
}
55
pw.close();
56
br.close();
57
clientSocket.close();
58
serverSocket.close();
59
} catch (IOException e) {
60
e.printStackTrace();
61
}
62
}
63 }

5.1.4.

Datagramas

Los clientes y servidores que se comunican mediante un canal fiable (como una URL o un socket) tienen un
canal punto a punto dedicado entre ellos (o al menos la ilusion de uno). Para comunicarse, establecen una conexion, transmiten los datos y luego cierran la conexion. Todos los datos enviados a traves del canal se reciben en el
mismo orden en el que fueron enviados. Esto esta garantizado por el canal.
En contraste, las aplicaciones que se comunican mediante datagramas, envan y reciben paquetes de informacion
completamente independientes. Estos clientes y servidores no tienen y no necesitan un canal punto a punto dedicado. El envo de los datos a su destino no esta garantizado, ni su orden de llegada.
El paquete java.net, contiene dos clases que ayudan a escribir programas Java que utilicen datagramas para
enviar y recibir paquetes a traves de la red: DatagramSocket y DatagramPacket. Una aplicacion enva y recibe
DatagramPackets a traves de un DatagramSocket.
El ejemplo de esta seccion esta comprendido por dos aplicaciones: un cliente y un servidor. El servidor recibe
continuamente paquetes de datagramas a traves de un socket para datagramas. Cada paquete recibido por el servidor contiene una peticion de la hora del cliente. Cuando el servidor recibe un datagrama, le responde enviando un
datagrama que contiene la hora del servidor.
La aplicacion cliente de este ejemplo es muy sencilla enva un datagrama vaco al servidor que indica que se
quiere saber la hora del servidor. Entonces, el cliente espera a que el servidor le enve un datagrama en respuesta.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

107

5.1. TRABAJO EN RED


Dos clases implementan la aplicacion servidor: DateServer y DateServerThread. Una sola clase implementa
la aplicacion cliente: DateClient.
Servidor de Fechas
A continuacion el codigo de las clases DateServer y DateServerThread:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
108

import java.io.*;
import java.net.*;
public class DateServer {
public static void main(String[] args) {
new DateServerThread().start();
}
}
class DateServerThread extends Thread {
DatagramSocket socket = null ;
DateServerThread() {
super ("DateServer");
try {
socket = new DatagramSocket();
System.out.println("DateServer escuchando el puerto: "
+ socket.getLocalPort());
} catch (java.io.IOException e) {
System.err.println("No se pudo levantar el servidor.");
}
}
public void run() {
while (socket != null ) {
byte [] buf = new byte [256];
DatagramPacket packet;
InetAddress address;
int port;
String dString = null ;
try {
// recibir paquete
packet = new DatagramPacket(buf, 256);
socket.receive(packet);
address = packet.getAddress();
port = packet.getPort();
// enviar respuesta
dString = (new Date()).toString();
buf = dString.getBytes();
packet = new DatagramPacket(buf, buf.length , address, port);
socket.send(packet);
} catch (IOException e) {
System.err.println("IOException: "+ e);
Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


46
47
48
49
50 }

e.printStackTrace();
}
}
}

La clase DateServer contiene un solo metodo: el metodo main() para la aplicacion servidor. El metodo main()
solo crea un nuevo objeto DateServerThread y lo arranca.
La clase DateServerThread implementa la logica principal del servidor: es un thread que se ejecuta continuamente esperando peticiones a traves del un socket de datagramas.
DateServerThread tiene una variable, llamada socket, que es una referencia a un objeto DatagramSocket.
Esta variable se inicializa a null .
Cuando el programa principal crea el DateServerThread, utiliza el u nico constructor disponible, como se ve en
las lneas 13 a la 21.
La lnea 14 llama al constructor de la superclase(Thread) para inicializar el thread con el nombre "DateServer".
La siguiente seccion de codigo, la lnea 16 principalmente, es la parte crtica del constructor de DateServerThread
crea un DatagramSocket. El DateServerThread utiliza este DatagramSocket para escuchar y responder
las peticiones de los clientes.
El socket es creado utilizando el constructor de DatagramSocket que no requiere argumentos.
Una vez creado usando este constructor, el nuevo DatagramSocket se asigna a algun puerto local disponible. La
clase DatagramSocket, tiene otro constructor que permite especificar el puerto que se quiere utilizar para asignarle al nuevo objeto DatagramSocket. Ciertos puertos estas dedicados a servicios bien-conocidos y que no
pueden ser utilizados. Si se especifica un puerto que esta siendo utilizado, fallara la creacion del DatagramSocket.
Despues de crear con e xito el DatagramSocket, el DateServerThread muestra un mensaje indicando el puerto
al que se ha asignado el DatagramSocket. El DateClient necesita este numero de puerto para construir los paquetes de datagramas destinados a este puerto. Por eso, se debe utilizar este numero de puerto, cuando se ejecute
el DateClient.
Ahora, la parte interesante de DateServerThread, es el metodo run()(que sobreescribe el metodo run() de la
clase Thread y proporciona la implementacion del thread).
El metodo run() primero comprueba que se ha creado un objeto DatagramSocket valido durante su construccion. Si socket es null , entonces el DateServerThread no podra recibir ni enviar paquetes. Sin el socket, el
servidor no puede operar, y el metodo run() retorna.
De otra forma, el metodo run() entra en un bucle infinito. Este bucle espera continuamente las peticiones de los
clientes y responde estas peticiones. Este bucle contiene dos secciones crticas de codigo: la seccion que escucha
las peticiones y la que las responde.
La seccion que escucha las peticiones, entre las lneas 33 y 37, crea primero un nuevo objeto DatagramPacket
encargado de recibir un datagrama a traves del socket. Se puede decir, que el nuevo DatagramPacket esta encargado de recibir datos desde el socket debido al constructor utilizado para crearlo. Este constructor requiere solo
dos argumentos, un arreglo de bytes que contendra los datos enviados por el cliente, y la longitud de este arreglo.
Cuando se construye un DatagramPacket para enviarlo a traves de un DatagramSocket, tambien se debe suministrar el host y el puerto de destino del paquete.
La lnea 35 recibe un datagrama desde el socket. La informacion contenida dentro del mensaje del datagrama se
copia en el paquete creado en la lnea anterior. El metodo receive() se bloquea hasta que se reciba un paquete.
Si no se recibe ningun paquete, el servidor no hace ningun progreso y simplemente espera.
Las dos lneas siguientes obtienen la direccion del host y el numero de puerto desde el que se ha recibido el datagrama. Este es donde el servidor debe responder. En este ejemplo, el arreglo de bytes del datagrama contiene el
numero a ser elevado al cuadrado. Solo la llegada del paquete indica una peticion por parte del cliente, que puede
ser encontrado en la direccion del host y el numero de puerto indicado en el datagrama.
En este punto, el servidor ha recibido un peticion desde un cliente. Ahora el servidor debe responder. Y las siguientes lneas de codigo, entre la 39 y la 43 construyen la respuesta y la envian.
La lnea 42 crea un nuevo objeto DatagramPacket utilizado para enviar el mensaje a traves del socket del datagrama. Se puede decir que, el nuevo DatagramPacket esta destinado a enviar los datos a traves del socket,
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

109

5.1. TRABAJO EN RED


porque el constructor lo utiliza para eso. Este constructor requiere cuatro argumentos. El primero, es el mismo que
el utilizado por el constructor para crear los datagramas receptores: un arreglo de bytes que contiene el mensaje
del emisor al receptor y la longitud de este arreglo. Los dos siguientes argumentos son diferentes: una direccion
de Internet y un numero de puerto. Estos dos argumentos son la direccion completa del destino del datagrama y
debe ser suministrada por el emisor del datagrama.
Finalmente, la lnea 43 enva el DatagramPacket creado de esta forma.

Cliente de Fechas
La clase DateClient implementa una aplicacion cliente para el DateServer. Esta aplicacion solo enva
una peticion al DateServer, espera una respuesta, y cuando esta se recibe, la muestra en la salida estandar. A
continuacion el codigo:
01 import java.io.*;
02 import java.net.*;
03
04 class DateClient {
05
public static void main(String[] args) {
06
int port;
07
InetAddress address;
08
DatagramSocket socket = null ;
09
DatagramPacket packet;
10
byte [] sendBuf = new byte [256];
11
12
if (args.length != 2) {
13
System.out.println("Uso: java DateClient servidor puerto");
14
return ;
15
}
16
17
try {
18
socket = new DatagramSocket();
19
} catch (java.io.IOException e) {
20
System.err.println("No se pudo crear la conexi
on.");
21
return ;
22
}
23
24
try {
25
// enviar solicitud
26
port = Integer.parseInt(args[1]);
27
address = InetAddress.getByName(args[0]);
28
packet = new DatagramPacket(sendBuf, 256, address, port);
29
socket.send(packet);
30
31
// obtener respuesta
32
packet = new DatagramPacket(sendBuf, 256);
33
socket.receive(packet);
34
String received = new String(packet.getData());
35
System.out.println(received);
36
37
socket.close();
38
} catch (IOException e) {
110

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


39
40
41
42
43 }

System.err.println("IOException: "+ e);


e.printStackTrace();
}
}

La clase DateClient contiene un metodo el metodo main() para la aplicacion cliente. La parte superior
de main(), entre las lneas 5 y 10, declara varias variables locales para su posterior utilizacion.
La siguiente seccion, entre las lneas 12 y 15, procesa los argumentos de la lnea de comandos utilizados para
invocar la aplicacion DateClient.
Esta aplicacion requiere dos argumentos: el nombre de la maquina en la que se esta ejecutando DateServer, y el
numero de puerto por el cual DateServer esta escuchando. Cuando arranca, el DateServer muestra un numero
de puerto. Este es el numero de puerto que debe utilizar en la lnea de comandos cuando arranque DateClient.
Luego, entre las lneas 17 y 22, el cliente utiliza el mismo constructor para crear un DatagramSocket que el
servidor. El DatagramSocket es asignado a cualquier puerto disponible.
Finalmente, el metodo main() contiene un bloque try , entre las lneas 24 y 41, que contiene la logica principal
del programa cliente. Este bloque try contiene tres secciones: una seccion que enva una peticion al servidor,
entre las lneas 25 y 29, el metodo getByName() de la clase InetAddress obtiene una direccion valida a partir
del nombre una maquina; y una seccion que obtiene la respuesta del servidor, entre las lneas 31 y 35. Cuando
el cliente recibe una respuesta del servidor, utiliza el metodo getData() para recuperar los datos del paquete. El
cliente convierte los datos en una cadena y los muestra. Finalmente, una seccion que cierra la conexion, la lnea
37.

5.2.

HTML

Cuando se produjo la explosion de Internet, el estandar de HTML que circulaba era el 2.0 (establecido en
noviembre del 95), de modo que cualquier navegador que se encuentre sera capaz de interpretarlo. Practicamente
todo lo que se vea en esta seccion esta contemplado por este estandar.
Aunque la version 2.0 cumpla bien el objetivo para el que se creo, careca de herramientas para tener un control
mnimamente complejo de los documentos. No se considero necesario que lo tuviera, ya que por aquel entonces,
Internet era un fenomeno mas bien circunscrito a la actividad academica y el contenido primaba sobre el diseno.
Debido a ello, Netscape (lder del mercado de navegadores en aquel entonces) empezo a incluir etiquetas nuevas
que no formaban parte de ningun estandar.
Por estos problemas, el IETF (comite que suele decidir todos los estandares dentro de Internet) comenzo a elaborar
el borrador del HTML 3.0, que resulto ser demasiado grande para la e poca, lo que dificulto su aceptacion en el
mercado.
Esto llevo a una serie de companas (entre ellas Netscape, Microsoft, IBM, Sun, etc...) a crear un nuevo comite llamado W3C, que es el que actualmente elabora las nuevas versiones del HTML. Su primer trabajo consistio en
crear el borrador del HTML 3.2, que inclua muchas de las mejoras que los principales navegadores (Netscape y
Explorer) haban introducido en Internet, como son las tablas, los applets, etc..
Este borrador fue aprobado en enero de 1997 e inmediatamente el W3C se puso a trabajar en la elaboracion del
siguiente estandar: el 4.0.
En julio de 1997 se presenta el borrador de este estandar. Por fin se estandarizan los marcos(frames), las hojas de
estilo y los scripts(entre otras cosas). El 17 de diciembre de 1997, dicho borrador fue finalmente aprobado. HTML
4.01 es la revision actual de HTML 4.0, que fue liberada el 24 de abril de 1998.

5.2.1.

Primera Pagina

El Codigo
<HTML>
<HEAD>
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

111

5.2. HTML
<TITLE>Mi Primera P
agina</TITLE>
</HEAD>
<BODY>
<CENTER><H1>Mi Primera P
agina</H1></CENTER>
<HR>
<P>Esta es mi primera p
agina. Por el momento no tiene nada m
as que un
t
tulo y un p
arrafo de texto.
</BODY>
</HTML>
La Explicacion
Lo primero que conviene explicar es, en que consisten todos esos smbolos de mayor y menor. El lenguaje
HTML se basa en la sintaxis SGML. Esto quiere decir que cualquier cosa que se haga en HTML estara encerrada
entre dos etiquetas de esta manera:
<ETIQUETA ATRIBUTO="valor" >... </ETIQUETA>
Hay ocasiones en que no es necesario cerrar la etiqueta. Mirando el codigo se visualizan un par de ejemplos de
esto(HR y P). Lo primero que se debe indicar, es que el texto que se esta componiendo es un documento HTML,
pues se indica as:
<HTML>... </HTML>
Un documento HTML tiene una estructura que lo separa en dos partes: cuerpo y cabecera. En la primera estara la
pagina en s, mientras que en la segunda se incluyen algunas cosas que pueden llegar a ser muy importantes, no
estando directamente ligadas al aspecto de la pagina, como son por ejemplo, informacion del autor, codigo script
o definiciones de estilos. Lo primero que hay que incluir en el codigo es, la cabecera. En el ejemplo:
<HEAD>
<TITLE>Mi Primera P
agina</TITLE>
</HEAD>
Dentro de la cabecera solo hay otra etiqueta. Es la u nica imprescindible: el ttulo de la pagina. Es lo que se
visualizara como ttulo de la ventana en los navegadores que lo permitan. Es como se conocera la pagina en
algunos buscadores y en la agenda de direcciones(bookmarks) de los usuarios. Por lo tanto, es importante pensar
en como llamarla.
El Cuerpo del Documento
Ahora se indicara el contenido. Lo primero sera indicar que se esta en el cuerpo del documento:
<BODY>... </BODY>
Luego se escribe el ttulo algo recalcado:
<CENTER><H1>... </H1></CENTER>
Con esto se coloca el texto centrado(<CENTER>) y en formato <H1> que asegura que aumentara el tamano del tipo
de letra lo suficiente como para que se vea resaltado. Luego se separa ese ttulo que se le ha puesto a la pagina, del
texto, por medio de una lnea horizontal:
<HR>
112

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


La lnea horizontal carece de etiqueta de cierre. Esto es normal en etiquetas que no varan los atributos de texto,
sino que insertan un elemento. Por ejemplo, para indicar que se quiere separar el texto de la lnea horizontal, con
un espacio vertical correspondiente a un parrafo nuevo, se usa la etiqueta <P>:
<P>Esta es mi primera p
agina. Por el momento no tiene nada m
as que un t
tulo y
un p
arrafo de texto.
En la seccion siguiente se veran algunas etiquetas que permitiran cambiar el aspecto del texto.

5.2.2.

Formateo Basico

Se pueden establecer varias categoras dentro de las etiquetas usadas para formatear el texto. Aqu se dividiran
entre aquellas que sirven para cambiar parrafos enteros y las que son capaces de formatear cadenas de caracteres
dentro del parrafo.
Formato de Parrafo
Estas son las etiquetas mas importantes (excluyendo algunas que se veran mas adelante):
<P>
Sirve para delimitar un parrafo. Inserta una lnea en blanco antes del texto.
<CENTER>... </CENTER>
Permite centrar todo el texto del parrafo.
<PRE WIDTH=x>... </PRE>
Representa el texto encerrado en ella con un tipo de letra monoespaciada. Es u til a la hora de representar
codigo fuente. El atributo WIDTH especifica el numero maximo de caracteres en una lnea.
<DIV ALIGN=x>... </DIV>
Permite justificar el texto del parrafo a la izquierda (ALIGN="LEFT"), derecha ("RIGHT"), al centro ("CENTER")
o a ambos margenes ("JUSTIFY").
<BLOCKQUOTE>... </BLOCKQUOTE>
Para citar un texto ajeno. Se suele implementar dejando margenes tanto a la izquierda como a la derecha,
razon por la que se usa habitualmente.

Las 6 Fuentes de Cabecera


HTML ofrece seis etiquetas distintas para mostrar cabeceras. Son e stas:
<H1>... </H1>

Cabecera de nivel 1
<H2>... </H2>

Cabecera de nivel 2
<H3>... </H3>

Cabecera de nivel 3
<H4>... </H4>
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

113

5.2. HTML

Cabecera de nivel 4
<H5>... </H5>

Cabecera de nivel 5
<H6>... </H6>
Cabecera de nivel 6
No resulta recomendable utilizarlas para aumentar o disminuir el tamano del tipo de letra, ya que cada navegador
los muestra de manera diferente. Se usan para dividir correctamente en secciones nuestra pagina, tal y como se
hace en un documento de texto normal.
Cambiando el Tipo de Letra
Todas estas etiquetas que permiten cambiar de una manera u otra el aspecto del tipo de letra que se esta utilizando y se pueden utilizar con cadenas de caracteres dentro de un parrafo.
<B>... </B>
Pone el texto en negrita.
<I>... </I>
Representa el texto en cursiva.
<U>... </U>
Para subrayar texto.
<S>... </S>
Para tachar.
<SUP>... </SUP>
Letra superndice.
<SUB>... </SUB>
Letra subndice.
<BIG>... </BIG>
Incrementa el tamano del tipo de letra.
<SMALL>... </SMALL>
Disminuye el tamano del tipo de letra.
Otros Elementos
Por u ltimo, se presentan algunas etiquetas que no afectan al texto y que se pueden incorporar a una pagina.
<HR>
Inserta una barra horizontal.
<BR>
Salto de lnea.
<!-- ... -->
Comentarios.
114

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET

5.2.3.

Caracteres Especiales

Las maquinas manejan la informacion en formato binario(unos y ceros). Estos, a su vez, forman numeros, los
cuales se traducen en letras. Como? Mediante tablas. Se puede asignar el valor 65 a la letra A, el 66 a la B, etc..
El problema esta en que cada computador es de un fabricante distinto y puede adoptar una tabla diferente al
resto. Para evitarlo, existen diversos estandares, y el mas extendido es el ASCII. De hecho, actualmente, todos los
computadores tienen la misma tabla ASCII para los primeros 127 caracteres. Pero esa tabla no contiene vocales
con acento, ni enes, ni smbolos de abrir interrogacion o exclamacion... Esto pasa por dejar que los norteamericanos
sean quienes construyan los computadores.
HTML 2.0 eligio como tabla estandar la ISO-Latin-1, que comparte con la ASCII los 127 caracteres e incluye
unos cuantos mas hasta el numero 255.
Caracteres Extendidos en HTML
La manera de incluir los caracteres extendidos (cuyo numero esta mas alla del 127) consiste en encerrar el
codigo entre los caracteres &# y ;. As pues, lo siguiente:
&#189;
debera resultar en el caracter un medio( 12 ). Tambien existe una serie de sinonimos para poder recordar con mas
facilidad estos caracteres. As, por ejemplo, &#189; tambien se puede escribir como &frac12;.
Caracteres de Control
En el HTML existen cuatro caracteres de control, que se usan para formar etiquetas, establecer atributos, etc..
Para poder emplearlos sin riesgo, se deben escribir los siguiente codigos:
Codigo
&lt;
&gt;
&amp;
&quot;
&nbsp;

5.2.4.

Resultado
<
>
&
"
Espacio en Blanco

Enlaces

Las siglas HTML significan HyperText Markup Language, es decir, es un lenguaje para hipertexto. Existen
multiples formatos de hipertexto (por ejemplo, los archivos de ayuda de Windows) y lo que tienen en comun es
que todos poseen enlaces.
Un enlace es una zona de texto o graficos que si son seleccionados, trasladan a otro documento de hipertexto o
a otra posicion dentro del documento actual. Siendo HTML el lenguaje de Internet, la diferencia que posee con
respecto a otros tipos de hipertexto, es que ese otro documento puede estar fsicamente en la otra punta del planeta.
Son los enlaces lo que hacen de la World Wide Web lo que es.
La Etiqueta <A>
Para incorporar un enlace hay que utilizar esta etiqueta. Todo lo que se encierre entre <A> y </A>, ya sea texto
o imagenes, sera considerado como enlace y sufrira dos modificaciones:
Se visualizara de manera distinta en el navegador. Generalmente, el texto aparecera subrayado y de un color
distinto al habitual, y las imagenes estaran rodeadas por un borde del mismo color que el del texto de un enlace.
Al pulsar sobre un enlace, se desplegara al documento al que apuntaba el enlace. Para que un enlace funcione, se
le debe especificar una direccion. Lo que se logra de la siguiente manera:
<A HREF="direccion" >Pulsame</A>
La direccion debe estar en formato URL(Uniform Resource Locator).
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

115

5.2. HTML
Anclas
Como ya se dijo, es posible acceder a una posicion de un documento HTML. Para hacerlo, primero se debe
especificar el lugar del documento al que se quiere acceder:
<A NAME="ancla" >
As, un link en la misma pagina que redireccione a esta posicion, sera:
<A HREF="#ancla" >Vamos a donde antes</A>
Tambien, se puede acceder a anclas situadas en documentos remotos. Para ello se anade el nombre del ancla a la
URL, as:
<A HREF="enlaces.html#ancla" >Otra vez</A>

5.2.5.

Listas

Listas de Itemes
La etiqueta <UL> permite presentar listas de elementos sin orden alguno. Cada elemento de la lista ira normalmente precedido por un crculo. Por ejemplo,
<UL>
<LI>Primer elemento
<LI>Segundo elemento
</UL>
Que se vera como:
Primer elemento
Segundo elemento
La etiqueta <UL> admite los siguientes atributos:
COMPACT
Indica al navegador que debe representar la lista de la manera mas compacta posible.
TYPE="..."
Indica al navegador el dibujo que debe precedir a cada elemento de la lista. Para mayor flexibilidad, se
admite tambien como parametro de <LI>. El tipo puede ser disc, circle o square.
Listas Enumeradas
La etiqueta <OL> permite presentar listas de elementos enumerados. Por ejemplo,
<OL>
<LI>Primer elemento
<LI>Segundo elemento
</OL>
Que se vera como:
1.

Primer elemento

2.

Segundo elemento

La etiqueta <OL> admite los siguientes atributos:


116

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


COMPACT
Indica al navegador que debe representar la lista de la manera mas compacta posible.
TYPE="..."
Indica al navegador el tipo de numeracion que precedera a cada elemento de la lista. Para mayor flexibilidad
se admite tambien como parametro de <LI>. El Tipo puede ser 1, a, A, i o I.
START="num"
Indica al navegador el numero por el que se comenzara a contar los elementos de la lista.
Listas de Definiciones
Este es el u nico tipo de lista que no utiliza la etiqueta <LI>. Al tener como objetivo presentar una lista de
definiciones, de modo que tiene que representar de manera distinta el objeto definido y la definicion. Esto se hace
por medio de las etiquetas <DT> y <DD>:
<DL>
<DT>Primer elemento<DD>Es un elemento muy bonito.
<DT>Segundo elemento<DD>Este, en cambio, es peor.
</DL>
Que se vera como:
Primer elemento
Es un elemento muy bonito.
Segundo elemento
Este, en cambio, es peor.
La etiqueta <DL> solo admite como parametro el ya conocido COMPACT, que tiene el mismo comportamiento que
con los otros dos tipos de lista anteriores.

5.2.6.

Imagenes

Para incluir graficos e imagenes en paginas se utiliza la etiqueta <IMG> de esta manera:
<IMG SRC="archivo grafico" ALT="descripcion" >
El atributo SRC especifica el nombre del archivo que contiene el grafico. Los formatos estandares en la red son el
GIF y el JPG. Las u ltimas versiones de Netscape y Explorer aceptan tambien el formato PNG.
El atributo ALT especifica el texto que se mostrara en lugar del grafico en aquellos navegadores que no sean capaces
de mostrarlos (como el Lynx) o en el supuesto de que el usuario los haya desactivado. Algunos navegadores lo
muestran cuando se pasa el mouse por encima de la imagen. Es por eso que, aunque algunos usuarios no lo lleguen
a ver nunca, conviene ponerlo siempre. De hecho, el estadar HTML 4.0 obliga a hacerlo.
Existen dos atributos que, aunque opcionales, conviene indicar siempre: la altura y el ancho del grafico en pixels.
De este modo, el navegador puede mostrar un recuadro del tamano real de la imagen, mientras la va cargando de
la red, y as poder mostrar el resto de la pagina correctamente mientras tanto.
<IMG SRC="graficos/dwnldns.gif" ALT="Netscape 6.0" WIDTH=88 HEIGHT=31>
Imagenes y Enlaces
Suele ser comun incluir enlaces dentro de un grafico. En ese caso, por defecto, los navegadores le pondran un
borde al grafico para indicar que efectivamente es un enlace. Practico, pero la mayora de las veces bastante poco
estetico. Por medio del atributo BORDER se puede alterar el grosor de ese borde o incluso eliminarlo dejandolo en
cero.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

117

5.2. HTML
<A HREF="http://www.netscape.com" >
<IMG SRC="graficos/dwnldns.gif" ALT="Netscape 6.0" WIDTH=88 HEIGHT=31 BORDER=0>
</A>
Alineacion respecto al texto
Para poder disenar paginas que contengan texto y graficos a la vez, HTML proporciona, por medio del atributo
ALIGN, las siguientes maneras de alinear una imagen respecto del texto que la acompana:
TOP
Coloca el punto mas alto de la imagen coincidiendo con el mas alto de la lnea de texto actual.
MIDDLE
Alinea el punto medio (en altura) de la imagen con la base del texto.
BOTTOM
Valor por defecto. Alnea el punto mas bajo de la imagen con la base del texto.
LEFT
Coloca la imagen a la izquierda del texto.
RIGHT
Coloca la imagen a la derecha del texto.

5.2.7.

Formateo Fino

Lo ideal cuando se trabaja con texto sera poder cambiarlo al tamano mas conveniente, ponerlo de colores y
cambiar el tipo de letra. Todo esto se puede lograr con la etiqueta <FONT>.
Colores
Para cambiar el color del texto se utiliza el atributo COLOR. La manera de especificar el color es comun a todas
las etiquetas HTML: o bien indicando el nombre, si es un color normal, o bien especificando el porcentaje de rojo,
verde y azul(codigo RGB) del mismo. Los colores reconocidos son los siguientes:
black
green

silver
lime

gray
olive

white
yellow

maroon
navy

red
blue

purple
teal

fuchsia
aqua

<FONT COLOR="red" >Estoy en rojo</FONT>


El modo de indicar el color RGB es el siguiente:
<FONT
<FONT
<FONT
<FONT
<FONT
<FONT
<FONT
<FONT
<FONT

COLOR="#FF0000"
COLOR="#EF0000"
COLOR="#DF0000"
COLOR="#CF0000"
COLOR="#BF0000"
COLOR="#AF0000"
COLOR="#9F0000"
COLOR="#8F0000"
COLOR="#7F0000"

>D</FONT>
>E</FONT>
>G</FONT>
>R</FONT>
>A</FONT>
>D</FONT>
>A</FONT>
>D</FONT>
>O</FONT>

Lo que da como resultado, lo siguiente:


DEGRADADO
La primera componente en hexadecimal es el rojo, la segunda el verde y la tercera el azul(Red-Green-Blue, RGB).
118

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


del Texto
Tamano
El parametro utilizado para indicar el tamano es SIZE. Puede utilizarse para indicar tamanos absolutos, del 1
al 7.
El tamano por defecto es 3. Tambien se pueden utilizar los modificadores + y - para indicar un incremento (o
decremento) relativo del tamano del tipo de letra. As, por ejemplo, si se indica un tamano de -2 se pide al
navegador que muestre el tipo de letra dos veces mas pequeno que el actual.
<FONT SIZE=2>Tama
no 2<FONT SIZE="+3" >Tama
no 5</FONT></FONT>
Tipo de Letra
Por u ltimo, se puede especificar el nombre del tipo de letra que se desea utilizar gracias al parametro FACE.
Como en principio no se tiene manera de saber que tipo de letra tiene instalado el computador del usuario que
esta viendo la pagina, se puede indicar mas de uno separado por comas. Si el navegador no encuentra ninguno
seguira utilizando el que tiene por defecto:
<FONT FACE="Helvetica,Arial,Times" >No s
e como voy a salir exactamente</FONT>
De todos modos es recomendable no utilizar confiadamente este atributo en Internet, ya que impide que todos
puedan ver las paginas como se desea. Internet, siempre que lo permitan Microsoft y Netscape, debe ser lo mas
estandar posible.

5.2.8.

Estructura del Documento

La estructura de un documento HTML se puede resumir as:


tipo de documento
<HTML>
<HEAD>
<TITLE>titulo de la p
agina</TITLE>
cosas que afectan a la p
agina, pero no a su contenido
</HEAD>
<BODY ATRIBUTO>
contenido de la p
agina
</BODY>
</HTML>
En el tipo de documento se debe especificar a que estandar de HTML responde la pagina entre una de las siguientes
opciones:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN" >
Cumple el estandar HTML 2.0
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN" >
Cumple el estandar HTML 3.2
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
Cumple el estandar HTML 4.0
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" >
Cumple el estandar HTML 4.0 y no contiene ademas elementos desaconsejables
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" >
Es una definicion de marcos que cumple el estandar HTML 4.0
El HTML 4.0 considera desaconsejables aquellos elementos que, aun siendo soportados, han sido sustituidos por
otros mas potentes y, por ello, es posible que sean eliminados del estandar HTML en el futuro.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

119

5.2. HTML
La Cabecera
Suele ser el lugar mas indicado para colocar aquellos elementos de la pagina que no alteran el contenido de la
misma, aunque si la forma de presentarlo y su comportamiento. Es por eso que es el lugar mas recomendable para
colocar los scripts y las hojas de estilo.
Ademas del ttulo de la pagina, uno de los elementos que se pueden incluir aqu son los META. Entre otras cosas,
sirven para indicar propiedades de la pagina como pueda ser el nombre de su autor. Por ejemplo,
<META NAME="GENERATOR" CONTENT="Mozilla/4.03 [es] (Win95; I) [Netscape]" >
Esto indica la herramienta con que se ha creado la pagina (en este caso la version 4.03 en espanol para Windows
95 del Composer de Netscape). Estas son las propiedades mas comunes:
AUTHOR
Autor de la pagina.
GENERATOR
Herramienta utilizada para hacer la pagina.
CLASSIFICATION
Palabras que permite clasificar la pagina dentro de un buscador jerarquico (como Yahoo).
KEYWORDS
Palabras clave por las que encontraran la pagina los buscadores.
DESCRIPTION
Descripcion del contenido de la pagina.
Hay tambien otro elemento interesante que se puede incluir en nuestras cabeceras. Cuando se especfica una URL
relativa en un enlace, en principio, es para acceder a una pagina situada en el mismo servidor. Sin embargo, si se
especfica:
<BASE HREF="http://www.inf.utfsm.cl" >
Ahora todas las URLs relativas se referiran al servidor http://www.inf.utfsm.cl.
El Cuerpo
A continuacion, una breve descripcion de los atributos mas importantes que admite la etiqueta <BODY>:
BACKGROUND
Permite definir un grafico de fondo para la pagina.
BGCOLOR
Permite definir el color de fondo de la pagina.
BGPROPERTIES
Cuando es igual a FIXED el grafico definido como fondo de la pagina permanecera inmovil.
TEXT
Cambia el color del texto.
LINK
Cambia el color de un enlace no visitado (por defecto azul).
VLINK
Cambia el color de un enlace ya visitado (por defecto purpura).
120

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


ALINK
Cambia el color que toma un enlace mientras se estan pulsando (por defecto rojo).
MARGINWIDTH y MARGINHEIGHT
Especifican el numero de pixels que dejara de margen entre el borde de la ventana y el contenido de la
pagina. Se suelen utilizar para dejarlos a cero.
No resulta recomendable cambiar los colores del texto y enlaces a no ser que exista alguna dificultad al leerlos
por haber cambiado el fondo, ya que en muchas ocasiones el usuario ha podido cambiarlos en las opciones de su
navegador y estaran ya a su gusto.

5.2.9.

Formularios

Una de las mayores ventajas de la web es que resulta interactiva. Los usuarios de una pagina no tienen mas
que escribir al autor de la misma para comentarle cualquier cosa de ella. Sin embargo, si se desea manipular
alguna informacion concreta(responder a alguna pregunta, seleccionar entre varias opciones, etc..) se deben utilizar
formularios. Por ejemplo,
<FORM ACTION=" " METHOD=POST>
Nombre:<BR><INPUT NAME="nombre" TYPE=TEXT SIZE=32>
<BR>>Cuantos son dos y dos?<BR>
<INPUT NAME="Respuesta" TYPE=RADIO VALUE="mal" >3<BR>
<INPUT NAME="Respuesta" TYPE=RADIO VALUE="bien" >4<BR>
<INPUT NAME="Respuesta" TYPE=RADIO VALUE="mal" >5<BR>
<INPUT TYPE="SUBMIT" VALUE="Comprobar" >
</FORM>
Que se vera as:

El boton no hace nada porque no se ha definido que debe hacer, normalmente se redirecciona a otra pagina que
procesa la informacion, esta se ingresa en el atributo ACTION de la etiqueta <FORM>. Tambien se suele llamar a
una funcion javascript, para hacer validaciones, por ejemplo.
Todos los elementos de un formulario deben estar encerrados entre <FORM> y </FORM>. Como atributos cabe
destacar tres. ACTION define la accion que debera ejecutar el formulario, cuando se presione un boton de tipo
SUBMIT. Puede ser una direccion de correo (precedida del inevitable mailto:), en cuyo caso se debe anadir el
atributo ENCTYPE="text/plain" para que se reciba texto legible.
Por otro lado, se tiene el atributo METHOD que define la manera en que se mandara los datos del formulario. Es
recomendable utilizar POST. En el caso de que se mande el formulario a una direccion de correo electronico, es
obligatorio usarlo.
Ahora se veran uno a uno todos los elementos que se pueden incluir en un formulario. Se vera que todos ellos
tienen algo en comun. Como el resultado de cualquier formulario es una lista de variables y valores asignados a
las mismas, todos ellos tendran un atributo en comun: el nombre de su variable. El atributo tambien sera comun a
todos: NAME.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

121

5.2. HTML
Cajas de Texto
Existen tres maneras de conseguir que el usuario introduzca texto en un formulario. Las dos primeras se
obtienen por medio de la etiqueta <INPUT>:
<INPUT TYPE=TEXT>
<INPUT TYPE=PASSWORD>
El primero dibujara una caja donde se puede escribir texto(de una sola lnea). El segundo es equivalente, pero no
se vera lo que se ingrese en e l. Estos son los atributos para modificarlos:
SIZE
Tamano de la caja de texto.
MAXLENGTH
Numero maximo de caracteres que puede introducir el usuario.
VALUE
Texto por defecto que contendra la caja.
Por otro lado, puede que se necesite que el usuario pueda introducir mas de una lnea. En ese caso, se utilizara la
siguiente etiqueta:
<TEXTAREA>Por defecto</TEXTAREA>
Lo que se incluya entre las dos etiquetas sera lo que se muestre por defecto dentro de la caja. Admite estos
parametros:
ROWS
Filas que ocupara la caja de texto.
COLS
Columnas que ocupara la caja de texto.
Opciones
Si lo que se desea es que el usuario decida entre varias opciones, se puede hacer de dos modos. El primero, es
el que se vio en el ejemplo inicial:
3<INPUT NAME="Respuesta" TYPE=RADIO VALUE="mal" ><BR>
4<INPUT NAME="Respuesta" TYPE=RADIO VALUE="bien" ><BR>
5<INPUT NAME="Respuesta" TYPE=RADIO VALUE="mal" ><BR>
Para asociar varios botones de radio a una misma variable se les pone a todos ellos el mismo NAME. Aparte de esto
acepta los siguientes parametros:
VALUE
Este es el valor que asignara a la variable.
CHECKED
Si se indica en una de las opciones esta sera la que este activada por defecto.
Pero tambien se tiene la posibilidad de usar listas desplegables. Para emplearlas se deben utilizar dos etiquetas,
SELECT y OPTION:
122

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


<SELECT NAME="Navegador" >
<OPTION>Netscape
<OPTION>Explorer
<OPTION>Opera
<OPTION>Lynx
<OPTION>Otros
</SELECT>
Los atributos que admite SELECT son los siguientes:
SIZE
El numero de opciones que se visualizan. Si es mayor que uno, se visualizara una lista de seleccion y, si no,
se visualizara una lista desplegable(un ComboBox).
MULTIPLE
Si se indica, se podra seleccionar mas de una opcion.
Y OPTION estos:
VALUE
Este es el valor que asignara a la variable.
SELECTED
Si se indica en una de las opciones, esta sera la seleccionada por defecto.
Botones del Formulario
Existen botones de dos tipos: uno que se utiliza para mandar el formulario y otro que sirve para limpiar todo
lo que haya seleccionado el usuario:
<INPUT TYPE=SUBMIT><BR>
<INPUT TYPE=RESET>
Se puede cambiar el texto que el navegador pone por defecto en esos botones, utilizando el atributo VALUE.
Otros Elementos
Puede que se necesite que el usuario sencillamente confirme o niegue una condicion. Esto se puede lograr por
medio de controles de confirmacion:
<INPUT NAME="moreinfo" TYPE=CHECKBOX>Desea recibir mayor informaci
on
Si se quiere que el control este activado por defecto, se le anade el atributo CHECKED. El formulario asignara a la
variable NAME el valor on u off.
Por u ltimo, existe la posibilidad de que se necesite tener en el formulario alguna variable con un valor previamente
asignado y que no sea visible por el usuario. Por ejemplo, aunque no es la manera o ptima de hacerlo, parametros
de control:
<INPUT TYPE=HIDDEN NAME="TipoMenu" VALUE="VERTICAL" >
Cuando el usuario haga clic sobre un boton de tipo SUBMIT, tambien se enviara la variable TipoMenu, con el valor
asignado.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

123

5.2. HTML

5.2.10.

Tablas

Las tablas son posiblemente la manera mas clara de organizar la informacion. Tambien es el modo mas adecuado de disenar paginas de texto y graficos de una manera mas controlada que con los parametros ALIGN.
Las tablas se definen de la siguiente manera. Primero, las caractersticas de la tabla, luego las de cada fila y dentro
de e sta, cada celda. As pues, una tabla con 2 filas y 3 columnas se declarara as:
<TABLE>
<TR>
<TD>1,1</TD>
<TD>1,2</TD>
<TD>1,3</TD>
</TR>
<TR>
<TD>2,1</TD>
<TD>2,2</TD>
<TD>2,3</TD>
</TR>
</TABLE>
Resultado:
1,11,21,3
2,12,22,3
Como se puede apreciar, no tiene mucho aspecto de tabla. Quedara mejor con bordes, y con mayor espacio entre
celdas o mayor anchura. Estos son los aspectos que se pueden cambiar con los atributos de TABLE:
BORDER
Especifica el grosor del borde que se dibujara alrededor de las celdas. Por defecto es cero, lo que significa
que no dibujara borde alguno.
CELLSPACING
Define el numero de pixels que separaran las celdas.
CELLPADDING
Especifica el numero de pixels que habra entre el borde de una celda y su contenido.
WIDTH
Especifica el ancho de la tabla. Puede estar tanto en pixels como en porcentaje del ancho total disponible
para e l, es decir, 100 % si se quiere ocupar todo el ancho de la ventana del navegador.
ALIGN
Alinea la tabla a izquierda (LEFT), derecha (RIGHT) o centro (CENTER).
Si ahora, por ejemplo, se define la tabla anterior como:
<TABLE BORDER=1 WIDTH="50 %" ALIGN=CENTER>
Se vera lo siguiente:

124

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


Definicion de Filas
Ahora que se ha definido la tabla, es necesario hacer lo mismo con las filas. Cada fila se define con una etiqueta
TR, que tiene los siguientes atributos:
ALIGN
Alinea el contenido de las celdas de la fila horizontalmente, a la izquierda (LEFT), la derecha (RIGHT) o al
centro (CENTER).
VALIGN
Alinea el contenido de las celdas de la fila verticalmente, hacia arriba (TOP), abajo (BOTTOM) o al centro
(MIDDLE).
Definicion de Celdas
Por u ltimo, queda definir cada celda por medio de las etiquetas TD y TH. Estas etiquetas son equivalentes, pero
la u ltima se utiliza para encabezados, de modo que su interior se escribira por defecto en negrita y centrado. Estos
son los atributos de ambas:
ALIGN
Alinea el contenido de la celda horizontalmente, a la izquierda (LEFT), la derecha (RIGHT) o al centro
(CENTER).
VALIGN
Alinea el contenido de la celda verticalmente, hacia arriba (TOP), abajo (BOTTOM) o al centro (MIDDLE).
WIDTH
Especifica el ancho de la celda. Se puede especificar tanto en pixels como en porcentaje, teniendo en cuenta que, en este u ltimo caso, sera un porcentaje respecto al ancho total de la tabla (no de la ventana del
navegador).
NOWRAP
Impide que al interior de la celda, se inserten saltos de lnea para ajustar el texto al ancho de la celda.
COLSPAN
Especifica el numero de celdas de la fila situadas a la derecha de la actual que se unen a e sta (incluyendo la
celda en que se declara este parametro). Es por defecto uno. Si se indica cero, se uniran todas las celdas que
queden a la derecha.
ROWSPAN
Especifica el numero de celdas de la columna situadas debajo de la actual, que se unen a e sta.
Posiblemente los dos u ltimos parametros no queden claros sin ejemplos. De hecho, aun entendiendo perfectamente
su funcion, es habitual confundir uno con otro. Por lo tanto, se vera una tabla de 3 3 con una celda que se une a
una de la derecha y otra que se une a su adyacente por debajo:
<TABLE BORDER=1>
<TR>
<TD COLSPAN=2>1,1 y 1,2</TD>
<TD>1,3</TD>
</TR>
<TR>
<TD ROWSPAN=2>2,1 y 3,1</TD>
<TD>2,2</TD>
<TD>2,3</TD>
</TR>
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

125

5.2. HTML
<TR>
<TD>3,2</TD>
<TD>3,3</TD>
</TR>
</TABLE>
Resultado:

Como se puede ver, cuando se declara una celda con ROWSPAN o COLSPAN, no se deben declarar las celdas absorbidas.

5.2.11.

Marcos

Un marco (o frame) es una ventana independiente dentro de la ventana del navegador. Cada marco tiene sus
bordes y sus propias barras de desplazamiento. As, cada pagina se dividira, en la practica, en varias paginas independientes.
Para crearlos se necesita un documento HTML especfico, el documento de definicion de marcos. En e l se especifican el tamano y posicion de cada marco y el documento HTML que contendra. A continuacion, un ejemplo de
este tipo de documento:
<HTML>
<HEAD>
<TITLE>Mi primera p
agina con marcos</TITLE>
</HEAD>
<FRAMESET COLS="20 %,80 %" >
<FRAME NAME="indice" SRC="indice.html" >
<FRAME NAME="principal" SRC="introduccion.html" >
<NOFRAMES>
<P>Lo siento, pero s
olo podr
a ver esta p
agina si su navegador tiene
la capacidad de visualizar marcos.
</NOFRAMES>
</FRAMESET>
</HTML>
Se observa que la cabecera de la pagina es similar a un documento normal, pero el habitual BODY es sustituido
por un FRAMESET. En cada FRAMESET se divide la ventana actual (sea la principal o un marco) en varias ventanas
definidas por el atributo COLS o por ROWS. En estos atributos, separado por comas, se define el numero de marcos
y el tamano de cada uno.
Dentro del FRAMESET se definen cada uno de los marcos, dandoles un nombre y especificando el archivo HTML
que le corresponde mediante la etiqueta FRAME. Tambien, se especifica lo que visualizara el usuario en el supuesto
(cada vez mas raro) de que su navegador no soporte frames dentro de la etiqueta NOFRAMES. Ahora se veran todos
estos elementos en mayor detalle.
Etiqueta FRAMESET
Segun el estandar, esta etiqueta solo debera contener el numero y tamano de cada marco, pero las extensiones
de Netscape y Explorer al estandar, obligan a estudiar un par de parametros mas.
126

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


En general, los navegadores dibujan un borde de separacion entre los marcos. Esto se puede manejar de dos
maneras: utilizando el atributo BORDER en las etiquetas FRAME de cada uno de los marcos contiguos o incluyendo
el atributo FRAMEBORDER en la etiqueta FRAMESET.
Tambien se puede controlar el espacio ente marcos, mediante el atributo FRAMESPACING.
Por u ltimo, los parametros COLS y ROWS, se les debe asignar una lista de tamanos separada por comas. Se admiten
los siguientes formatos de tamano:
Con Porcentajes:
Al igual que con las tablas, se puede definir el tamano de un marco como un porcentaje del espacio total
disponible.
Absolutos:
Si se utiliza un numero a secas, el marco correspondiente tendra el tamano especificado en pixels.
Sobre el Espacio Sobrante:
Si se utiliza un asterisco(*), se hace referencia al espacio sobrante. Se puede utilizar este smbolo en varios
marcos, que se repartiran el espacio equitativamente. As, un marco con un espacio de 3*, sera tres veces
mas grande que su companero, que tiene un asterisco solo.
Por ejemplo, el siguiente codigo es una muestra de como combinar los tres metodos:
<FRAMESET COLS="10 %,*,200,2*" >
Supongase que el ancho total de la ventana son 640 pixels. El primer marco ocupara el 10 %, es decir, 64 pixels.
El tercero necesita 200 pixeles, luego quedan 476 pixeles para los otros dos marcos. Como el cuarto debe tener
el doble de espacio que el segundo, se tienen aproximadamente 158 pixels para este u ltimo y 316 para el cuarto
marco.
Tener cuidado cuando se usan valores absolutos en la definicion de marcos; se debe asegurar de tener al menos un
marco con un tamano relativo, si se quiere estar seguro del aspecto final de la pagina.
Por u ltimo, considerese que las etiquetas FRAMESET se pueden anidar. Esto se hace colocando otro FRAMESET
donde normalmente se colocara una etiqueta FRAME tal que as:
<FRAMESET COLS="20 %,80 %" >
<FRAME NAME="indice" SRC="indice.html" >
<FRAMESET ROWS="*,80" >
<FRAME NAME="principal" SRC="introduccion.html))
<FRAME NAME="ejemplos" SRC="ejemplo.html))
</FRAMESET>
</FRAMESET>
El resultado del anidamiento se puede contemplar a continuacion:

Etiqueta FRAME
Esta etiqueta define las caractersticas de un marco determinado. Estos son los atributos que admite:
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

127

5.2. HTML
NAME
Asigna un nombre a un marco para que despues se pueda hacer referencia a e l.
SRC
Indica la direccion del documento HTML que ocupara el marco.
SCROLLING
Decide si se colocan o no barras de desplazamiento al marco para que poder navergar por su contenido. Su
valor es por defecto AUTO, que deja al navegador la decision. Las otras opciones que se tienen son YES y NO.
NORESIZE
Si se especifica el usuario no podra cambiar de tamano el marco.
FRAMEBORDER
Es identico a su homonimo en la etiqueta FRAMESET.
MARGINWIDTH
Permite cambiar los margenes horizontales dentro de un marco. Se representa en pixels.
MARGINHEIGHT
Igual al anterior pero para margenes verticales.
Acceso a Otros Marcos
Por defecto, cuando se pulsa sobre un enlace situado dentro de un marco, la nueva pagina a la que se quiere
acceder, sera cargada en ese mismo marco. Es posible que se desee que esto no ocurra. Por ejemplo, si se tiene
un marco que sirve de ndice y otro donde se muestran los contenidos, sera deseable que los enlaces del marco
ndice se abrieran en el otro marco. Esto es posible hacerlo gracias al atributo TARGET.
Este atributo se puede usar en tres etiquetas: A, AREA y BASE. En las dos primeras sirve para indicar el marco en
el que se cargara ese enlace en particular y el u ltimo modifica el marco en el que por defecto se cargan todos los
enlaces.
Pero para que un atributo funcione, es habitual que se asigne un valor, y TARGET no es una excepcion. Para indicarle
el marco que se desea, se le asigna el nombre del mismo. As, en el ejemplo anterior, si en el marco llamado indice,
se tiene un enlace que se quiera abrir en el marco principal, se utiliza:
<A HREF="pagina.html" TARGET="principal" >
Tambien existen cuatro nombres reservados que se pueden utilizar en el parametro TARGET:
top
Elimina todos los marcos existentes y muestra la nueva pagina en la ventana original del navegador sin
marcos.
blank
Muestra la nueva pagina en una ventana nueva y sin nombre del navegador.
self
Muestra la nueva pagina en el marco donde esta declarado el enlace.
parent
Muestra la nueva pagina en el FRAMESET que contiene al marco donde se declara el enlace. En el ejemplo
anterior, un enlace situado en el marco ejemplo cuyo parametro TARGET fuese igual a parent, eliminara
la separacion entre los marcos ejemplos y principal y mostrara en ese nuevo marco la nueva pagina.
128

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET

5.3.

Java Server Pages

Java Server Pages (JSP) permite separar la parte dinamica de las paginas Web del HTML estatico. Simplemente se escribe el HTML regular de forma normal. Luego, se encierra el codigo de las partes dinamicas entre
etiquetas especiales, la mayora de las cuales empiezan con "< %" y terminan con " %>". Por ejemplo, aqu se
muestra una seccion de una pagina JSP que resulta en algo as como Ud. acaba de ganar $2 Millones,
jugando Loto para una URL como http://host/azar.jsp?juego=Loto:
Ud. acaba de ganar <B>$ < %=new java.util.Random().nextInt(10) %>Millones</B>,
jugando <I>< %= request.getParameter("juego") %></I>
Normalmente se usa la extension .jsp, y los archivos JSP se instalan en el mismo sitio que una pagina Web
normal. Aunque lo que se escriba, frecuentemente se parezca a un archivo HTML normal, detras de la escena,
la pagina JSP se traduce en un servlet, donde el HTML estatico simplemente se imprime en el flujo de salida
estandard asociado con el metodo service() del servlet. Esto normalmente solo se hace la primera vez que se
solicita la pagina, y se puede solicitar la pagina explicitamente cuando se instala por primera vez, si se quiere estar
seguro de que el primer usuario real no tenga un retardo momentaneo cuando la pagina JSP sea traducida a un
servlet, y este sea compilado y cargado. Observese tambien, que muchos servidores Web permiten definir alias
para que una URL que parece apuntar a un archivo HTML, realmente apunte a un servelt o a una pagina JSP.
Ademas del HTML normal, hay tres tipos de construcciones JSP que se pueden incrustar en una pagina JSP:
elementos de script, directivas y acciones. Los elementos de script permiten especificar codigo Java que se convertira en parte del servlet resultante, las directivas permiten controlar la estructura general del servlet, y las acciones
permiten especificar componentes que deberan ser usuados, y de otro modo controlar el comportamiento del
motor JSP. Para simplificar los elementos de script, se tiene acceso a un numero de variables predefinidas como
request del fragmento de codigo anterior.

5.3.1.

Plantilla de Texto

En muchos casos, un gran porcentaje de las paginas JSP consistira en HTML estatico, conocido como plantilla de texto. En casi todos lo s aspectos, este HTML es HTML normal, sigue la mismas reglas de sintaxis, y
simplemente pasa a traves del cliente por el servlet creado para manejar la pagina. Hasta puede ser creado con
cualquier herramienta que se desee para generar paginas Web.
La u nica excepcion a la regla de que la plantilla de texto se pasa tal y como es es que, si se quier tener "< %" en
la salida, se debe escribir "<\ %" en la plantilla de texto.

5.3.2.

Elementos de Script

Los elementos de script permiten insertar codigo Java dentro del servlet que se generara desde la pagina JSP
actual. Hay tres formas:
Expresiones que son evaluadas e insertadas en la salida.
Scriptlets que se insertan dentro del metodo service del servlet, y
Declaraciones que se insertan en el cuerpo de la clase del servlet, fuera de cualquier metodo existente.
Expresiones
Una expresion JSP se usa para insertar valores Java directamente en la salida. Tiene la siguiente forma:
< %= expresion %>
La expresion es evaluada, convertida a un string, e insertada en la pagina. Esta evaluacion se realiza durante la
ejecucion (cuando se solicita la pagina) y as se tiene total acceso a la informacion sobre la solicitud. Por ejemplo,
esto muestra la fecha y hora en que se solicito la pagina:
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

129

5.3. JAVA SERVER PAGES


La fecha: < %= new java.util.Date() %>
Para simplificar estas expresiones, hay un gran numero de variables predefinidas que se pueden usar. Estos objetos
implcitos se describen mas adelante con mas detalle, pero para el proposito de las expresiones, los mas importantes
son:
request: Un HttpServletRequest, que permite la comunicacion del servidor a la pagina.
response: Un HttpServletResponse, que permite la comunicacion de la pagina al servidor.
session: Un HttpSession asociada con el request, si existe, que contiene la informacion de la sesion de
trabajo del usuario.
out: Un PrintWriter, una version con buffer del tipo JspWriter, usada para envar la salida al cliente.
Aqu un ejemplo:
Su m
aquina: < %= request.getRemoteHost() %>
Scriptlets
Si se quiere hacer algo mas complejo que insertar una simple expresion, los scriptlets JSP permiten insertar
codigo arbitrario dentro del servlet que sera construido al generar la pagina. Los Scriptlets tienen la siguiente
forma:
< % codigo %>
Los Scriptlets tienen acceso a las mismas variables predefinidas que las expresiones. Por eso, por ejemplo, si se
quiere que la salida aparezca en la pagina resultante, se debe usar la variable out:
<%
String queryData = request.getQueryString();
out.println("Datos atachados: "+ queryData);
%>
Observese que el codigo dentro de un scriptlet se insertara exactamente como esta escrito, y cualquier HTML
estatico (plantilla de texto) anterior o posterior al scriptlet, se convierte en sentencias print. Esto significa que
los scriptlets no necesitan completar las sentencias Java, y los bloques abiertos pueden afectar al HTML estatico
fuera de los scriplets. Por ejemplo, el siguiente fragmento JSP, contiene una mezcla de texto y scritplets:
< % if (Math.random() <0.5) { %>
Voy a ver tele
< % } else { %>
Voy a trabajar
< % } %>
Que se traducira en algo como:
< % if (Math.random() <0.5) { %>
out.println("Voy a ver tele");
< % } else { %>
out.println("Voy a trabajar");
< % } %>
Si se quiere usar los caracteres " %>" dentro de un scriptlet, se debe usar "\ %>".
130

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


Declaraciones
Una declaracion JSP permite definir metodos o campos que seran insertados dentro del cuerpo principal de la
clase Servlet (fuera del metodo service() que procesa la peticion). Tiene la siguiente forma:
< %! codigo %>
Como las declaraciones no generan ninguna salida, normalmente se usan en conjuncion con expresiones o scriptlets. Por ejemplo, aqu se tiene un fragmento JSP, que imprime el numero de veces que se ha solicitado la pagina
actual desde que el servidor se arranco (o la clase del servlet se modifico o se recargo):
< %! private int accessCount = 0; %>
Cantidad de accesos a la p
agina:
< %= ++accessCount %>
Como con los scriptlet, si se quiere usar los caracteres " %>", se debe usar "\ %>".

5.3.3.

Directivas

Una directiva JSP afecta a la estructura general de la clase Servlet. Normalmente tienen la siguiente forma:
< % directiva AtributoA="valor1"... AtributoN="valorN" %>
Hay dos tipos principales de directivas: page , que permite importar clases, personalizar la superclase del servlet,
etc. e include , que permite insertar un archivo dentro de la clase Servlet al momento que el archivo JSP es
traducido a un servlet.
La Directiva page
La directiva page permite definir uno o mas de los siguientes atributos(sensibles a las mayusculas):
import
Permite especificar los paquetes que deben ser importados. Por ejemplo:
< % page import="java.util.*" %>
El atributo import es el u nico que puede aparecer multiples veces.
contentType
Especifica el tipo MIME de la salida. El valor por defecto es text/html. Por ejemplo, la directiva:
< % page contentType="text/plain" %>
Tiene el mismo resultado que el scriptlet:
< % response.setContentType("text/plain"); %>
isThreadSafe
Un valor true (por defecto), indica un procesamiento del servlet normal, donde multiples peticiones pueden procesarse concurrentemente con un solo ejemplar del servlet, bajo la suposicion que el autor sincroniza
las variables de ejemplar. Un valor false , indica que el servlet debera implementar SingleThreadModel,
con peticiones enviadas serialmente o con peticiones concurrentes, siendo entregadas a distintos ejemplares
del servlet.
session
Un valor true (por defecto), indica que la variable predefinida session(del tipo HttpSession) debera
unirse a la sesion existente si existe una, y si no existe, se debera crear una nueva sesion para unirla. Un
valor false , indica que no se usaran sesiones, y los intentos de acceder a la variable session resultaran
ser errores al momento en que la pagina JSP sea traducida a un servlet.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

131

5.3. JAVA SERVER PAGES


buffer
Esto especifica el tamano del buffer para el JspWriter out en kilobytes. El valor por defecto es especfico
del servidor, y debera ser de al menos 8Kb.
autoflush
Un valor true (por defecto), indica que el buffer debera descargase cuando este lleno. Un valor false
, raramente utilizado, indica que se debe lanzar una excepcion cuando el buffer se sobrecargue. Un valor
false , es ilegal cuando se usa buffer="none".
extends
Esto indica la superclase del servlet que se va a generar. Se debe usar con extrema precaucion, ya que el
servidor podra utilizar una superclase personalizada.
info
Define un string que puede usarse para ser recuperado mediante el metodo getServletInfo.
errorPage
Especifica una pagina JSP que se debera procesar, si se lanzara cualquier Throwable, pero no fuera capturado en la pagina actual.
isErrorPage
Indica si la pagina actual actua o no como pagina de error de otra pagina JSP. El valor por defecto es false
.
La Directiva include
Esta directiva permite incluir archivos en el momento en que la pagina JSP es traducida a un servlet. La
directiva tiene esta forma:
< % include file="url relativa" %>
La URL especificada normalmente se interpreta como relativa a la pagina JSP a la que se refiere. Los contenidos
del archivo incluido son analizados como texto normal JSP, y as pueden incluir HTML estatico, elementos de
script, directivas y acciones.
Por ejemplo, muchos sitios incluyen una pequena barra de navegacion en cada pagina. Debido a los problemas
con los marcos HTML, esto normalmente se implementa mediante una pequena tabla que cruza la parte superior
de la pagina o el lado izquierdo, con el HTML repetido para cada pagina del sitio. La directiva include es una
forma natural de hacer esto, ahorrando a los desarrolladores el mantenimiento engorroso de copiar realmente el
HTML en cada archivo separado, sin mencionar los costos de mantenimiento. Aqu se tiene un ejemplo:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
...
</HEAD>
<BODY>
< % include file="/navbar.html" %>
...
</BODY>
</HTML>
Observese que como la directiva include inserta los archivos en el momento en que la pagina es traducida, si
la barra de navegacion cambia, es necesario re-traducir todas las paginas JSP que la referencian. Esto es un buen
132

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


compromiso en una situacion como esta, ya que las barras de navegacion no cambian frecuentemente, y se quiere
que el proceso de inclusion sea tan eficiente como sea posible. Si, sin embargo, los archivos incluidos cambian de
forma mas frecuente, se podra usar la accion jsp :include en su lugar. Esto incluye el archivo en el momento
en que se solicita la pagina JSP, como se describe posteriormente.

5.3.4.

Variables Predefinidas

Para simplificar el codigo en expresiones y scriplets JSP, se tienen ocho variables predefinidas, algunas veces
llamadas objetos implcitos. Las variables disponibles son: request, response, out, session, application,
config, pageContext, y page.
request
Este es el HttpServletRequest asociado con la peticion, y permite usar los parametros de la peticion (mediante el metodo getParameter()), el tipo de peticion (GET, POST, HEAD, etc.), y las cabeceras HTTP entrantes
(cookies, Referer, etc.). Estrictamente hablando, se permite que la peticion sea una subclase de ServletRequest
distinta de HttpServletRequest, si el protocolo de la peticion es distinto de HTTP.
response
Este es el HttpServletResponse asociado con la respuesta al cliente. Permite entre otras cosas, obtener el
flujo de salida (ver out mas abajo).
out
Este es el PrintWriter usado para envar la salida al cliente, que se obtiene(automaticamente) del objeto
response. Es una version con buffer de PrintWriter llamada JspWriter. Observese que se puede ajustar
el tamano del buffer, o incluso desactivarlo, usando el atributo buffer de la directiva page . out se usa casi
exclusivamente en scriptlets, ya que las expresiones JSP obtienen(automaticamente) un lugar en el flujo de salida,
y por eso raramente se refieren explcitamente a out.
session
Este es el objeto HttpSession asociado con la peticion. Las sesiones se crean automaticamente, por ello esta
variable se une incluso si no hubiera una sesion de referencia entrante. La u nica excepcion es al usar el atributo
session de la directiva page para desactivar las sesiones, en cuyo caso los intentos de referenciar la variable
session causaran un error al momento de traducir la pagina JSP a un servlet.
application
Este es el ServletContext obtenido mediante getServletConfig().getContext(). Mediante sus metodos getAttribute y setAttribute, es posible almacenar cualquier tipo de dato arbitrario y compartirlo con
otras paginas JSP o servlet, ya que todas las paginas de una misma aplicacion web comparten el mismo objeto
application
config
Este es el objeto ServletConfig para esta pagina.
pageContext
JSP presenta una nueva clase llamada PageContext para encapsular caractersticas de uso especficas del
servidor como JspWriters de alto rendimiento. Tambien puede ser un objeto alternativo para compartir datos,
pero como es especfico de cada servidor es poco usado.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

133

5.3. JAVA SERVER PAGES


page
Esto es solo un sinonimo de this , y aun no es muy u til.

5.3.5.

Accciones

Las acciones JSP usan construcciones de sntaxis XML para controlar el comportamiento del motor de Servlets. Se puede insertar un archivo dinamicamente, reutilizar componentes JavaBeans, generar codigo generico para
la invocacion de un applet, al igual que la etiqueta APPLET o reenviar al usuario a otra pagina.
Notar que, como en XML, los nombre de elementos y atributos son sensibles a las mayusculas.
Las acciones que se veran en este documento son:
Accion jsp:include
Esta accion permite insertar archivos en una pagina que esta siendo generada. La sntaxis es:
<jsp:include page ="URL" flush="true" />
Al contrario que la directiva include , que inserta el archivo en el momento de la conversion de la pagina JSP a
un servlet, esta accion inserta el archivo en el momento en que la pagina es solicitada. Esto se paga con eficiencia, e
imposiblita a la pagina incluida contener codigo JSP general (no puede seleccionar cabeceras HTTP, por ejemplo),
pero se obtiene una significante flexibilidad.
Accion jsp:forward
Esta accion permite reenviar la peticion a otra pagina. Tiene un solo atributo, page, que debera consistir en
una URL relativa. Este podra ser un valor estatico, o podra ser calculado en el momento de la peticion, como en
estos dos ejemplo:
<jsp:forward page="/utils/errorReporter.jsp" />
<jsp:forward page=" < %= someJavaExpression %>" />

5.3.6.

Ejemplo

Aqu se muestra un sencillo ejemplo que muestra el uso de expresiones, scriptlets, declaraciones y directivas
JSP:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<TITLE>Ejemplo de JSP</TITLE>
<META NAME="author" CONTENT="Michael Moossen" >
<META NAME="keywords" CONTENT="JSP,Java Server Pages,servlets" >
<META NAME="description" CONTENT="Un ejemplo de JSP." >
</HEAD>
<BODY BGCOLOR="#FDF5E6" TEXT="#000000" LINK="#0000EE"
VLINK="#551A8B" ALINK="#FF0000" >
<CENTER>
<TABLE BORDER=5 BGCOLOR="#EF8429" >
<TR><TH>
Ejemplo de Java Server Pages
</TH></TR>
134

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


</TABLE >
</CENTER>
<P>
Algunos mecanismos JSP para crear contenido din
amico:
<UL>
<LI><B>Expresiones:</B><BR>
Su m
aquina: < %= request.getRemoteHost() %>.
<LI><B>Scriptlets:</B><BR>
< % out.println("Datos atachados: "+ request.getQueryString()); %>
<LI><B>Declaraciones:</B><BR>
< %! private int accessCount = 0; %>
Cantidad de accesos a la p
agina: < %= ++accessCount %>
<LI><B>Directivas:</B><BR>
< % page import= "java.util.*" %>
La fecha: < %= new Date() %>
</UL>
</BODY>
</HTML>
Aqu un resultado tpico:

5.4.

Applets

Un applet es una mini-aplicacion, escrita en Java, que se ejecuta en un browser (Netscape Navigator, Microsoft
Internet Explorer, etc.) al cargar una pagina HTML que incluye informacion sobre el applet a ejecutar por medio
de los tags <APPLET>... </APPLET>.
A continuacion se detallan algunas caractersticas de los applets:
Los archivos de Java compilados(*.class) se descargan a traves de la red desde un servidor Web o servidor
HTTP hasta el browser en cuya JVM se ejecutan. Pueden incluir tambien archivos de imagenes y sonido.
Los applets no tienen ventana propia: se ejecutan en la ventana del browser (en un panel).
Por la propia naturaleza abierta de Internet, los applets tienen importantes restricciones de seguridad, que
se comprueban al llegar al browser: solo pueden leer y escribir archivos en el servidor del que han venido,
solo pueden acceder a una limitada informacion sobre el computador en el que se estan ejecutando, etc. Con
ciertas condiciones, los applets de confianza (trusted applets) pueden pasar por encima de estas restricciones.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

135

5.4. APPLETS
Aunque su entorno de ejecucion es un browser, los applets se pueden probar sin necesidad de browser con la
aplicacion appletviewer del JDK de Sun.
Las caractersticas de los applets mas importantes, desde el punto de vista del programador, son:
Los applets no tienen un metodo main() con el que comience la ejecucion. El papel central de su ejecucion
lo asumen otros metodos que se veran posteriormente.
Todos los applets derivan de la clase java.applet.Applet. Los applets deben redefinir ciertos metodos
heredados de Applet que controlan su ejecucion: init(), start(), stop(), destroy().
Se heredan otros muchos metodos de las super-clases de Applet, relacionados con la generacion de interfaces graficas de usuario (AWT). As, los metodos graficos se heredan de Component, mientras que la
capacidad de anadir componentes de interface de usuario se hereda de Container y de Panel.
Los applets tambien suelen redefinir ciertos metodos graficos: los mas importantes son paint() y update(),
heredados de Component y de Container; y repaint() heredado de Component.
Los applets disponen de metodos relacionados con la obtencion de informacion, como por ejemplo:
getAppletInfo(), getAppletContext(), getParameterInfo(), getParameter(), getCodeBase(),
getDocumentBase(), e isActive().
El metodo showStatus() se utiliza para mostrar informacion en la barra de estado del browser.
Existen otros metodos relacionados con imagenes y sonido: getImage(), getAudioClip(), play(), etc.

5.4.1.

El Tag APPLET de HTML

Para llamar a un applet desde una pagina HTML se utiliza el tag <APPLET>...</APPLET>, cuya forma general
es (los elementos opcionales aparecen entre corchetes):
<APPLET CODE="miApplet.class" [CODEBASE="unURL"] [NAME="unName"] WIDTH="wpixels"
HEIGHT="hpixels" [ALT="TextoAlternativo"] ARCHIVE="file1.zip, file2.jar" >
[<PARAM NAME="MyName1" VALUE="valueOfMyName1" >]
[<PARAM NAME="MyName2" VALUE="valueOfMyName2" >]
</APPLET>
El atributo NAME permite dar un nombre opcional al applet, con objeto de poder comunicarse con otros applets o
con otros elementos que se esten ejecutando en la misma pagina. El atributo ARCHIVE permite indicar uno o varios
archivos Jar o Zip (separados por comas), donde se deben buscar las clases. El atributo ALT permite indicar texto
alternativo para browsers que reconocen el tag <APPLET> pero no pueden ejecutar el applet.
Otros posibles atributos de <APPLET> son ALIGN, VSPACE y HSPACE, que tienen el mismo significado que el tag
IMG de HTML.
Paso de Parametros
Los tags PARAM permiten pasar diversos parametros desde el archivo HTML al programa Java del applet, de
forma analoga a la que se utiliza para pasar argumentos a main().
Cada parametro tiene un nombre y un valor. Ambos se dan en forma de String, aunque el valor sea numerico.
El applet recupera estos parametros y, si es necesario, convierte los Strings en valores numericos. El valor de los
parametros se obtienen con el siguiente metodo de la clase Applet:
String getParameter(String name)
La conversion de Strings a los tipos primitivos se puede hacer con los metodos asociados a los wrappers que Java
proporciona para dichos tipos fundamentales (Integer.parseInt(String), Double.valueOf(String), ...).
En los nombres de los parametros no se distingue entre mayusculas y minusculas, pero s en los valores, ya que
seran interpretados por un programa Java, que s distingue.
136

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


El programador del applet debera prever siempre unos valores por defecto para los parametros del applet, para el
caso de que en la pagina HTML que llama al applet no se definan.
El metodo getParameterInfo() devuelve una matriz de strings (String[][]) con informacion sobre cada uno
de los parametros soportados por el applet: nombre, tipo y descripcion, cada uno de ellos en un String. Este
metodo debe ser redefinido por el programador del applet y utilizado por la persona que prepara la pagina HTML
que llama al applet. En muchas ocasiones seran personas distintas, y e sta es una forma de que el programador del
applet de informacion al usuario.

5.4.2.

Ciclo de Vida de un Applet

El ciclo de vida de una applet, es como sigue: primero se inicializa usando el metodo init(), luego comienza
su ejecucion el en metodo start(), esta ejecucion puede ser detenida temporalmente a traves del metodo stop, y
finalizada por medio del metodo destroy(). A continuacion se detalla el manejo de cada uno de estos metodos:
init()
Se llama automaticamente al metodo init() en cuanto el browser o visualizador carga el applet. Este
metodo se ocupa de todas las tareas de inicializacion, realizando las funciones del constructor (al que el
browser no llama).
start()
El metodo start() se llama automaticamente en cuanto el applet se hace visible, despues de haber sido
inicializada. Se llama tambien cada vez que el applet se hace de nuevo visible, despues de haber estado
oculta (por dejar de estar activa esa pagina del browser, al cambiar el tamano de la ventana del browser, al
hacer reload, etc.).
Es habitual crear threads en este metodo para aquellas tareas que, por el tiempo que requieren, dejaran sin
recursos al applet o incluso al browser. Las animaciones y ciertas tareas a traves de Internet son ejemplos de
este tipo de tareas.
stop()
El metodo stop() se llama de forma automatica al ocultar el applet (por haber haber dejado de estar activa la
pagina del browser, por hacer reload o resize, etc.). Con objeto de no consumir recursos inutilmente, en este
metodo se suelen parar los threads que esten corriendo en el applet, por ejemplo para mostrar animaciones.
destroy()
Se llama a este metodo cuando el applet va a ser descargado para liberar los recursos que tenga reservados
(excepto la memoria). Generalmente, no es necesario redefinir este metodo, pues el que se hereda cumple
bien con esta mision.
Generalmente el programador tiene que redefinir uno o mas de estos metodos, pero no tiene que preocuparse de
llamarlos: el browser se encarga de hacerlo. Ademas, si el applet usa funciones graficas, se deben manejar algunos
metodos adicionales, que se veran a continuacion.

5.4.3.

Metodos para Dibujar un Applet

Los applets son aplicaciones graficas que aparecen en una zona de la ventana del browser. Por ello deben
redefinir los metodos graficos paint() y update() de la clase java.awt.Container de la cual hereda Applet.
El metodo paint() se declara en la forma:
void paint(Graphics g)
El objeto grafico g pertenece a la clase java.awt.Graphics, que siempre debe ser importada por el applet. Este
objeto define un contexto o estado grafico para dibujar (metodos graficos, colores, fonts, etc.) y es creado por el
browser.
Todo el trabajo grafico del applet (dibujo de lneas, formas graficas, texto, etc.) se debe incluir en el metodo
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

137

5.4. APPLETS
paint(), porque este metodo es llamado cuando el applet se dibuja por primera vez y tambien de forma automatica cada vez que el applet se debe redibujar.
En general, el programador crea el metodo paint() pero no lo suele llamar. Para pedir explcitamente al sistema
que vuelva a dibujar el applet (por ejemplo, por haber realizado algun cambio) se utiliza el metodo repaint(),
que es mas facil de usar, pues no requiere argumentos. Este metodo es parte de java.awt.Component, de la cual
Applet tambien hereda. El metodo repaint() se encarga de llamar a paint() a traves de update().
El metodo repaint() llama a update(), que borra todo pintando de nuevo con el color de fondo y luego llama
a paint(). A veces esto produce parpadeo de pantalla o flickering. Existen dos formas de evitar el flickering:
Redefinir update() de forma que no borre toda la ventana sino solo lo necesario.
Redefinir paint() y update() para utilizar doble buffer.
Eliminacion de Parpadeo Redefiniendo el Metodo update()
El problema del flicker se localiza en la llamada al metodo update(), que borra todo pintando con el color
de fondo y despues llama a paint(). Una forma de resolver esta dificultad, es redefinir el metodo update(), de
forma que se adapte mejor al problema que se trata de resolver.
Una posibilidad es no repintar todo con el color de fondo, no llamar a paint() e introducir en update() el
codigo encargado de realizar los dibujos, cambiando solo aquello que haya que cambiar. A pesar de esto, es
necesario redefinir paint(), pues es el metodo que se llama de forma automatica cuando la ventana de Java es
tapada por otra que luego se retira. Una posible solucion es hacer que paint() llame a update(), terminando por
establecer un orden de llamadas opuesto al de defecto. Hay que tener en cuenta que, al no borrar todo pintando con
el color de fondo, el programador tiene que preocuparse de borrar de forma selectiva entre frame y frame, lo que
sea necesario. Los metodos setClip() y clipRect() de la clase Graphics permiten hacer que las operaciones
graficas no surtan efecto fuera de un a rea rectangular previamente determinada. Al ser dependiente del tipo de
graficos concretos de que se trate, este metodo no siempre proporciona soluciones adecuadas.
Tecnica de Doble Buffer
La tecnica del doble buffer proporciona la mejor solucion para el problema de las animaciones, aunque requiere
una programacion algo mas complicada. La idea basica del doble buffer es realizar los dibujos en una imagen
invisible, distinta de la que se esta viendo en la pantalla, y hacerla visible cuando se ha terminado de dibujar, de
forma que aparezca instantaneamente.
Para crear el segundo buffer o imagen invisible, hay que crear un objeto de la clase Image del mismo tamano que
la imagen que se esta viendo y crear un contexto grafico u objeto de la clase Graphics que permita dibujar sobre
la imagen invisible. Esto se hace con las sentencias:
Image imgInv;
Graphics graphInv;
Dimension dimInv;
Dimension d = size(); // se obtiene la dimensi
on del panel
en la clase que controle el dibujo (por ejemplo en una clase que derive de Panel). En el metodo update(), se
modifica el codigo de modo que primero se dibuje en la imagen invisible y luego e sta se haga visible:
public void update(Graphics g) {
// se comprueba si existe el objeto invisible y si sus dimensiones son correctas
if ((graphInv==null ) || (d.width!=dimInv.width) || (d.height!=dimInv.height)) {
dimInv = d;
// se llama al m
etodo createImage de la clase Component
imgInv = createImage(d.width, d.height);
// se llama al m
etodo getGraphics de la clase Image
graphInv = imgInv.getGraphics();
138

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


}
// se establecen las propiedades del contexto gr
afico invisible,
// y se dibuja sobre
el
graphInv.setColor(getBackground());
...
// finalmente se hace visible la imagen invisible a partir del punto (0, 0)
// utilizando el propio panel como ImageObserver
g.drawImage(imgInv, 0, 0, this );
} // fin del m
etodo update()
Los graficos y las animaciones son particularmente u tiles en los applets.

5.4.4.

Comunicacion entre Applet y Browser

La comunicacion entre el applet y el browser en el que se esta ejecutando, se puede controlar mediante la
interfaz AppletContext (package java.applet). AppletContext es una interfaz implementada por el browser,
cuyos metodos pueden ser utilizados por el applet para obtener informacion y realizar ciertas operaciones, como
por ejemplo, sacar mensajes breves en la barra de estado del browser. Hay que tener en cuenta que la barra de
estado es compartida por el browser y los applets, lo que tiene el peligro de que el mensaje sea rapidamente sobreescrito por el browser u otros applets y que el usuario no llegue a enterarse del mensaje.
Los mensajes breves a la barra de estado se producen con el metodo showStatus(), como por ejemplo,
getAppletContext().showStatus("Cargado desde el archivo "+ filename);
Los mensajes mas importantes se deben dirigir a la salida estandar o a la salida de errores, que en Netscape
Navigator es la Java Console. Estos mensajes se pueden enviar con las sentencias:
System.out.print();
System.out.println();
System.err.print();
System.err.println();
Para mostrar documentos HTML en una ventana del browser se pueden utilizar los metodos siguientes:
showDocument(URL miUrl, String target)
Muestra un documento HTML en el frame del browser indicado por target (name, top, parent, blank,
self).
showDocument(URL miUrl)
Muestra un documento HTML en la ventana actual del browser.
Un applet puede conseguir informacion de otros applets que estan corriendo en la misma pagina del browser,
enviarles mensajes y ejecutar sus metodos. El mensaje se enva invocando los metodos del otro applet con los
argumentos apropiados.
Algunos browsers exigen, para que los applets se puedan comunicar, que provengan del mismo browser o incluso
del mismo directorio (que tengan el mismo codebase).
Por ejemplo, para obtener informacion de otros applets se pueden utilizar los metodos:
getApplet(String name)
Devuelve el applet llamado name (o null si no la encuentra). El nombre del applet se pone con el atributo
opcional NAME o con un parametro llamado NAME.
getApplets()
Devuelve una enumeracion con todos los applets de la pagina.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

139

5.4. APPLETS
Para poder utilizar todos los metodos de un applet que se esta ejecutando en la misma pagina HTML (y no solo
los metodos comunes heredados de Applet), debe hacerse un casting del objeto de la clase Applet, que se obtiene
como valor de retorno de getApplet(), a la clase concreta del applet.
Para que pueda haber respuesta (es decir, comunicacion en los dos sentidos), el primer applet que enva un mensaje
debe enviar una referencia a s misma por medio del argumento this .

5.4.5.

Sonidos en Applets

La clase Applet y la interfaz AudioClip permiten utilizar sonidos en applets. A continucacion se muestran
algunos metodos interesantes al respecto.
Metodos de Applet:
AudioClip getAudioClip(URL url)
Devuelve el objeto especificado por url, que implementa la interfaz AudioClip.
AudioClip getAudioClip(URL url, String name)
Devuelve el objeto especificado por url (direccion base) y name (direccion relativa).
void play(URL url), void play(URL url, String name)
Ejecuta el AudioClip correspondiente a la direccion especificada.
Metodos de la interface AudioClip (en java.applet):
void loop()
Ejecuta el sonido repetidamente.
void play()
Ejecuta el sonido una sola vez.
void stop()
Detiene la ejecucion del sonido.
Respecto a la carga de sonidos, por lo general es mejor cargar los sonidos en un thread distinto (creado en el metodo
init()) que en el propio metodo init(), que tardara en devolver el control y permitir al usuario empezar a
interaccionar con el applet.
Si el sonido no ha terminado de cargarse (en el thread especial para ello) y el usuario interacciona con el applet
para ejecutarlo, el applet puede darle un aviso de que no se ha terminado de cargar.

5.4.6.

Imagenes en Applets

Los applets admiten los formatos JPEG y GIF para representar imagenes a partir de archivos localizados en
el servidor. Estas imagenes se pueden cargar con el metodo getImage() de la clase Applet, que puede tener las
formas siguientes:
Image getImage(URL url)
Image getImage(URL url, String name)
Estos metodos devuelven el control inmediatamente. Las imagenes se cargan cuando se da la orden de dibujarlas
en pantalla. El dibujo se realiza entonces de forma incremental, a medida que el contenido va llegando.
Para dibujar imagenes se utiliza el metodo drawImage() de la clase Graphics, que tiene las formas siguientes:
boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer)
boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor,
ImageObserver observer)
140

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


El primero de ellos dibuja la imagen con su tamano natural, mientras que el segundo realiza un cambio en la escala
de la imagen.
Los metodos drawImage() van dibujando la parte de la imagen que ha llegado, con su tamano, a partir de las
coordenadas (x, y) indicadas, utilizando bgcolor para los pixels transparentes.
Estos metodos devuelven el control inmediatamente, aunque la imagen no este del todo cargada. En este caso
devuelve false . En cuanto se carga una parte adicional de la imagen, el proceso que realiza el dibujo avisa
al ImageObserver especificado. java.awt.image.ImageObserver es una interfaz implementada por Applet
que permite seguir el proceso de carga de una imagen.

5.4.7.

Threads en Applets

Un applet puede ejecutarse con varios threads, y en muchas ocasiones sera necesario o conveniente hacerlo
as. Hay que tener en cuenta que un applet se ejecuta siempre en un browser (o en la aplicacion appletviewer).
As, los threads en los que se ejecutan los metodos principales init(), start(), stop() y destroy()
dependen del browser o del entorno de ejecucion. Los metodos graficos paint(), update() y repaint()
se ejecutan siempre desde un thread especial del AWT.
Algunos browsers dedican un thread para cada applet en una misma pagina; otros crean un grupo de threads para
cada applet (para poderlos matar al mismo tiempo, por ejemplo). En cualquier caso se garantiza que todos los
threads creados por los metodos principales pertenecen al mismo grupo.
Se deben introducir threads en applets siempre que haya tareas que consuman mucho tiempo (cargar una imagen
o un sonido, hacer una conexion a Internet, etc.). Si estas tareas pesadas se ponen en el metodo init(), bloquean
cualquier actividad del applet o incluso de la pagina HTML hasta que se completen. Las tareas pesadas pueden ser
de dos tipos:
Las que solo se hacen una vez.
Las que se repiten muchas veces.
Un ejemplo de tarea que se repite muchas veces puede ser una animacion. En este caso, la tarea repetitiva se
ejecuta, por ejemplo, dentro de un bucle while , dentro del thread. El thread se debera crear dentro del metodo
start() del applet y destruirse en stop(). De este modo, cuando el applet no esta visible, se dejan de consumir
recursos.
Al crear el thread en el metodo start(), se pasa una referencia al applet con la palabra this , que se refiere al
applet. El applet debera implementar la interfaz Runnable, y por tanto debe definir el metodo run(), que es el
centro del thread.
Un ejemplo de tarea que se realiza una sola vez es la carga de una imagen, que se realiza automaticamente en un
thread especial.
Sin embargo, los sonidos no se cargan en threads especiales de forma automatica; los debe crear el programador
para cargarlos en background. Este es un caso tpico de un programa producer-consumer: el thread es el producer
y el applet el consumer. Los threads deben estar sincronizados, para lo que se utilizan los metodos wait() y
notifyAll().
A continuacion se presenta un ejemplo de thread con una tarea repetitiva:
public void start() {
if (repetitiveThread == null ) {
repetitiveThread = new Thread(this ); // se crea un nuevo thread
}
repetitiveThread.start(); // se arranca el thread creado: start() llama a run()
}
public void stop() {
repetitiveThread = null ; // para parar la ejecuci
on del thread
}
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

141

5.4. APPLETS

public void run() {


...
while (Thread.currentThread() == repetitiveThread) {
... // realizar la tarea repetitiva.
}
}
El metodo run() se detendra en cuanto se ejecute el metodo stop(), porque la referencia al thread esta a null .

5.4.8.

Applets como Aplicaciones

Es muy interesante desarrollar aplicaciones que pueden funcionar tambien como applets y viceversa. En concreto, para hacer que un applet pueda ejecutarse como una aplicacion, pueden seguirse las siguientes instrucciones:
1. Se anade un metodo main() a la clase MiApplet (que deriva de Applet).
2. El metodo main() debe crear un objeto de la clase MiApplet e introducirlo en un Frame.
3. El metodo main() debe tambien ocuparse de hacer lo que hara el browser, es decir, llamar a los metodos
init() y start() de la clase MiApplet.
4. Se puede anadir tambien una static inner class que derive de WindowAdapter y que gestione el
evento de cerrar la ventana de la aplicacion definiendo el metodo windowClosing(). Este metodo ejecuta
System.exit(0). Segun como sea el applet, el metodo windowClosing(), previamente debera tambien
llamar a los metodos MiApplet.stop() y MiApplet.destroy(), cosa que para los applets se encarga de
hacer el browser. En este caso, conviene que el objeto de MiApplet creado por main() sea static , en
lugar de una variable local.
A continuacion se presenta un ejemplo:
import java.applet.*;
import java.awt.event.*;
import java.awt.*;
public class MiApplet extends Applet {
static MiApplet unApplet = null ;
public
public
public
public

void
void
void
void

init() { System.out.println("init");}
start() { System.out.println("start");}
stop() { System.out.println("stop");}
destroy() { System.out.println("destroy");}

// clase para seguir el comportamiento de la ventana


static class WL extends WindowAdapter {
public void windowClosing(WindowEvent e) {
unApplet.stop();
unApplet.destroy();
System.exit(0);
}
public void windowDeactivated(WindowEvent e) {
unApplet.stop();
}
142

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET

public void windowActivated(WindowEvent e) {


unApplet.start();
}
} // fin de la clase WL
// programa principal
public static void main(String[] args) {
unApplet = new MiApplet();
Frame unFrame = new Frame("MiApplet");
unFrame.addWindowListener(new WL());
unFrame.add(unApplet, BorderLayout.CENTER);
unFrame.setSize(400,400);
unApplet.init();
unFrame.setVisible(true );
}
} // fin de la clase MiApplet

5.4.9.

Restricciones de Seguridad

Uno de los principales objetivos del entorno Java es hacer que los usuarios de navegadores se sientan seguros
cuando ejecutan cualquier applet. Para alcanzar este objetivo, se han restringido varias capacidades, de forma conservadora.
En esta seccion se veran las restricciones actuales de los applets, desde el punto de vista de como afectan al diseno
de los mismos.
Todo visualizador de applets tiene un objeto SecurityManager, que chequea las violaciones de seguridad de
los applets. Cuando un SecurityManager detecta una violacion, crea y lanza un objeto SecurityException.
Generalmetne, el constructor de la SecurityException imprime un mensaje de aviso en la salida estandar. Un
applet puede capturar las SecurityExceptions y reaccionar de forma apropiada, como avisar al usuario y saltar
a una forma segura (pero menos ideal) de realizar la tarea.
Algunos visualizadores de applets ocultan algunas SecurityExceptions, para que el applet nunca obtenga la
SecurityException. Por ejemplo, la implementacion del appletviewer del JDK de los metodos getApplet()
y getApplets() de AppletContext, simplemente capturan e ignoran cualquier SecurityExceptions. El usuario puede ver los mensajes de error en la salida estandar, pero el applet obtiene un resultado valido desde los
metodos. Esto tiene sentido, ya que desde getApplets() debera ser posible volver cualquier applet valido que
encuentre, incluso si encuentra unos invalidos (El appletviewer considera un applet valido si fue cargado desde
el mismo host que el applet que llamo a getApplets()).
Los applets tienen las siguientes restricciones:
Los applets no pueden cargar libreras o definir metodos nativos.
Los applets solo pueden usar su propio codigo Java y el API Java que proporciona el visualizador. Como
mnimo, a todo applet se le debe proporcionar acceso al API definido en los paquetes java.*.
Normalmente un applet no puede leer o escribir archivos en el host en el que se esta ejecutando. El
appletviewer del JDK permite algunas excepciones a esta regla especificadas por el usuario, pero por
ejemplo Netscape Navigator, no lo hace. Los applets en cualquier visualizador pueden leer archivos especificados con URLs completas, en lugar de con nombres de archivos. Un atajo para no tener que escribir
archivos, es tener un applet que reenve datos a una aplicacion en el servidor del que vino. Esta aplicacion
puede escribir los datos en archivos de su propio host.
Un applet no puede hacer conexiones de red excepto con el host del que vino. El atajo para esta restriccion
es hacer que el applet funcione con una aplicacion en el host del que vino. La aplicacion puede hacer sus
propias conexiones a cualquier lugar de la red.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

143

5.5. SEGURIDAD
Un applet no puede arrancar ningun programa en el host en el que se esta ejecutando.
Un applet no puede leer ciertas propiedades del sistema.
Las ventanas que muestran los applets tienen un aspecto distinto a las que muestran las aplicaciones. Las
ventanas de los applets tienen algun texto de aviso y una barra coloreada o una imagen. Esto ayuda al usuario
a distinguir las ventanas de los applets, de aquellas de las aplicaciones verdaderas.

5.5.

Seguridad

5.5.1.

Controlador de Seguridad

La seguridad se vuelve importante cuando se escriben programas que interactuan con Internet. Es imposible
que los computadores en Internet esten completamente seguros del ataque de unos pocos villanos externos. Sin
embargo, se pueden seguir algunos pasos para proporcionar un nivel de proteccion significante. Una de las formas
que proporciona Java frente a la seguridad, es a traves del uso de los controladores de seguridad. Un controlador
de seguridad implementa e impone una poltica de seguridad para una aplicacion.
Toda aplicacion Java puede tener su propio objeto controlador de seguridad, que actua como un guardia de seguridad a tiempo completo. La clase SecurityManager del paquete java.lang, es una clase abstracta que
proporciona la interfaz de programacion y una implementacion parcial para todos los controladores de seguridad
de Java.
Por defecto, una aplicacion no tiene controlador de seguridad. Esto es, el sistema de ejecucion de Java no crea
automaticamente un controlador de seguridad para cada aplicacion. Entonces, por defecto, una aplicacion permite
todas las operaciones que estan sujetas a las restricciones de seguridad.
Para cambiar este comportamiento indulgente, una aplicacion puede crear e instalar su propio controlador de seguridad. Sin embargo, hay que tener en cuenta que, los navegadores existentes y los visualizadores de applets
crean su propio controlador de seguridad cuando arrancan. As, un applet esta sujeto a las restricciones de acceso
que sean impuestas por el controlador de seguridad de la aplicacion particular en la que el applet se esta ejecutando.
Se puede obtener el controlador de seguridad actual de una aplicacion utilizando el metodo getSecurityManager()
de la clase System.
SecurityManager appsm = System.getSecurityManager();
Observese que getSecurityManager() devuelve null si no hay ningun controlador de seguridad actual en
la aplicacion, por lo que debera asegurarse de que tiene un objeto valido, antes de llamar a cualquiera de sus
metodos.
Una vez que se tiene el controlador de seguridad, se puede pedir permiso para permitir o prohibir ciertas operaciones. De hecho, muchas de las clases en los paquetes de Java hacen esto. Por ejemplo, el metodo System.exit(),
que finaliza el interprete Java, utiliza el metodo checkExit() del controlador de seguridad, para aprobar la operacion de salida.
SecurityManager security = System.getSecurityManager();
if (security != null ) {
security.checkExit(status);
}
Si el controlador de seguridad aprueba la operacion de salida, la llamada checkExit() retorna normalmente. Si
el controlador de seguridad prohibe la operacion, esta llamada lanza una SecurityException. De esta forma, el
controlador de seguridad permite o prohibe una operacion potencialmente danina, antes de que pueda ser completada.
La clase SecurityManager define muchos otros metodos utilizados para verificar otras clases de operaciones.
Por ejemplo, el metodo checkAccess(), verifica los accesos a los threads, y checkPropertyAccess() verifica
el acceso a la propiedad de sistema especificada. Cada operacion o grupo de operaciones tiene su propio metodo
checkXXX().
144

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


Ademas, el conjunto de metodos checkXXX(), representa el conjunto de operaciones de las clases de los paquetes
Java y el sistema de ejecucion de Java que ya estan sujetos a la proteccion del controlador de seguridad. Por eso,
normalmente, el codigo propio no tendra que llamar a ningun metodo checkXXX() las clases de los paquetes
de Java hacen esto a un nivel lo suficientemente bajo, de tal forma cualquier operacion representada por un metodo
checkXXX() ya esta protegida. Sin embargo, cuando se escriba un controlador de seguridad propio, se tendra que
sobreescribir algun metodo checkXXX() de SecurityManager, para modificar la poltica de seguridad de las
operaciones especficas, o se podra tener que anadir algunos propios para poner otras clases de operaciones para
el escrutinio del controlador de seguridad.

5.5.2.

Un Controlador de Seguridad Propio

Para escribir un controlador de seguridad propio, se debe crear una subclase de la clase SecurityManager.
Esta subclase debe sobreescribir varios metodos de SecurityManager, para personalizar las verificaciones y
aprobaciones necesarias para una aplicacion Java.
Esta seccion muestra un controlador de seguridad de ejemplo, que restringe la lectura y escritura en el sistema de
archivos. Para obtener la aprobacion del controlador de seguridad, un metodo que abra un archivo para leer, invoca
uno de los metodos checkRead() de SecurityManager, un metodo que abre un archivo para escribir, invoca a
uno de los metodos checkWrite() de SecurityManager. Si el controlador de seguridad aprueba la operacion,
el metodo checkXXX() retorna nomalmente, de otra forma checkXXX() lanza una SecurityException.
Para imponer una poltica restrictiva en los accesos al sistema de archivos, el ejemplo debe sobreescribir los metodos checkRead() y checkWrite() de SecurityManager. SecurityManager proporciona tres versiones de
checkRead() y dos versiones de checkWrite(). Cada una de ellas debera verificar si la aplicacion puede abrir
un archivo para I/O. Esta es una poltica implementada frecuentemente en los navegadores, para que los applets
cargados a traves de la red no puedan leer o escribir en el sistema local de archivos, a menos que el usuario lo
apruebe.
La poltica implementada por el ejemplo le pide al usuario una password cuando la aplicacion intenta abrir un
archivo para leer o escribir. Si la password es correcta se permite el acceso.
Todos los controladores de seguridad deben ser una subclase de SecurityManager. As, la
PasswordSecurityManager desciende de SecurityManager.
class PasswordSecurityManager extends SecurityManager {
. . .
}
Luego, PasswordSecurityManager declara un ejemplar de la variable privada password para contener la palabra clave que el usuario debe introducir, para permitir el acceso al sistema de archivos restringido. La palabra
clave, se selecciona durante la construccion.
PasswordSecurityManager(String pwd) {
super();
this .password = pwd;
}
El siguiente metodo en la clase PasswordSecurityManager es un metodo de ayuda privado llamado accessOK().
Este metodo le pide al usuario una password y la verifica. Si el usuairo introduce una password valida, el metodo
devuelve true , de otra forma devuelve false .
private boolean accessOK() {
int c;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String response;
System.out.println("Whats the secret password?");
try {
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

145

5.5. SEGURIDAD
response = br.readLine();
if (response.equals(password))
return true ;
else
return false ;
} catch (IOException e) {
return false ;
}
}
Finalmente, la clase PasswordSecurityManager sobreescribe los tres metodos checkRead() y los dos metodos
checkWrite().
public void checkRead(FileDescriptor filedescriptor) {
if (!accessOK())
throw new SecurityException("Not a Chance!");
}
public void checkRead(String filename) {
if (!accessOK())
throw new SecurityException("No Way!");
}
public void checkRead(String filename, Object executionContext) {
if (!accessOK())
throw new SecurityException("Forget It!");
}
public void checkWrite(FileDescriptor filedescriptor) {
if (!accessOK())
throw new SecurityException("Not!");
}
public void checkWrite(String filename) {
if (!accessOK())
throw new SecurityException("Not Even!");
}
Todos los metodos checkXXX() llaman a accessOK() para pedirle al usuario la password. Si el acceso falla, entonces checkXXX() lanza una SecurityException. De otra froma, checkXXX() retorna normalmente. Observese que SecurityException, es una excepcion en tiempo de ejecucion, y no necesita ser declarada en la clausula
throws de estos metodos.
checkRead() y checkWrite() son solo unos pocos de los muchos metodos checkXXX() de SecurityManager
que verifican varias clases de operaciones. Se pueden sobreescribir o anadir cualquier numero de metodos
checkXXX() para implementar una poltica de seguridad propia. No se necesita sobreescribir todos los metodos
checkXXX() de SecurityManager, solo aquellos que se quieran personalizar. Sin embargo, la implementacion por defecto proporcionada por la clase SecurityManager para todos los metodos checkXXX(), lanza una
SecurityException. En otras palabras, por defecto, la clase SecurityManager prohibe todas las operaciones
que estan sujetas a las restricciones de seguridad. Por lo que, podra ser que se tienen que sobreescribir muchos
metodos checkXXX() para obtener el comportamiento deseado.
Todos los metodos checkXXX() de la clase SecurityManager operan de la misma forma.
Si el acceso esta permitido, el metodo retorna.
Si el acceso no esta permitido, el metodo lanza una SecurityException.
As, implementar un controlador de seguridad es sencillo, solo se necesita:
146

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


Crear una subclase de SecurityManager.
Sobreescribir unos cuantos metodos.
El truco esta en determinar los metodos que se deben sobreescribir para implementar la poltica de seguridad
propia.

5.5.3.

Instalar un Controlador de Seguridad

Una vez que esta lista la subclase de SecurityManager, se debe instalar como el controlador de seguridad por
defecto de la aplicacion. Esto se puede hacer utilizando el metodo setSecurityManager() de la clase System.
Aqu se muestra una pequena aplicacion de prueba, SecurityManagerTest, que instala la clase
PasswordSecurityManager de la seccion anterior como el controlador de seguridad por defecto. Luego, para verificar que el controlador de seguridad esta en su lugar y es operacional, esta aplicacion abre dos archivos
uno para leer y otro para escribir y copia el contenido del primero en el segundo.
El metodo main() comienza con la instalacion del nuevo controlador de seguridad.
try {
System.setSecurityManager(new PasswordSecurityManager("tarzan"));
} catch (SecurityException se) {
System.out.println("SecurityManager already set!");
}
La segunda lnea del codigo anterior crea un nuevo ejemplar de la clase PasswordSecurityManager con la clave
"tarzan". Este ejemplar es pasado al metodo setSecurityManager() de la clase System, que instala el objeto
como el controlador de seguridad por defecto para la aplicacion que se esta ejecutando. Este controlador de seguridad permanecera efectivo durante toda la ejecucion de esta aplicacion.
Solo se puede seleccionar una vez el controlador de seguridad de una aplicacion. En otras palabras, una aplicacion Java solo pude invocar una vez a System.setSecurityManager() durante su ciclo de vida. Cualquier intento posterior de instalar un controlador de seguridad dentro de una aplicacion Java, resultara en una
SecurityException.
El resto del programa copia el contenido de este archivo inputtext.txt en un archivo de salida llamado
outputtext.txt. Es solo un texto que verifica que PasswordSecurityManager se ha instalado de forma apropiada.
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream("inputtext.txt")));
DataOutputStream fos = new DataOutputStream(new FileOutputStream(
"outputtext.txt"));
String inputString;
while ((inputString = br.readLine()) != null ) {
fos.writeBytes(inputString);
fos.writeByte(\n);
}
br.close();
fos.close();
} catch (IOException ioe) {
System.err.println("I/O failed for SecurityManagerTest.");
ioe.printStackTrace();
}
Las primeras dos lneas del codigo anterior son los accesos al sistema de archivos restringido. Estas llamadas a
metodos resultan en una llamada al metodo checkAccess() del PasswordSecurityManager.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

147

5.5. SEGURIDAD
Cuando se ejecute la aplicacion SecurityManagerTest, se pedira dos veces la password: una cuando la aplicacion abre el archivo de entrada y otra cuando abre el archivo de salida. Si se ingresa la password correcta, se
permite el acceso al objeto archivo y la aplicacion prosigue con la siguiente sentencia. Si se ingresa una
password incorrecta, checkXXX() lanza una SecurityException, que la aplicacion no intenta capturar por lo
que aplicacion termina.
Este es un ejemplo de la salida de aplicacion cuando se ingresa la password correcta la primera vez, pero no la
segunda.
Whats the secret password?
tarzan
Whats the secret password?
xxx
java.lang.SecurityException: Not Even!
at PasswordSecurityManager.checkWrite(PasswordSecurityManager.java:46)
at java.io.FileOutputStream.<init>(FileOutputStream.java:169)
at java.io.FileOutputStream.<init>(FileOutputStream.java:70)
at SecurityManagerTest.main(SecurityManagerTest.java:13)
Observese que el mensaje de error que muestra la aplicacion es el mensaje contenido en el metodo
checkWrite(String).

5.5.4.

Decidir que Metodos Sobreescribir del SecurityManager

Se podra tener que sobreescribir varios metodos checkXXX() del SecurityManager dependiendo de las
operaciones a las que se quiera que el controlador de seguridad les imponga restricciones.
La primera columna de la siguiente tabla, son objetos sobre los que se pueden realizar varias operaciones. La
segunda columna, lista los metodos de SecurityManager que aprueban las operaciones de los objetos de la
primera columna.
Operaciones sobre
Sockets

Threads
Cargador de Clases
Sistema de Archivos

Comandos del Sistema


Interprete
Paquetes
Red
Ventanas

148

Aprobadas por
checkAccept(String host, int port)
checkConnect(String host, int port)
checkConnect(String host, int port, Object executionContext)
checkListen(int port)
checkAccess(Thread thread)
checkAccess(ThreadGroup threadgroup)
checkCreateClassLoader()
checkDelete(String filename)
checkLink(String library)
checkRead(FileDescriptor filedescriptor)
checkRead(String filename)
checkRead(String filename, Object executionContext)
checkWrite(FileDescriptor filedescriptor)
checkWrite(String filename)
checkExec(String command)
checkExit(int status)
checkPackageAccess(String packageName)
checkPackageDefinition(String packageName)
checkSetFactory()
checkTopLevelWindow(Object window)

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 5. JAVA E INTERNET


Operaciones sobre
Propiedades del Sistema

Aprobadas por
checkPropertiesAccess()
checkPropertyAccess(String key)
checkPropertyAccess(String key, String def)

Dependiendo de la poltica de seguridad, se puede sobreescribir algunos o todos estos metodos. Por ejemplo,
supongase que se esta escribiendo un Navegador Web o un visualizador de applets, y se quiere evitar que los applets utilicen sockets. Se puede hacer esto sobreescribiendo los cuatro metodos que afectan al acceso a los sockets.
Muchos de los metodos checkXXX() son llamados en multiples situaciones. Por ejemplo, el metodo
checkAccess(ThreadGroup), es llamado cuando se crea un ThreadGroup, se selecciona su estado de servicio, se detiene su ejecucion, etc. Cuando se sobreescriba un metodo checkXXX(), es necesario asegurase de que
se comprenden todas las situaciones en las que puede ser llamado.
La implementacion por defecto suministrada por la clase SecurityManager para todos los metodos checkXXX()
es:
public void checkXXX(. . .) {
throw new SecurityException();
}
La mayora de las veces se querra que haga algo mas selectivo que prohibirlo todo! Por eso, podra ser u til
sobresscribir todos los metodos checkXXX() de SecurityManager.

Michael Moossen

Departamento de Informatica. U.T.F.S.M.

149

5.5. SEGURIDAD

150

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

Captulo 6

Interfaces Graficas
Antes de explicar que son las interfaces graficas y como se programan con java, es necesario definirlas.
En terminos simples la interfaz de una aplicacion, es aquel mecanismo que permite al usuario interactuar con
la la aplicacion. Existen varios niveles de interfaces, de las mas simples a las mas sofisticadas:
Interfaces de Consola
En general, en estos tipos de interfaces, el u nico dispositivo de entrada usado es el teclado. Se tienen tres
subtipos:
Lnea de Comandos
Este tipo de interfaz consiste en que el usuario puede especificar algunas opciones y parametros al
momento de ejecutar la aplicacion, mediante la lnea de comandos. Ejemplo:
javac -cp c:\codebase;. -jar tools.jar com.soft.Ejemplo
Interaccion Pregunta-Respuesta
Este tipo de interfaz consiste en que la apliacion le hace una serie de preguntas al usuario, las cuales
deben ser respondidas por el usuario antes de poder seguir la ejecucion de la aplicacion. Ejemplo:
Desea sobrescribir el archivo "miClase.java" (s/n)?
Ventanas basadas en Texto
Este tipo de interfaz consiste en emular un sistema de ventanas graficas, usando caracteres ASCII
extendidos, ofreciendo as al usuario la mayora de las ventajas de una interfaz grafica, incluyendo por
ejemplo el Mouse como dispositivo de entrada. Como ejemplo de aplicaciones que usan este tipo de
interfaces estan el Norton Disk Doctor for DOS y el Partition Magic for DOS
Interfaces Graficas
Este tipo de interfaz consiste en dibujar un sistemas de ventanas graficas, que contienen una serie de componentes graficas como botones, tablas, menus, a rboles jerarquicos, etc. para facilitar la interaccion con el
usuario. En general, una aplicacion de interfaz grafica necesita una plataforma grafica, que le provea de
todos los elementos basicos. Ademas, la manera estandar como que se ven las aplicaciones, esta fuertemente relacionada con la plataforma sobre la cual se ejecuta. Este tipo de interfaces generalemnete usan otros
dispositivos de entrada, ademas del teclado, como por ejemplo el Mouse, Voz, Joystick, Pantallas sensibles
(TouchScreen), etc. Ejemplo:

151


6.1. CONTEXTO HISTORICO

6.1.

Contexto Historico

Como las interfaces graficas dependen en gran medida de la plataforma en la cual se estan ejecutan, su implementacion varia mucho de una plataforma a otra. Por lo cual, el objetivo de tener interfaces graficas para java
portables e independientes de plataforma, no es de ninguna manera facil de lograr. Por este mismo es que la corta
historia de java, esta llena de intentos buscando este objetivo, unos mas existosos que otros, y otros simplementes
fracasados.
Las interfaces graficas en java comenzaron con la primera version de este. Esta version inclua un paquete
llamado AWT (Abstract Windows Toolkit), el cual era el punto mas debil de aquella primera version. Se trataba
de una capa de comunicacion entre java y las interfaces nativas, as solo ofrecia soporte para aquellos controles
disponibles en todos las plataformas por igual. Lo que lo haca muy limitado y poco flexible, ademas de tener un
pesimo desempeno. Los eventos eran controlados por cada componente, tipo Visual Basic, y presentaba una serie
de problemas serios con los eventos del Mouse. Debido a todo esto, es que AWT en la actualidad es solo un mal
recuerdo.
Luego, en la version 1.1 de java vino Swing junto con las Java Foundation Classes (JFC), lo cual puso un
poco de orden en la escena. Estaba programado 100 % en java, por lo tanto es 100 % portable, ofrece una mayor
funcionalidad de los componentes, cambio la arquitectura de manejo de eventos haciendolo mas flexible, tambien
introduce el manejo del Look & Feel por software. Se dice que Swing reemplaza, mejora y extiende a AWT, esto
debido a que reemplaza un sin numero de componentes de AWT, usa tambien una serie de funcionalidades de
AWT y tambien extiende la funcionalidad de algunos componentes de AWT.
A la vez comenzaron a introducirse una serie de APIs que extienden las funcionalidades de las interfaces
graficas, como lo son:
Accesibility
Introduce una serie de funcionalidades para mejorar la accesibilidad de los componentes.
Java2D y Java3D
Introduce una serie de funcionalidades para crear y manipular graficas 2D y 3D.
Drag & Drop
Introduce una serie de funcionalidades para arrastrar y soltar objetos entre distintos componentes.
Printing
Introduce una serie de funcionalidades para mejorar el manejo de la impresora.
Ademas, Sun en cada nueva version de java, sigue mejorando y ampliando las caractersticas de Swing. Sin
embargo, aunque las mejoras han sido notables, Swing aun deja bastante que desear si se compara con interfaces
nativas, principalmente debido a temas de desempeno.
As surge SWT (Standart Widget Toolkit) de IBM, enmarcado en su proyecto opensource Eclipse(http:
//www.eclipse.org/). Esto es una librera para crear interfaces graficas con Java. Es una delgada capa java que
comunica con una librera de codigo nativo, ofreciendo un mayor desempeno, ademas de un renovado Look &
Feel. Debido a que necesita una librera de codigo nativo es menos flexible que Swing, sin embargo, ya existen
distribuciones de SWT para las siguientes plataformas: Win32, Linux, Solaris, HPUnix, AIX, MacOS, Win32ce,
QNX.
En resumen, SWT esta entrando con fuerza en el mundo Java, sin embargo, aun es bastante nuevo. Por otro
lado, Swing es flexible y estable, teniendo ya mas de 5 anos de historia, por lo que lejos es lo mas usado en el
mundo. Pero en definitiva, pareciera que SWT va a desplazar muy rapido Swing, aunque en Sun solo hablen mal
de e l.
Este cambio no debiese ser problema para ningun desarrollador java, ya que su manejo es bastante similar a
Swing.
152

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS

6.2.

Introduccion a Swing

La arquitectura basica de Swing esta basada en Contenedores que contienen componentes (o subcontenedores)
formandose una jerarquia de componentes, a apartir de un contenedor maestro y terminando en un componente
basico. Esto se logra a traves de una programacion de alto nivel, limpia de detalles dependientes de plataforma
como los hWnd de windows o las llamadas a X en Unix.
Por otro lado, en general, las ventanas se programan y no se pintan como en lenguajes tpicos como Visual
Basic o Visual C++. Por lo mismo, es que tambien se prefiere un mecanismo de disposicion de componentes
administrados logicamente, mediante Layout Managers, por sobre el mecanismo de disposicion de componentes
con posiciones y tamanos absolutos, aunque tambien se pueden usan con Java. Sin embargo, la mayora de las
IDEs para java ofrecen herramientas para pintar ventanas.
Ademas el manejo de eventos se produce mediante interfaces de escuchadores de eventos(listeners) o adaptadores(adapters), con lo cual un mismo evento puede ser procesado de varias maneras simultaneamente.
Los componentes son elementos graficos basicos como etiquettas, cajas de texto y botones. Estos hacen la
interaccion con el usuario posible, y todos estan encapsulados por una subclase de la clase Component. Los
contenedores en cambio agrupan, contienen y organizan componentes, y son a la vez tambien componentes, lo que
posibilita que exista una jerarquia de componentes. Todos los contenedores estan encapsulados por una subclase
de la clase Container.
Ejemplo:

En este ejemplo, tenemos la siguiente estructura jerarquica: La ventana principal es de tipo JFrame ella contiene un panel de tipo JPanel que a la vez contiene un panel de desplazamiento de tipo JScrollPane que contiene
una a rea de texto JTextArea, as mismo el primer panel, contiene otro panel del mismo tipo (JPanel), que
contiene dos botones de tipo JButton.

6.2.1.

Contenedores

Existen varios tipos de contenedores:


Contenedores Maestros
Estos contenedores son aquellos que pueden ser la raz de una jerarquia de componentes, dependiendo del
tipo, es el tipo de ventana que se obtiene:
JApplet
Permiten crear un applet con componentes Swing.
JFrame
Permite crear una ventana tpica.
JDialog
Permite crear una ventana de dialogo, ya sea modal o no.
Todos ellos tienen un panel de contenidos de tipo JPanel donde se agregan sus componentes.
Contenedores de Proposito General
JPanel
Un panel simple que agrupa componentes.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

153

A SWING
6.2. INTRODUCCION
JScrollPane
Un panel de desplazamiento que permite al usuario desplazarse por su contenido.
JSplitPane
Un panel de division que permite que el usuario ajuste el tamano de sus componentes.
JTabbedPane
Un panel de pestanas que permite al usuario seleccionar un conjunto de controles a la vez.
JToolBar
Un panel de herramientas que dan al usuario acceso directo a cierto controles.
JMenuBar
Un panel de menu que dan de funciones al usuario mediante un sistema de menus desplegables.
Contenedores Especficos
JDesktopPane y JInternalFrame
Permiten la implementacion de aplicaciones MDI (Multiple Document Interface).
JLayeredPane
Permiten mantener el control de la profundidad de los componentes
JRootPane
Permiten manejar algunas funcionalidad entre componentes (de tal vez, distintos paneles), como por
ejemplo indicar el boton por defecto de un formulario.
La clase JPanel
Para clarificar un poco el uso de los contenedores, se vera como ejemplo la clase JPanel.
La jerarquia de esta clase es como sigue:
java.lang.Object java.awt.Component java.awt.Container javax.swing.JComponent
javax.swing.JPanel
Es decir, como casi todos los componentes graficos, es tanto un componente como un contenedor, y sus metodos
mas importantes para agregar componentes al panel:
Component add(Component c)
Component add(Component c, int pos)
Component add(Component c, String name)
Todos estos metodos agregan componentes al contenedor, y el segundo parametro de algunos de estos metodos
tiene relacion con el administrador de disposicion usado para indicar la posicion del componente.
Metodos para manipular el administrador de disposicion:
void setLayout(LayoutManager lm)
LayoutManager getLayout()
Metodos para manipular el borde:
void setBorder(Border b)
Border getBorder()
154

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS
La clase JFrame
La raz tpica de un a rbol de componentes jerarquico es tipo JFrame que encapsula la funcionalidad de una
ventana tpica, por lo cual es el contenedor maestro mas usado.
Esta clase contiene una serie de metodos esenciales para el manejo de ventanas:
void setTitle(String s)
Permite indicar el ttulo de la ventana, el cual se despliega en la barra superior.
void setSize(int sx, int sy)
Permite indicar el tamano inicial de la ventana en pxeles.
void pack()
Establece el tamano ideal de la ventana, segun el administrador de disposicion.
void setVisible(boolean v)
Permite desplegar u ocultar la ventana.
void setDefaultCloseOperation(int v)
Permite indicar un manejo de eventos de cierre simple, por defecto. Para esto se usan las constantes definidas
en la clase WindowConstants: EXIT ON CLOSE, HIDE ON CLOSE y DISPOSE ON CLOSE.
Estos eventos pueden ser manejados mas extensamente usando un WindowAdapter.
void setContentPane(Container c)
Permite indicar el panel de contenidos, es decir, el panel principal, a usar.
Container getContentPane()
Permite acceder al panel de contenidos actual.
void setJMenuBar(JMenuBar m)
Permite indicar la barra de menu a usar.
JMenuBar getJMenuBar()
Permite acceder a la barra de menu actual.
Tambien existen otros metodos para acceder a una serie de otros paneles mas especficos con que cuenta un
JFrame:
Root Pane: Este panel, de clase JRootPane, permite realizar algunas operaciones conjuntas entre componentes de distintos subpaneles. Por ejemplo, indicar el boton por defecto de la ventana, lo cual se realiza
mediante el comando:
frame.getRootPane().setDefaultButton(boton);
Layered Pane: Este panel, de clase JLayeredPane, se encarga de distribuir adecuadamente la profundidad
de los subpaneles en el eje Z.
Glass Pane: Este panel, de clase Component y permite, por ejemplo, dibujar por encima de los componentes,
incluso abarcando varios a la vez.
A continuacion una imagen que ilustra claramente la relacion de todos estos paneles:

Michael Moossen

Departamento de Informatica. U.T.F.S.M.

155

A SWING
6.2. INTRODUCCION

6.2.2.

Componentes

Existen varios tipos de componentes:


Botones
JButton
Es un boton tipo.
JRadioButton
Es un boton que permite seleccionar una opcion entre varias de un grupo.
JCheckBox
Es un boton que permite mantener un estado binario: seleccionado o no.
JToggleButton
Muy parecido al anterior solo que de distinta apariencia.
Despliege de Informacion no Editable
JLabel
Permite desplegar texto o imagen.
JProgressBar
Permite desplegar el avance de una operacion.
JToolTip
Permite desplegar algun texto de ayuda al mover el mouse sobre el componente asociado.
Cajas de Texto sin Formato
JTextField
Permite ingresar texto en una sola lnea.
JPasswordField
Identico al anterior, solo que no se despliega el contenido.
JTextArea
Permite ingresar texto multilnea.
Controles de Menu
JMenu
Permite crear un menu ha ser insertado en una barra de menu, o un submenu de un menu.
JPopupMenu
Permiten crear un menu que puede ser desplegado sobre un componente dependiendo de ciertos eventos.
JMenuItem
Representa un tem simple de menu.
JSeparator
Permite introducir separaciones dentro de un menu.
JRadioButtonMenuItem
Es un tem de menu que es tratado como un JRadioButton.
JCheckBoxMenuItem
Es un tem de menu que es tratado como un JCheckBox.
Controles de Seleccion
156

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS
JComboBox
Permite seleccionar una opcion entre varias de una lista desplegable.
JList
Permite seleccionar una o mas opciones entre varias de una lista.
JSlider
Permite seleccionar un valor dentro de un intervalo.
Informacion Formateada
JTable
Permite crear tablas de datos.
JTree
Permite crear a rboles jerarquicos de datos.
JEditorPane
Permite manipular texto formateado (HTML o RTF).
La clase JComponent
Para ejemplificar el manejo de componentes, se vera como ejemplo la clase JComponent de la cual heredan
casi todos los componentes graficos.
En forma general, tiene algunos metodos para sugerirle al administrador de disposicion el tamano. Estos metodos son:
void setMinimumSize(Dimension d)
void setPreferredSize(Dimension d)
void setMaximumSize(Dimension d)
Aqu el parametro d es un objeto de la clase Dimension que presenta una dimension planar, es decir tiene alto y
ancho.
Para sugerir la alineacion del componente, se pueden usar:
void setAlignmentX(float pos)
void setAlignmentY(float pos)
Donde pos es un numero entre 0.0 y 1.0 que indica, en forma porcentual, la posicion relativa de este componente
con el proximo. Por ejemplo, supongase que se tiene un panel con dos botones, uno encima del otro. Si el primer
boton tiene una alineacion en el eje X de 0.5, entonces el segundo boton se desplegara comenzando del punto
medio del primero.
Tambien hay unos metodos muy usados para manejar ToolTips:
void setToolTipText(String tt)
String getToolTipText()
Ejemplo:

Michael Moossen

Departamento de Informatica. U.T.F.S.M.

157

6.3. MANEJO DE EVENTOS

6.3.

Manejo de Eventos

En el contexto de las interfaces graficas, existen dos tipos de eventos:


Eventos de Bajo Nivel
Estos son los eventos producidos directamente por el usuario mediante el hardware. Por ejemplo, eventos
de mouse, de teclado, de voz, de joystick, etc.
Eventos Semanticos
Estos son eventos de mas alto nivel, gatillados por los componentes, generalmente debido a algun evento de
bajo nivel. Por ejemplo, si el usuario cambia el tamano de una columna de una tabla con el mouse, no es
necesario manejar el evento del mouse, y con la posicion del mouse determinar el la columna afectada y el
nuevo ancho, sino que la misma tabla maneja el codigo de bajo nivel, y luego gatilla un evento semantico
diciendo que una columna cambio su tamano, por si se quiere hacer alguna operacion adicional.
Entre estos eventos se encuentran acciones, y eventos de componentes.
Para manipular eventos java provee de una arquitectura publisher/subscriber, es decir, para poder reaccionar
ante un evento es necesario registrarse(subscribirse) con el componente que puede lanzar el evento en particular,
as si se produce el evento el componente originador(publisher) enva el evento a todos aquellos que se registraron.
El registro se produce por medio de una interfaz llamada Listener o de sus clases derivadas o implementadas.
Tambien existen los adaptadores que, en general, agrupan un conjunto de listeners relacionados.

La ejecucion de cada evento debe ser lo mas rapida posible, debido a que todos los eventos se ejecutan en
forma secuencial, includo el evento de repintado de las ventanas, en una hebra dedicada llamada event-dispatching
thread
Existen distintos tipos de listeners, dependiente del origen del o de los eventos que esperan, los mas usados
son:
MouseListener
Escucha eventos basicos del Mouse, solo clics.
MouseMotionListener
Escucha eventos de movimiento del Mouse.
WindowListener
Escucha eventos de ventana, como cambio de tamano, minimizacion, etc.
FocusListener
Escucha eventos de obtencion y perdida del foco de lso componentes.
ActionListener
Escucha eventos de acciones. Por ejemplo, presionar un boton o seleccionar un tem de menu.
KeyListener
Escucha eventos de teclado.
ListSelectionListener
Escucha eventos sobre cambios en la seleccion de una lista.
158

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS
En general, todos los metodos de un listener tienen un parametro de tipo EventObject o alguno de sus
derivados, del cual se puede obtener toda la informacion necesaria para manejar de forma correcta el evento. Por
ejemplo, son un MouseEvent se pueden obtener las coordenadas y sobre que componente el usuario hizo clic con
el mouse.
As para implementar un manejador de eventos es necesario seguir dos pasos:
Primero, es necesario declarar una clase que implemente un Listener o que extienda un Adapter e implementar los metodos necesarios.
Luego, es necesario registrar esta nueva clase con el componente correspondiente, para que sepa que cuando
se gatillan ciertos eventos debe avisarle a esta nueva clase.
El siguiente ejemplo, implementa un nuevo ActionListener que hace beep cuando es llamado:
public class MiManejador implements ActionListener {
public void actionPerformed(ActionEvent e) {
Toolkit.getDefaultToolkit().beep();
}
}
El cual se puede registrar en un boton con la siguiente instruccion:
boton.addActionListener(new MiManejador());
En la mayora de las ocasiones un manejador se implementa especificamente para un componente, ademas su
codigo es bastante reducido, lo que ofrece el ambiente propicio para usar clases anonimas.

6.4.

de Interfaces
Diseno

6.4.1.

Administracion de Disposicion

Como se ha mencionado anteriormente, la forma correcta de ubicar componentes en un panel es mediante el


uso de un administrador de disposicion (LayoutManager), el cual se encarga, bajo ciertos parametros, de darle el
tamano y la posicion adecuada a cada uno de los componentes.
Existen varios tipos de administradores de disposicion, que manejan la disposicion de los componentes de
distintas maneras.
Por defecto, los paneles de contenidos, tienen un BorderLayout y los demas paneles tienen un FlowLayout.
La clase BorderLayout
Un BorderLayout ofrece cinco sectores para posicionar componentes, como se puede apreciar en el ejemplo.
Estos sectores se identifican por constantes definidas por esta clase: NORTH, SOUTH, WEST, EAST y CENTER.
No es necesario ocupar los cinco sectores siempre. Y su comportamiento al cambiar el tamano del contenedor
es el siguiente:
Los sectores NORTH y SOUTH ajustan su tamano a lo largo, en el eje X.
Los sectores WEST y EAST ajustan su tamano a lo alto, en el eje Y.
El sector CENTER ajusta su tamano tanto a lo ancho como a lo alto.
Para usarlo, basta con crear un nuevo objeto y registrarlo con el panel en cuestion, para esto los constructores
mas usados son:
BorderLayout()
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

159

DE INTERFACES
6.4. DISENO
BorderLayout(int hgap, int vgap)
El u ltimo constructor separa los sectores hgap pxeles horizontalmente y vgap pxeles verticalmente.
Ejemplo:

La clase BoxLayout
Esta clase representa un stack de componentes el cual puede ser tanto vertical como horizontal.
Su constructor mas usado es:
BoxLayout(Component c, int pos)
En donde, c es el panel con el cual se va a registrar este BoxLayout y pos puede ser Y AXIS para indicar un stack
vertical de arriba hacia abajo, o X AXIS para indicar un stack horizontal de izquierda a derecha.
La clase CardLayout
Esta clase permite, tener un conjunto de paneles en una misma posicion, pero siempre uno solo sera visible a
la vez, lo cual se puede ir variando dependiendo de las circunstancias, como por ejemplo el estado de otro control.
Para usar un CardLayout se usa su constructor por defecto, y al agregar distintos paneles a un contenedor
con este tipo de administrador se puede usar el metodo add(Component, String), donde el String es un
identificador u nico.
Para desplegar un panel especfico se pueden usar los siguientes metodos:
void first(Container c)
void last(Container c)
void previous(Container c)
void next(Container c)
void show(Container c, String s)
En donde, c es el contenedor que usa el CardLayout, y s es el identificador de un panel especfico.
La clase FlowLayout
Este administrador de disposicion, es el mas simple de todos, y es muy parecido a un BoxLayout horizontal,
con la diferencia que inserta saltos de lnea para acomodar mejor los componentes. Tambien permite ajustar el
alineamiento de cada fila.
Sus contructores mas usados son:
FlowLayout()
FlowLayout(int align)
FlowLayout(int align, int hgap, int vgap)
En donde, align puede ser LEFT, RIGHT o CENTER, y hgap y vgap tienen el mismo significado que con BorderLayout.
160

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS
La clase GridLayout
Este administrador de disposicion representa un grilla de componentes, donde el espacio siempre se distribuye
de forma uniforme.
Sus constructores son:
GridLayout(int rows, int cols)
GridLayout(int rows, int cols, int hgap, int vgap)
En donde, rows y cols indican el tamano de la grilla, en numero de componentes. Cualquiera de las dos dimensiones puede ser cero, lo que indica que la grilla crece en esa direccion de tal manera que pueda contener todos los
componentes del panel.
Ejemplo:
contentPane.setLayout(new GridLayout(0,2));
contentPane.add(new JButton("Button 1"));
contentPane.add(new JButton("2"));
contentPane.add(new JButton("Button 3"));
contentPane.add(new JButton("Long-Named Button 4"));
contentPane.add(new JButton("Button 5"));

La clase GridBagLayout
Este es el administrador de disposicion mas complejo, ya que encapsula una funcionalidad similar a la de
una tabla HTML. Siendo una grilla de componentes, como tambien lo es GridLayout pero mucho mas flexible, permitiendo por ejemplo, unir celdas y/o columnas. Para esto cada celda tiene un conjunto de restricciones,
representadas por un objeto de la clase GridBagConstraints.
Para crear un GridBagLayout se usa su constructor estandar, y para indicar las restricciones de cada componente se usa el metodo:
void setConstraints(Component c, GridBagConstraints gbc)
La clase GridBagConstraint
Esta clase no es mas que una lista de atributos que pueden ser modificados, en general, usando las constantes
que define la misma clase, para cambiar el comportamiento de un celda en particular de una grilla de componentes
manejada por un GridBagLayout.
A continuacion se detallan los atributos mas usados:
gridx, gridy
Indican la nueva celda, comenzando a numerar desde cero, por supuesto. Tambien se puede usar la constante
RELATIVE que se refiere a la celda a la derecha de la actual, y si es la u ltima de la fila, a la primera de la fila
siguiente.
gridwidth, gridheight
Estos atributos indican el tamano de la nueva celda, y tienen el mismo significado que lso atributos COLSPAN
y ROWSPAN de una tabla HTML, respectivamente. Aqu se puede usar la constante REMAINDER para indicar
el uso de todas las celdas posibles en esa direccion.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

161

DE INTERFACES
6.4. DISENO
fill
Indica como ajustar el tamano del componente que contiene la celda. Para esto se puede usar alguna de las
siguientes contantes: NONE, HORIZONTAL, VERTICAL, BOTH
ipadx, ipady
Indican el margen interno de la celda, en ambos caso, la cantidad de pxeles indicada se distribuye a ambos
lados.
insets
Indica el espaciado interno, como un objeto de la clase Insets, cuyo constructor mas importante es:
Insets(int t, int l, int b, int r)
Donde t es la cantidad de pxeles por arriba, l por la izquierda, b por abajo y r por la derecha.
anchor
Indica la alineacion del control dentro de la celda. Se pueden usar las siguientes constantes: CENTER, NORTH,
SOUTH, EAST, WEST, NORTHWEST, NORTHEAST, SOUTHWEST, SOUTHEAST.
weightx, weighty
Permite controlar la distribucion del espacio, asignando pesos relativos a cada celda. Por defecto, la esquina
inferior derecha tiene todo el peso, por lo tanto, es la u nica que puede cambiar de tamano.
Ejemplo:

6.4.2.

Posicionamiento Absoluto

Tambien existe la posibilidad de usar posicionamiento y tamano absoluto, para esto es necesario eliminar el
administrador de disposicion por defecto del panel en cuestion, mediante el metodo setLayout() y pasandole
como parametro null . Ademas, existen un par de metodos que permiten indicar el tamano y la posicion de un
componente:
void setBounds(int pl, int pt, int sx, int sy)
Este metodo permite indicar tanto la posicion del componente, indicando su esquina superior izquierda,
como el tamano del mismo, indicando su ancho y alto.
void setSize(int sx, int sy)
Este metodo permite indicar el tamano de un componente mediante su ancho y alto.

6.4.3.

Relleno

A veces es necesario dejar espacios en blanco entre componentes, para obtener una disposicion o ptima. Para
esto se usa la clase Box, con la cual se pueden crear una variedad de componentes que ocupan espacio, pero no
son visibles.
Rectangulo Rgido
Para crear un rectangulo rgido se puede usar el siguiente metodo estatico:
162

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS
Component Box.createRigidArea(Dimension size)
Elastico
Para ocupar todo el espacio posible entre dos componentes, existen los elasticos:
Component Box.createHorizontalGlue()
Component Box.createVerticalGlue()
Rectangulo Flexible
Tambien se puede crear un rectangulo con cierta flexibilidad, definiendo su tamano mnimo, maximo y
preferido.
Box.Filler(Dimension min, Dimension pre, Dimension max)

6.4.4.

Bordes

Para ponerle bordes a los componentes, existe la clase BorderFactory, con la cual se pueden crear un sin
numero de bordes.
Bordes Vacos
Este tipo de borde se usa para darle mayor espacio al componente, y se crea usando el metodo:
Border createEmptyBorder(int t, int l, int b, int r)
Bordes Simples
Este tipo de borde simplemente dibuja una lnea de cierto color y ancho alrededor del componente, y se crea
usando el metodo:
Border createLineBorder(Color c, int w)
Bordes tipo Marco
Este tipo de bordes, permiten especificar el ancho del borde en cada direccion:
MatteBorder createMatteBorder(int t, int l, int b, int r, Color c)
Tambien existen metodos que permiten usar una imagen como patron del borde.
Bordes con Ttulo
Para crear un borde con ttulo, basta crear un borde cualquiera y luego ponerle el ttulo con este metodo:
TitledBorder createTitledBorder(Border b, String t)
Bordes Compuestos
Se pueden combinar tambien varios bordes en uno, mediante este metodo:
CompoundBorder createCompoundBorder(Border b1, Border b2)
Por ejemplo, un boton con un margen rojo:
JButton b = new JButton("bot
on");
b.setBorder(BorderFactory.createLineBorder(Color.red, 5);
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

163

DE INTERFACES
6.4. DISENO

6.4.5.

Look & Feel

Look & Feel es un termino que se usa para denominar el aspecto general que tiene una aplicacion grafica. Por
ejemplo, aspectos como: El color de la barra de ttulo, el color, tipo, y tamano de las fuentes, etc.
El Look & Feel normalmente depende del sistema operativo, ya que es e l, el que en definitiva ofrece el sistema
de ventanas, as por ejemplo una aplicacion tpica para windows 98, se ve como se ve porque el sistema operativo
la pinta a su pinta, y as la misma aplicacion ejecutandose en Windows XP tiene un Look & Feel totalmente
diferente, es debido a que la mayora de las aplicaciones no manejan directamente su Look & Feel, aunque es
posible hacerlo, como es el caso por ejemplo de WinAmp.
As, como Java es independiente de plataforma, sus sistema de ventanas es tambien totalmente independiente
del sistema operativo, por lo que en general, las aplicaciones Java se ven igual en todas las plataformas y tambien
muy distintas a otras aplicaciones nativas de esa plataforma. Sin embargo, es posible que una aplicacion Java se
pinte como una aplicacion nativa, mas aun tambien es posible implementar un Look & Feel propio.
La clase UIManager
Esta clase permite manipular el Look & Feel de una aplicacion, para esto se disponen de los siguientes metodos.
void setLookAndFeel(String classname)
Este metodo necesita como argumento el nombre de una clase que extienda la clase LookAndFeel. Si la
interfaz aun no esta creada no es necesario hacer nada mas. Sin embargo, si ya se ha creado la interfaz, es
necesario actualizarla, lo cual se hace va:
SwingUtilities.updateComponentTreeUI(frame);
Donde, frame es la ventana principal de la aplicacion, o la raz del a rbol de componentes que se desea
actualizar. Debido a que tambien pueden haber cambios de tamano de los componentes, es aconsejable,
volver a distribuir los componentes va: frame.pack();.
String getCrossPlatformLookAndFeelClassName()
Para obtener el nombre de la clase que implementa el Look & Feel independiente de la plataforma, en
general, sera:
javax.swing.plaf.metal.MetalLookAndFeel
Este es el Look & Feel por defecto de la aplicaciones Java.
String getSystemLookAndFeelClassName()
Este metodo sirve para obtener la clase que implementa el Look & Feel de la plataforma en la cual se
esta ejecutando, las que pueden ser:
Windows: com.sun.java.swing.plaf.windows.WindowsLookAndFeel
Solaris: javax.swing.plaf.mac.MacLookAndFeel
Macintosh: javax.swing.plaf.metal.MetalLookAndFeel
Se debe tener presente que, en general, los Look & Feel de plataformas especficas solo estan disponibles en
esas plataformas.
Ejemplo:

164

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS

6.5.

Contenedores

6.5.1.

Ventanas de Dialogo

Existen dos tipos de ventanas de dialogo, las modales, que bloquean la aplicacion mientras esperan la interaccion con el usuario y las no-modales, que no bloquean la aplicacion.
La clase que encapsula toda la funcionalidad de una ventana de dialogo, es la JDialog, sin embargo, la clase
JOptionPane ofrece una variada gama de ventanas de dialogo modales simples:
Ventanas de Mensaje
Este tipo de ventana solo despliega un mensaje y espera hasta que el usuario lo lea y presione el boton. Se
usa mediante:
static void showMessageDialog(Component parent, Object msg, String title, int
msgType, Icon icon)
Donde
parent es el componente a bloquear
msg es el mensaje a desplegar
title es el ttulo de la ventana
msgType es el tipo de mensaje, dependiendo del cual se muestra un cono por defecto, el cual puede tomar cualquiera de los siguientes valores: INFORMATION MESSAGE, WARNING MESSAGE, ERROR MESSAGE,
QUESTION MESSAGE o PLAIN MESSAGE, y
icon es un cono personalizado.
Tambien existen otras versiones de este metodos(y los demas) con menos parametros, los que toman algunos
valores por defecto.
Ventanas de Confirmacion
Este tipo de ventana pide la confimacion o cancelacion de una accion al usuario. Se ejecuta va:
static int showConfirmDialog(Component parent, Object msg, String title, int
optType, int msgType, Icon icon)
Los parametros son identicos a los de la venta de mensaje, excepto por optType que indica si se despliegan
dos o tres botones, y que puede ser: YES NO OPTION o YES NO CANCEL OPTION.
Ademas, este metodo devuelve el valor del boton seleccionado por el usuario, que puede ser: YES OPTION,
NO OPTION o CANCEL OPTION.
Ventanas de Entrada
Esta ventana permite al usuario ingresar un valor.
static String showInputDialog(Component parent, Object msg, String title, int
msgType)
El metodo retorna el valor ingresado por el usuario.
Ventanas de Opciones
Esta es la ventana mas generica de todas, que permite personalizar las etiquetas de los botones mediante su
paramtero options.
static int showOptionDialog(Component parent, Object msg, String title, int
optType, int msgType, Icon icon, Object[] options, Object initialValue)
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

165

6.5. CONTENEDORES
Tambien existen algunas ventanas de dialogo mas especializadas, como lo son:
Ventanas de Seleccion de Colores
Existe un control especializado para la seleccion de colores encapsulado en la clase JColorChooser, el
cual puede ser usado en cualquier contenedor, y que ademas provee de un dialogo por defecto, el que se usa
mediante el metodo:
static Color showDialog(Component parent, String title, Color default)
El valor de retorno es el color seleccionado.
Ventanas de Seleccion de Archivos
Tambien existen un control especializado para la seleccion de archivos(o directorios) encapsulado en la clase
JFileChooser.
Los principales constructores de esta clase son:
JFileChooser()
JFileChooser(String iniDir)
JFileChooser(File iniDir)
Permitiendo indicar un directorio de inicio para la seleccion, sino es la carpeta del usuario, segun el sistema
operativo.
Otros metodos que influyen en el comportamiento de la ventana de dialogo:
File getSelectedFile()
Este metodo devuelve el archivo seleccionado.
void setFileHidingEnabled(boolean fh)
Permite indicar si se desea acceder a archivos ocultos o no.
void setFileFilter(FileFilter ff)
void addChoosableFileFilter(FileFilter ff)
Estos dos metodos permiten filtrar los archivos a seleccionar. Para esto es necesario extender la clase
javax.swing.filechooser.FileFilter especificando los dos metodos:
boolean accept(File f)
String getDescription()
El primero filtra los archivos aceptando o rechazando cada uno, y el segundo metodo da una descripcion del tipo de archivos que se filtran. Por ejemplo,
class GIFFileFilter extends FileFilter {
public boolean accept(File f) {
return (f.isDirectory() || (f.getName().endsWith(".gif")));
}
public String getDescription() {
return "Archivos GIF";
}
}
void setFileSelectionMode(int mode)
Permite indicar el modo de operacion del control. Se pueden usar las siguentes constantes: FILES ONLY,
DIRECTORIES ONLY o FILES AND DIRECTORIES.
Finalmente, la ventana de dialogo se ejecuta mediante alguno de los siguientes metodos:
int showOpenDialog(Component parent)
int showSaveDialog(Component parent)
int showDialog(Component parent, String title)
166

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS
Los primeros dos metodos solo obtienen el ttulo que despliegan de la configuracion del sistema operativo
en que se ejecuta la aplicacion.
El valor de retorno puede ser APPROVE OPTION o CANCEL OPTION.
Todas estas ventanas son modales, para crear y usar otras ventanas de dialogo, ya sea modales o no, es necesario
extender la clase JDialog.

6.5.2.

Contenedores Generales

Panel de Desplazamiento
Este tipo de panel permite desplazarse por un objeto(que debe implementar la interfaz Scrollable) que es
mas grande que el area visible, por ejemplo una imagen o un documento de texto. Esta funcionalidad esta encapsulada por la clase JScrollPane.
Sus principales constructores son:
JScrollPane(Component c)
JScrollPane(Component c, int hp, int vp)
En donde, c es el componente al cual se le desea atachar las barras de deslizamiento, y, hp y vp, son las opciones
para las barras de desplazamiento horizontales y verticales. Las cuales pueden ser: VERTICAL SCROLLBAR AS NEEDED,
HORIZONTAL SCROLLBAR AS NEEDED, VERTICAL SCROLLBAR ALWAYS, HORIZONTAL SCROLLBAR ALWAYS, VERTICAL SCROLLBAR
y HORIZONTAL SCROLLBAR NEVER respectivamente.
Tambien existen una serie de a reas que se pueden personalizar en un JScrollPane, como lo son las esquinas
y los llamados encabezados de fila y columna, esto se ve mas claramente en el siguiente diagrama:

Para personalizar estas a reas se usan los siguientes metodos:


void setColumnHeaderView(Component c)
void setRowHeaderView(Component c)
void setCorner(String key, Component c)
En donde, c es el componente que personaliza el a rea especificada, ademas el u ltimo metodo tiene un parametro key que indica que esquina se va a personalizar, para esto se usan las constantes: UPPER LEFT CORNER,
LOWER LEFT CORNER, UPPER RIGHT CORNER y LOWER RIGHT CORNER
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

167

6.5. CONTENEDORES
Panel de Division
Un panel de division permite agrupar dos componentes en un contenedor divididos por una barra desplazable, que permite ajustar el tamano de los componentes. La clase que escapsula esta funcionalidad se llama
JSplitPane, y su constructor mas usado es:
JSplitPane(int o, Component c1, Component c2)
En donde, c1 y c2 son los dos componentes a separar, y o es la orientacion de la barra separadora, que puede ser:
HORIZONTAL SPLIT, VERTICAL SPLIT.
Sus metodos mas usados son:
void setOneTouchExpandable(boolean e)
Este metodo indica si se deben o no dibujar los botones en el divisor, que permiten maximizar el espacio de
cada componente.
void setDividerLocation(int pxl)
Este componente indicar la posicion inicial del divisor en pxeles desde la esquina superior izquierda.
void setDividerLocation(double perc)
Lo mismo que el anterior pero en porcentaje.
void setDividerSize(int pxl)
Indica el tamano del divisor en pxeles.
void setResizeWeight(double rat)
Indica el peso de cada componente al momento de cambiar el tamano del contenedor.
Ejemplo:

Panel de Pestanas
Un panel de pestanas permite, seleccionar de un gran conjunto de componentes un subgrupo a la vez, identificados por pestanas con nombre. La clase que encapsula este comportamiento es JTabbedPane.
Sus constructores mas importantes son:
JTabbedPane(int tp)
Este constructor permite indicar la posicion de las pestanas, mediante las constantes: RIGHT, LEFT, TOP y
BOTTOM.
JTabbedPane(int tp, int tl)
Con este constructor, ademas de poder indicar la posicion de las pestanas, se puede indicar el comportamiento de pestanas, si no todas caben en el espacio dado: WRAP TAB LAYOUT con lo cual se acomodan en
lneas y SCROLL TAB LAYOUT con lo cual se agrega botones de desplazamiento.
Sus metodos mas usados son:
168

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS
void addTab(String title, Icon icon, Component c, String tip)
Este metodo agrega una nueva pestana de nombre title, con un cono icon, con un texto de ayuda tip,
para el componente c. Tambien existen otras versiones de este mismo metodo con menos parametros.
void setEnabledAt(boolean b, int index)
Permite habilitar o deshabilitar la pestana index.
int getSelectedIndex()
Permite obtener el ndice de la pestana seleccionada actualmente.
Ejemplo:

Barra de Herramientas
Una barra de herramientas es un panel con un conjunto de componentes, generalmente botones, pero pueden
ser cualquier cosa, que permiten acceder de forma facil y rapida a ciertas funcionalidades de una aplicacion, esta
barra generalmente es flotante, es decir, puede ser reubicada por el usuario. Esta funcionalidad es encapsulada por
la clase JToolBar.
Su constructor mas importante es:
JToolBar(String name, int ori)
En donde, name es el nombre de la barra y ori es la orientacion inicial de esta, la cual puede ser HORIZONTAL o
VERTICAL.
Sus metodos mas importantes son:
void add(Component c)
Este metodo agrega un nuevo componente a la barra.
void addSeparator()
Este metodo agrega un separador a la barra.
void setFloatable(boolean b)
Este metodo permite indicar si la barra es flotante o no.

Barra de Menu
Una barra de menu contiene una serie de menus desplegables, que permiten acceder a la mayor parte de las funcionalidades de una aplicacion tpica. Por defecto se ubica en el borde superior de una ventana. Esta funcionalidad
esta encapsulada por la clase JMenuBar.
Sus metodos mas importantes son:
JMenu add(JMenu m)
Este metodo permite agregar un nuevo menu a la barra.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

169

6.5. CONTENEDORES
JMenu getMenu(int index)
Permite obtener el menu en la posicion indicada.
void setMargin(Insets mgs)
Permite indicar los margenes de la barra.
Menu
Un menu es una lista desplegable de comandos, que se activan desde una barra de menu, son los mas tpicos,
y su funcionalidad se encapsula en la clase JMenu. Tambien hay otros tipos de menus que se activan al ejecutar
alguna accion sobre algun componente, estos son los llamados Pop-up Menus, cuya funcionalidad se encuentra
encapsulada en la clase JPopupMenu.
El constructor mas usado de JMenu:
JMenu(String text)
Con el cual se crea un menu con nombre text.
Sus metodos mas importantes son:
JMenuItem add(JMenuItem item)
El cual agrega un nuevo tem al menu.
void addSeparator()
Este metodo agrega al menu un separador.
La clase JPopupMenu se usa casi igual, excepto que hay que desplegar el menu, para esto esta el metodo:
void show(Component c, int x, int y)
El cual despliega el menu, sobre el componente c y en las coordenadas indicadas.
El despliegue se efectua, generalmente, en un evento del mouse. As, la clase MouseEvent provee todos los
metodos necesarios para desplegar un menu:
Component getComponent()
Permite obtener el componente sobre el cual sucedio el evento.
boolean isPopupTrigger()
Permite discriminar si el evento es o no gatillador de un menu.
int getX()
int getY()
Estos metodos devuelven las coordenadas en que sucedio el evento.
Item de Menu
Un tem de menu puede ser una etiqueta con o sin un cono (JMenuItem), o un check box (JCheckBoxMenuItem)
o un radio button (JRadioButtonMenuItem). Todos los cuales se usan de manera bastante similar, excepto en el
manejo de eventos, esto debido a su super clase en comun llamada AbstractButton, la cual ofrece todos los
metodos necesarios:
void setText(String label)
Permite indica un texto a desplegar en el boton.
void setIcon(Icon icon)
Permite, ademas del texto, desplegar un cono. Existen tambien una serie de otros metodos similares, que
permiten personalizar los conos cuando el boton esta deshabilitado, o seleccionado, etc.
170

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS
void setEnabled(boolean b)
Permite indicar si el boton esta habilitado o no.
void setMargin(Insets mrg)
Permite indicar los margenes del boton
void setIconTextGap(int gap)
Permite indicar el tamano de la separacion entre el cono y el texto.
void setHorizontalTextPosition(int p)
Permite indicar la posicion del texto relativa al cono. Se pueden usar las siguientes constantes: LEFT, RIGHT
o CENTER.
void setActionCommand(String cmd)
Permite indicar una palabra clave, con la cual se puede luego en un manejador de eventos discriminar el
boton accionado. Por defecto, se usa el texto del boton.
void setMnemonic(int mn)
Permite indicar la letra resaltada, con la cual se activa el tem si se presiona ALT- y la letra indicada. Este
metodo se usa en conjunto con la clase KeyEvent que provee de las siguientes constantes:
Numeros: Desde la VK 0 a la VK 9.
Letras: Desde la VK A a la VK Z.
Teclas de Funcion: Desde la VK F1 a la VK F24.
Ademas de todos estos metodos heredados de AbstractButton, tambien todos son un JMenuItem, cuyo
mayor aporte es el siguiente metodo:
void setAccelerator(KeyStroke ks)
Este metodo asigna una combinacion de teclas directamente al menu tem en cuestion. Para crear un KeyStroke
se tiene el metodo:
KeyStroke.getKeyStroke(int key, int modifiers)
Donde key es una tecla de KeyEvent y modifiers es una composicion de las constantes de InputEvent:
CTRL MASK, SHIFT MASK y/o ALT MASK.

6.6.

Componentes

En esta seccion se veran una serie de componentes graficos que permiten la interaccion con el usuario.

6.6.1.

Etiquetas

Las etiquetas son componentes que solo permiten desplegar informacion simple, ya sea atraves de una lnea
de texto y/o un cono. Esta funcionalidad es encapculada por la clase JLabel.
Sus constructores mas usados son:
JLabel(String label)
JLabel(Icon icon)
Y sus metodos mas importantes:
void setIcon(Icon icon)
Este metodo permite setear el cono a desplegar.
void setText(String label)
Este metodo permite indicar el texto a desplegar. Este texto puede ser texto HTML.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

171

6.6. COMPONENTES

6.6.2.

Botones

Los botones son componentes que por naturaleza ejecutan una accion al ser presionados (tanto por teclado o mouse). Swing ofrece una serie de botones con comportamientos especficos, y todos extienden la clase
AbstractButton, por lo tanto, estan disponibles todos los metodos indicados en la seccion ??.
Botones Simples
Un boton simple es un componente que ejecuta una accion directmante cuando es presionado y que vuelve a
su estado original inmediatamente. Esta funcionalidad es encapsulada por la clase JButton.
Sus constructores mas usados son:
JButton(String label)
JButton(String label, Icon icon)
Para indicar el boton por defecto de una ventana, se usa la siguiente sentencia:
frame.getRootPane().setDefaultButton(button);
Botones de Dos Estados
Un boton de dos estados es un componente, que por defecto no ejecuta ninguna accion inmediata al ser presionado, sino que mantiene su estado el cual puede ser de dos tipos: presionado o no, activado/desactivado, seleccionado o no, etc. Su funcionalidad basica se encapsula en la clase JToggleButton.
Su contructor mas usado es:
JToggleButton(String label, Icon icon, boolean selected)
Donde se indica, ademas de una etiqueta e cono, su estado inicial: true si esta presionado, false sino.
Su apariencia es bastante parecida a la de un boton simple. Sin embargo, esta clase posee dos subclases,
que apesar de tener la misma funcionalidad basica, tienen algunas variaciones en apariencia principalmente y
funcionalidad tambien.
Botones de Seleccion Simple
Este tipo de boton, tiene exactamente la misma funcionalidad que la vista anteriormente, la u nica diferencia
radica en su apariencia. Su funcionalidad esta encapsulada en la clase JCheckBox.
Como es de esperarse su uso es identico:
JCheckBox(String label, Icon icon, boolean selected)
Botones de Seleccion Grupal
Este tipo de boton, ademas de diferenciarse por su apariencia, tambien modifica su funcionalidad, en cuanto
permiten seleccionar una y solo una de las opciones de un grupo a la vez. Su funcionalidad esta encapsulada en la
clase JRadioButton.
Su constructor no cambia:
JRadioButton(String label, Icon icon, boolean selected)
Pero, debe usarse en conjunto con la clase ButtonGroup, la cual tiene el siguiente metodo:
void add(AbstractButton button)
172

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS

6.6.3.

Listas Desplegables

Una lista desplegable es un componente que permite seleccionar(o ingresar) una opcion entre varias alternativas, desplegando solo la opcion seleccionada. Su funcionalidad se encapsula en la clase JComboBox.
Sus constructores mas usados son:
JComboBox(Object[] items)
JComboBox(Vector items)
Los cuales indican las opciones ofrecidas al usuario por defecto.
Sus metodos mas importantes son:
Object getSelectedItem()
Este metodo permite obtener el tem seleccionado.
void setSelectedItem(Object item)
Este metodo permite indicar el tem seleccionado por defecto.
void setEditable(boolean flag)
Este metodo permite indicar si el componente admite que el usuario ingrese otra opcion no contenida en la
lista de opciones.
void setEnabled(boolean flag)
Este metodo permite indicar si el componente esta habilitado o no.

6.6.4.

Cajas de Texto

Una caja de texto permite al usuario ingresar un texto corto en una lnea. Esta funcionalidad esta encapsulada
en la clase JTextField.
Sus constructores mas usados son:
JTextField(int cols)
JTextField(String text, int cols)
Los cuales permiten indicar el tamano del componente en caracteres y opcionalmente un texto por defecto.
Sus metodos mas importantes son:
void setHorizontalAlignment(int ha)
Este metodo permite indicar el alineamiento del texto, el cual puede ser LEFT, RIGHT o CENTER.
void setColumns(int cols)
Este metodo permite indicar cambiar el tamano del componente.
String getText()
Este metodo permite obtener el texto actual de la caja de texto.

6.6.5.

Campos de Password

Este componente es muy similar a una caja de texto, excepto que el texto ingresado, se despliega con un
caracter comodn. Esta funcionalidad se encapsula en la clase JPasswordField.
Sus constructores son identicos a los de una caja de texto:
JPasswordField(int cols)
JPasswordField(String text, int cols)
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

173

6.6. COMPONENTES
Y sus metodos mas importantes son:
void setEchoChar(char echo)
Permite indicar el caracter comodn a desplegar.
char [] getPassword()
Permite obtener el texto ingresado.

6.6.6.

Areas
de Texto

Una a rea de texto permite al usuario ingresar y/o editar texto a atraves de varias lneas, lo cual es la limitacion
de una caja de texto. Esta funcionalidad esta encapsulada en la clase JTextArea.
Sus constructores son identicos a los de una caja de texto:
JTextArea(String text)
JTextArea(int cols, int rows)
Que permiten indicar un texto por defecto y el tamano inicial del a rea de texto.
Y sus metodos mas importantes son:
void setLineWrap(boolean lw)
Permite indicar si al llegar el texto a un extremo del a rea de texto, este se corta automaticamente, siguiendo
en la lnea siguiente.
void setWrapStyledWord(boolean wtw)
Permite indicar el estilo de corte de lnea automatico, ya sea por palabras o por caracteres.
void setFont(Font font)
Permite indicar la fuente a usar para desplegar el texto.

6.6.7.

Listas

Las listas son componentes que despliegan una serie de opciones y que permiten que el usuario seleccione una
o mas temes. Esta funcionalidad se encapsula en la clase JList
Sus principales constructores son:
JList(Object[] items)
JList(Vector items)
JList(ListModel model)
Todos permiten indicar los temes iniciales. Luego se vera que es un objeto ListModel.
Sus metodos mas importantes son:
void ensureIndexIsVisible(int index)
Este metodo manipula el viewport actual, de tal manera que el tem indicado sea visto por el usuario.
ListModel getModel()
Este metodo obtiene el modelo de datos de la lista.
int getSelectedIndex()
Este metodo obtiene el ndice del tem seleccionado.
ListSelectionModel getSelectionModel()
Este metodo obtiene el ndice del tem seleccionado.
174

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS
Object getSelectedValue()
Este metodo obtiene el tem seleccionado.
void setLayoutOrientation(int lo)
Este metodo permite especificar el esquema usado para desplegar la mayor cantidad de temes posibles a la
vez, el cual puede ser:
VERTICAL: Indica una lista vertical simple.
VERTICAL WRAP: Indica una lista vertical, que al llegar al extremo del viewport sigue en una nueva
columna.
HORIZONTAL WRAP: Indica una lista horizontal, que al llegar al extremo del viewport sigue en una
nueva fila.
void setSelectionMode(int sm)
Permite indicar el modo de seleccion, el cual puede ser cualquiera de los indicados por la clase ListSelectionModel:
SINGLE SELECTION: Indica seleccion simple.
SINGLE INTERVAL SELECTION: Indica seleccion mediante un solo intervalo.
MULTIPLE INTERVAL SELECTION: Indica seleccion multiple, totalmente libre.
Para poder manipular los temes seleccionados, existe la interfaz ListSelectionModel, cuyos principales metodos son:
boolean isSelectedIndex(int index)
Este metodo permite comprobar si un tem especfico esta o no seleccionado.
boolean isSelectionEmpty()
Permite comprobar si hay o no algun tem seleccionado.
int getMinSelectionIndex()
Devuelve el ndice del primer tem seleccionado.
int getMaxSelectionIndex()
Devuelve el ndice del u ltimo tem seleccionado.
void addListSelectionListener(ListSelectionListener lsl)
Permite agregar un nuevo manejador de eventos de seleccion.
Para manejar los eventos de seleccion de una lista, existe la interfaz ListSelectionListener. Cuyo metodo
mas importante es:
void valueChanged(ListSelectionEvent e)
Que se gatilla, al efecuarse un cambio en los temes seleccionados de la lista.
Luego, el evento mismo es de la clase ListSelectionEvent. Y tiene los siguientes metodos:
boolean getValueIsAdjusting()
En general, el evento soloo debe considerarse si este metodo devuelve false , sino quier decir, que se trata
de un evento intermedio de ajuste.
int getFirstIndex()
Permite obtener el primer ndice seleccionado.
int getLastIndex()
Permite obtener el u ltimo ndice seleccionado.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

175

6.6. COMPONENTES
Por u ltimo, y lo mas importante, es el modelo de datos de la lista, el cual se encapsula en la interfaz ListModel.
Toda lista tiene un modelo de datos, que en realidad representa a los datos mismos, generalmente, es un arreglo
con el detalle de los datos, pero tambien se puede usar un metodo que genere los datos. Ahora, se veran dos clases
concretas que pueden ser utilizadas para manipular los datos:
La clase DefaultListModel
Esta clase implementa la interfaz ListModel mediante un simple vector de datos. Esta clase es utilizada
por defecto, cuando se crea una lista con un arreglo o un vector de tems.
La clase AbstractListModel
Esta clase es comunmente usada para ser extendida, y sobrescribir sus metodos para generar los datos. Los
metodos mnimos a sobrescribir son:
Object elementAt(int index)
int getSize()

6.6.8.

Tablas

Una tabla es una matriz bidimensional de datos, funcionalidad que encapsula la clase JTable.
Sus principales constructores son:
JTable(Object[][] data, Object[] colNames)
JTable(Vector data, Vector colNames)
JTable(TableModel model)
Los dos primeros, permiten indicar los datos iniciales como una matrix o vector bidimensional, y ademas un
vector de nombres de las columnas, en cambio, el u ltimo utiliza un modelo de datos, con la misma idea de la clase
ListModel, pero para tablas.
Una tabla puede ser tratada tambien como una lista, para lo cual se tienen metodos analogos a esta:
void setSelectionMode(int sm)
ListSelectionModel getSelectionModel()
Con respecto al modelo de datos de la tabla, el cual se encapsula en la interfaz TableModel. Generalmente, es
un arreglo bidimensional con el detalle de los datos, pero tambien se puede usar un metodo que genere los datos.
Ahora, al igual que con las listas, se veran dos clases concretas que pueden ser utilizadas para manipular los datos:
La clase DefaultTableModel
Esta clase implementa la interfaz TableModel mediante un simple vector bidimensional de datos. Esta clase
es utilizada por defecto, cuando se crea una tabla con un arreglo o un vector bidimensional de tems.
La clase AbstractTableModel
Esta clase es comunmente usada para ser extendida, y sobrescribir sus metodos para generar los datos. Los
metodos mnimos a sobrescribir son:
Object getValueAt(int row, int column)
public String getColumnName(int column)
int getRowCount()
int getColumnCount()
176

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


CAPITULO 6. INTERFACES GRAFICAS
Para manejar los eventos de una tabla existen dos metodos:
La Dficil
Este metodo es va TableModelListener y TableModelEvent, parecido a como se vio con las listas.
La Facil
La interfaz TableModel tambien ofrece una serie de metodos relacionados con el manejo de eventos que se
pueden sobrescribir, para personalizar su comportamiento:
void setValueAt(Object val, int row, int col)
Este metodo se ejecuta, cuando el usuario modifica el valor de la celda especficada, para lo cual la
celda debe ser editable.
void fireTableCellUpdated(int row, int col)
Este metodo se gatilla, al haber un cambio en la celda especficada.
boolean isCellEditable(int row, int col)
Este metodo permite personalizar las celdas editables por el usuario.

6.7.

Lo que falto

Por tiempo y espacio, este documento no contempla todos los componentes disponibles. Aqu se nombran los
mas importantes y se indican referencias de documentacion.
Contenedores Especializados
JRootPane, JLayeredPane y Glass Pane
http://java.sun.com/docs/books/tutorial/uiswing/components/rootpane.html
http://java.sun.com/j2se/1.4/docs/api/javax/swing/JRootPane.html
http://java.sun.com/j2se/1.4/docs/api/javax/swing/JLayeredPane.html
Aplicaciones Multidocumento (MDI)
JDesktopPane y JInternalFrame
http://java.sun.com/docs/books/tutorial/uiswing/components/internalframe.html
http://java.sun.com/j2se/1.4/docs/api/javax/swing/JDesktopPane.html
http://java.sun.com/j2se/1.4/docs/api/javax/swing/JInternalFrame.html
Otros Componentes Basicos
Spinners:
La clase JSpinner
http://java.sun.com/j2se/1.4/docs/api/javax/swing/JSpinner.html

Barras de Progreso:
Las clases JProgressBar y ProgressMonitor
http://java.sun.com/j2se/1.4/docs/api/javax/swing/JProgressBar.html http:
//java.sun.com/j2se/1.4/docs/api/javax/swing/ProgressMonitor.html

Sliders:
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

177


6.7. LO QUE FALTO
La clase JSlider
http://java.sun.com/j2se/1.4/docs/api/javax/swing/JSlider.html

Modelo de Documentos
http://java.sun.com/docs/books/tutorial/uiswing/components/generaltext.html#document
Controles de Texto Formateado
Editores de Texto de formatos como HTML y RTF.
Las clases JFormattedTextField, JEditorPane y JTextPane
http://java.sun.com/j2se/1.4/docs/api/javax/swing/JFormattedTextField.html
http://java.sun.com/docs/books/tutorial/uiswing/components/text.html
Personalizacion de Tablas
Seleccion de Columnas
Editores de campos personalizados
Validacion de campos
Eventos en los encabezados
http://java.sun.com/docs/books/tutorial/uiswing/components/table.html

Arboles
Jerarquicos
JTree, TreeNode, MutableTreeNode, TreeModel, TreeSelectionModel, TreeCellEditor y TreePath
http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html
http://java.sun.com/j2se/1.4/docs/api/javax/swing/JTree.html

178

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

Captulo 7

Java 2 Enterprise Edition


7.1.

Introduccion

Java 2 Enterprise Edition nace de la necesidad de estandarizar el desarrollo de aplicaciones distribuidas con
Java, garantizando un buen rendimiento, alta escalabilidad, soporte de transacciones de alto nivel, servicios de
seguridad basicos, acceso a bases de datos, administracion del ciclo de vida de los objetos, reutilizacion facil de
componentes, etc.
Permitiendo de esta manera que el desarrollador se concentre exclusivamente en la logica del negocio de la
aplicacion a desarrollar.
La definicion oficial de J2EE es:
J2EE es la especificacion de una arquitectura de componentes para el desarrollo de aplicaciones
coorporativas orientadas a objetos y distribuidas.
Sun Microsystems 1998
Esto significa en la practica:
J2EE es el framework que todo el mundo usa para escribir soporte de transacciones, acceso a datos,
seguridad y ejecucion de componentes del lado del servidor.
o tambien
J2EE es un conjunto de patrones de diseno que especifican como desarrollar componenttes reutilizables para aplicaciones distribuidas.
J2EE es una especificacion y NO un producto, luego hay muchas aplicaciones de terceros que cumplen con la
especificacion J2EE.

7.1.1.

Enterprise Java Bean

Cuando se habla de un componente, se refiere a un Enterprise Java Bean (EJB), los cuales no tienen ninguna
relacion con los Java Beans, a pesar de la similitud de los nombres. Estos componentes se ejecutan dentro de
contenedores EJB que normalmente son parte de un servidor EJB. Estos concentran la logica del negocio de forma
reutilizable y estandar, de forma tal de poder ser distribuidos y tambien poder interactuar con otros componentes,
como servicios Web tipo SOAP o WSDL sin mayor esfuerzo.

7.1.2.

Contenedor EJB

Un contenedor EJB es la plataforma en la cual se ejecutan los EJBs, estos dan soporte y permiten manejar
a un mayor nivel el acceso a bases de datos, a servidores de mail, a transacciones, a servicios de mensajera y
seguridad, administracion de persistencia, etc.
179


7.1. INTRODUCCION
Tambien se habla de Servidores EJB, que ademas de ser un contenedor, ofrece el servicio de los EJBs a
agentes externos mediante Java Naming and Directory Interface (JNDI), como por ejemplo a un servidor Web.
As tambien, se dice que una suite que ofrece tanto un servidor Web como un servidor de EJB, es un servidor de
aplicaciones.

7.1.3.

Arquitectura

En el siguiente diagrama se ve claramente el modelo de cuatro capas en que esta basada la especificacion
J2EE:

Se tienen las cuatro capas bien definidas y separadas unas de otras:


Presentacion
Esta capa es lo que el usuario ve, es estatico(tonto) y puede ser por ejemplo HTML o una aplicacion de
escritorio.
Logica de la Presentacion
Esta es la capa que contiene la logica de como presentar los datos al usuario, generalmente son paginas JSP
o EJBs.
Logica del Negocio
Esta es la capa mas importante de todas, que define la logica del negocio de la aplicacion, este es el campo
de aplicacion principal de los EJBs
Datos
Esta es la u ltima capa, que simplemente contiene los datos en algun RDBMS u otra forma de persistencia.
Este esquema muestra tambien lo facil que es distribuir los distintos componentes de cada capa:

Aqu vemos que se tienen varios clientes, que pueden o no pasar por un control de seguridad, cuya carga se puede
distribuir mediante una serie de servidores Web, los cuales pueden tambien o no necesitar cierta identificacion para
acceder a los EJB que tambien pueden estar distribuidos mediante una serie de servidores EJB los que finalmente
acceden a los datos distribuidos tambien identificandose.
180

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 7. JAVA 2 ENTERPRISE EDITION

7.1.4.

Distribucion de Carga

Los metodos de distribucion de carga, aunque no estan contemplados directamente dentro de J2EE, estan ya
bastante estandarizados entre distintos vendedores de servidores de aplicaciones.
Aqu hay dos conceptos importantes:
Clustering
Permite una alta disponibilidad de EJBs, replicando los componentes en varios servidores, esta replicacion
en general es automatica incluyendo el proceso de integrar un nuevo servidor al cluster.
Farming
Este es un mecanismo usado para distribuir una nueva version de un componente automaticamente a traves
de todo el cluster.

7.1.5.

Descriptores de Instalacion

Para instalar un EJB en un contenedor se necesita un descriptor de instalacion, que es un archivo xml, que
define entre otras cosas:
Lmite de Transacciones
Para cada metodo se define su manejo transaccional por parte del contenedor.
Componentes relacionados
Se definen todos los componentes con los cuales se puede comunicar el EJB.
Fuentes
Se definen todos las fuentes de datos que pueden ser accedidas por el EJB.
Variables de Entorno
Se pueden definir variables de entorno para cada EJB.

7.2.

Enterprise Java Beans

Existen tres tipos de EJBs:


Session Beans
Entity Beans
Message Driven Beans
Para desarrollar un EJB es necesario crear tres clases:
Bean
Esta es el bean mismo, que implementa alguna de las interfaces base para cada tipo de bean. Todos sus
metodos y atributos deben ser serializables, y los atributos no pueden ser publicos. En general, estan excentos
de codigo de bajo nivel y el codigo esta clase nunca se ejecuta fuera de un contenedor EJB.
Por Ejemplo, podemos implementar una clase llamada FacturaBean que implementa un SessionBean
Home Interface
Esta una clase debe implementar la interfaz EJBHome y debe declarar todos los metodos de creacion del
Bean, los cuales deben lanzar una excepcion CreateException y deben retornar un objeto de la interfaz
remota del bean.
Por Ejemplo, para el caso de la factura, se debera implementar una clase llamada FacturaHome.
Michael Moossen

Departamento de Informatica. U.T.F.S.M.

181

7.3. TRANSACCIONES
Remote Interface
Esta una clase debe implementar la interfaz EJBObject y debe declarar todos los metodos publicos del
Bean, los cuales deben lanzar una RemoteException
Por Ejemplo, para el caso de la factura, se debera implementar una clase llamada FacturaRemote.
Para instanciar un EJB el cliente debe buscar la referencia de la interfaz Home del Bean al servicio JNDI del
servidor de EJB, con lo cual se crea(o se reutiliza) una instancia del Bean y se le asocia una interfaz Remote que
se retorna al cliente.
As, una vez obtenida una instancia de la interfaz remota, esta se puede usar como si el cliente tuviese una
instancia del bean, pero en realidad, en cada invocacion de un metodo la interfaz remota le pasa el control al
contenedor EJB para que este pueda realizar operaciones como el manejo de transacciones antes y/o despues de
ejecutar realmente el codigo del Bean.

7.2.1.

Session Beans

Son los EJBs mas genericos, que pueden(Stateful) o no(Stateless) mantener el estado de la sesion del cliente.
Los stateless session beans son facilmente escalables y reutiilizables, ya que un mismo bean puede ser usado
para atender concurrentemente a varios clientes. En cambio, los stateful session beans mantienen la sesion del
cliente en el servidor, por lo cual es necesario, crear un nuevo bean para cada cliente.

7.2.2.

Entity Beans

Estos beans representan, en general, datos directamente persistentes en bases de datos. Y el contenedor se
encarga de manejar la persistencia del mismo. Existen dos tipos:
Bean Managed Persistency (BMP)
Este tipo de entity bean obliga al bean a implementar cuatro metodos de persistencia para crear, cargar,
actualizar, eliminar los datos. Sin embargo, las llamadas a estos metodos son manejadas por el contenedor.
Container Managed Persistency (CMP)
Este tipo de entity bean permite simplemente mapear una tabla de una base de datos con un bean, con lo
cual el usuario se desliga totalmente de la peristencia de los datos.

7.2.3.

Message Driven Beans

Este tipo de beans permite un proceso de peticiones. No son invocados de forma directa, sino que mediante el
contenedor, por lo que no son necesarias las intefaces Home y Remote, tampoco mantienen el estado de la sesion
del cliente, y existen dos modelos de peticiones posibles:
Point to Point
Este modelo permite la implementacion de una cola FIFO simple, es decir, todas las peticiones que llegan,
son atendidas en forma secuencial por el bean.
Publisher/Subscriber
Este otro modelo permite crear topicos, as los beans se subscriben a los topicos y todas las peticiones que
son enviadas a un topico son distribuidas a todos los bean subscritos y procesadas en forma secuencial por
cada uno.

7.3.

Transacciones

Existen dos tipos de manejo de transacciones por parte de un contenedor EJB:


182

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

CAPITULO 7. JAVA 2 ENTERPRISE EDITION

7.3.1.

Manejo Programado

Este es el metodo mas parecido al tpico, el usuario es el encargado de iniciar la transaccion y terminarla o
cancelarla. Sin embargo, debe pedirle el servicio transaccional al contenedor EJB que maneja un pool de transacciones distribuidas, es decir, que se puede usar una u nica transaccion aun se accedan a datos de distintas bases de
datos.

7.3.2.

Manejo Declarado

Este metodo libera al usuario de todo manejo de transacciones, para este se debe declarar el tipo de manejo
transaccional que soporta cada metodo del bean en el descriptor del mismo.

Michael Moossen

Departamento de Informatica. U.T.F.S.M.

183

7.3. TRANSACCIONES

184

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

Apendice A

Utilitarios de Java
Java provee de varios programas utilitarios que pueden, en gran medida, facilitarle la vida al programador.
Entre estos, estan los siguientes, que se revisaran con detalle en este apendice.
javadoc : Generador de documentacion.
jar : Generador paquetes.
appletviewer : Emulador de aplicacion cliente de applets.
jdb : Depurador de consola.

A.1.

Generador de Documentacion

Ademas de los comentarios tpicos tambien existe un tipo especial de comentarios que procuran ayudar en
la tarea de documentar los programas. Todo programador conoce el problema de documentar los programas, y
por eso Java intenta ayudar con un tipo especial de comentarios. Es equivalente al comentario de parrafo, pero se
utiliza un asterisco mas para empezar:
/** Esto es un comentario
que servir
a para documentar el programa */
La herramienta javadoc recogera esos comentarios y generara documentacion en formato HTML. Dado que el
resultado es HTML, se puede incluir codigo HTML en los comentarios. Para respetar el modo de comentar de
muchos programadores, un asterisco al comienzo de la lnea sera ignorado. Tambien admite etiquetas especiales
que comienzan por una arroba. Por ejemplo, la clase HelloWorldApp puede ser documentada de la siguiente
forma:
/** Este es un ejemplo del Curso de Java,
* que simplemente escribe la frase -Hello World!* @author Michael Moossen
* @version 1.0
*/
public class HelloWorldApp {
/** Punto de entrada a la aplicaci
on
* @param args Arreglo de String que contiene los argumentos
* @return No devuelve ning
un valor
* @exception Ninguna No lanza excepciones
*/
public static void main(String[] args) {
185

A.2. JAVA ARCHIVE


System.out.println("Hello World!");
}
}
La documentacion se genera ejecutando la siguiente lnea:
javadoc -author -version HelloWorldApp.java
La documentacion generada puede ser vito con cualquier navegador HTML.
Entre las etiquetas especiales, cabe destacar que se diferencian entre etiquetas de clase (@author y @version)
y etiquetas de metodo (@param, @return, @exception y @deprecated). Este u ltimo requiere una atencion
especial. No existe un u nico Java, pues despues de la primera version se lanzaron distintas versiones. Algunos
aspectos del Java original comenzaron a parecer obsoletos y se decidio desaconsejar su uso, pues podran dejar de
ser soportados en el futuro. Se marcaron con la etiqueta deprecated. As pues, se permitio utilizar esa etiqueta a
los programadores de clases.

A.2.

Java ARchive

Permite generar archivos jar, agrupando codigo ejecutable (archivos .class) y/o archivos de recursos (imagenes, sonidos, etc.). Sus principales caractersticas son:
Seguridad
Permite firmar digitalmente el contenido de un archivo .jar
Compresion
Permite comprimir el contenido de un archivo .jar. con lo cual se logra mejores tiempo de bajada desde
internet y mejor aprovechamiento de medios de almacenamiento.
El comando jar es muy similar a cualquier compresor como zip, de hecho el formato de un archivo jar es
compatible con el formato zip.
Para crear un nuevo archivo de usa el comando:
jar cf jar-file input-file(s)
Para ver el contenido de un archivo de usa el comando:
jar tf jar-file
Para extraer el contenido de un archivo de usa el comando:
jar xf jar-file
Al crear un archivo jar se crea automaticamente un archivo de configuracion llamado META-INF/MANIFEST.MF.
Este archivo contiene una serie de secciones, de las cuales las mas importantes son:
Main-Class: classname
Indica una clase ejecutable por defecto dentro del archivo.
Class-Path: servlet.jar infobus.jar acme/beans.jar
Indica una serie de archivos adicionales que son prerequisitos necesarios para usar el archivo.

A.3.

Applet Viewer

Existe una herramienta llamada appletviewer que permite ver (y depurar) un applet sin necesidad de contar
con un browser. Dado los avances de los browsers y las facilidades que existen para ejecutar un applet como una
aplicacion, esta herramienta es actualmente solo parte de la historia.
186

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


APENDICE
A. UTILITARIOS DE JAVA

A.4.

Java Debugger (jdb)

Esta herramienta es un depurador de lnea de comando.


A pesar de tener toda la funcionalidad de cualquier depurador grafico (como el integrado en Visual Basic), esta lejos de ser as de amistoso. Para mas informacion ver http://java.sun.com/j2se/1.4/docs/
tooldocs/win32/jdb.html.
Sin embargo, Sun provee de una API especfica para que cualquiera pueda implementar un depurador grafico
llamada JPDA (Java Platform Debugger Architecture) y la SDK viene con un ejemplo de un depurador grafico llamado javadt, pero aun esta lejos de ser usable. para mas informacion ver http://java.sun.com/products/
jpda.
Sin embargo, la mayora de las IDEs comerciales proveen depuradores graficos integrados buenos y bonitos,
al mas puro estilo Visual Basic.

A.5.

Java IDEs

A pesar de la gran oferta de IDEs (Integrated Development Environment) para desarrollar proyectos Java, es
dficil encontrar una con la funcionalidad necesaria para desarrollar facilmente sin tener que leer primero miles de
paginas de documentacion.
A continuacion una lista de las distintas alternativas que ofrece el mercado, para que el usuario elija, ya que a
m no me satisface ninguna:
NetBeans
http://www.netbeans.org/
Eclipse
http://www.eclipse.org/
Borland JBuilder
http://www.borland.com/jbuilder/
IBM Visual Age
http://www.software.ibm.com/ad/vajava/
IntelliJ IDEA
http://www.intellij.com/
BlueJ
http://www.bluej.org
JCreator
http://www.jcreator.com/

Michael Moossen

Departamento de Informatica. U.T.F.S.M.

187

A.5. JAVA IDES

188

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

Apendice B

Propiedades del Sistema


A continuacion, una tabla de todas las propiedades de sistema, disponibles en la version 1.4.
Nombre
java.version
java.vendor
java.vendor.url
java.specification.version
java.specification.vendor
java.specification.name
java.home
java.vm.version
java.vm.vendor
java.vm.name
java.vm.specification.version
java.vm.specification.vendor
java.vm.specification.name
java.class.version
java.class.path
java.ext.dirs
os.name
os.arch
os.version
file.separator
path.separator
line.separator
user.name
user.home
user.dir

Descripcion de la Propiedad
Version del Entorno de Ejecucion de Java. JRE
Proveedor del JRE
URL del proveedor de Java
Version de la especificacion del JRE
Proveedor de la especificacion del JRE
Nombre de la especificacion del JRE
Directorio de instalacion de Java
Version de la Maquina Virtual de Java. JVM
Proveedor de la JVM
Nombre de la JVM
Version de la especificacion de la JVM
Proveedor de la especificacion de la JVM
Nombre de la especificacion de la JVM
Version del Bytecode Java
class path de Java
Directorio de extensiones
Nombre del Sistema Operativo
Arquitectura del Sistema Operativo
Version del sistema Operativo
Separador de Archivos (/ en UNIX)
Separador de Directorios (: en UNIX)
Separator de lnea (\n en UNIX)
Nombre de la cuenta de usuario
Directorio raz del usuario
Directorio de trabajo

Estas pueden ser accesadas va el metodo System.getProperty() y similares. (Ver seccion 4.2.4).

189

190

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

Bibliografa
[1] http://java.programacion.net.
[2] Patrick Naughton. Manual de Java. 1996. Editorial Osborne/McGraw-Hill.
[3] Jose Arturo de los Angeles. Programacion Orientada a Objetos.
[4] Agustn Froufe. JAVA 2: Manual de Usuario y Tutorial. 2002. http://usuarios.lycos.es/froufe/
index.html.
[5] Pietro Castellucci. Curso Introduccion al Java.. http://www.htmlpoint.com/guidajava/index.
html.
[6] Pablo Lanza Moreno. Curso de Java. 2000. http://www.geocities.com/vienna/7905/.
[7] Intoduccion a Java. http://www.monografias.com.
[8] Sun Microsystems. http://java.sun.com.

191

BIBLIOGRAFIA

192

Departamento de Informatica. U.T.F.S.M.

Michael Moossen


Indice
alfabetico
., 17
blank, 128
parent, 128
self, 128
top, 128

start(), 137
stop(), 137
AppletContext, 139
getApplet(), 139
getApplets(), 139
showDocument(), 139
showStatus(), 139
Applets, 135
Applets como Aplicaciones, 142
application, 133
ARCHIVE, 136
Archivos Binarios, 77
Archivos de Acceso Aleatorio, 78
Archivos de Texto, 76
Archivos y Directorios, 74
AREA, 128
Arreglos, 13
Atributos, 41
De Clase, 49
Estaticos, 49
AudioClip
loop(), 140
play(), 140
stop(), 140
AUTHOR, 120
autoflush, 132
Ayuda en Lnea, 5

A, 115, 128
Abstraccion, 36
abstract, 50
AbstractButton, 170
setActionCommand(), 171
setEnabled(), 171
setHorizontalTextPosition(), 171
setIcon(), 170
setIconTextGap(), 171
setMargin(), 171
setMnemonic(), 171
setText(), 170
AbstractListModel, 176
elementAt(), 176
getSize(), 176
AbstractTableModel, 176
getColumnCount(), 176
getColumnName(), 176
getRowCount(), 176
getValueAt(), 176
Acciones JSP, 134
ACTION, 121
Agregacion, 37
Ejemplo, 38
ALIGN, 124, 125, 136
ALINK, 121
ALT, 117, 136
APPLET, 136
Applet
destroy(), 137
getAudioClip(), 140
getImage(), 140
getParameter(), 136
getParameterInfo(), 137
init(), 137
play(), 140

B, 114, 124
BACKGROUND, 120
BASE, 120, 128
BGCOLOR, 120
BGPROPERTIES, 120
BIG, 114
BigDecimal, 70
divide(), 70
ROUND DOWN, 70
BigInteger, 70
add(), 70
ONE, 70
ZERO, 70
BLOCKQUOTE, 113
193

INDICE ALFABETICO

BODY, 111
BORDER, 117, 124
BorderLayout, 142
BOTTOM, 118
BR, 114
break, 27
buffer, 132
BufferedReader, 76
readline(), 76
BufferedWriter, 77
ButtonGroup, 172
add(), 172
Byte Code, 2
Calendar, 71
add(), 71
get(), 71
getTime(), 71
setTime(), 71
casting, 15
catch, 29
CELLPADDING, 124
CELLSPACING, 124
CENTER, 111, 113
CHECKBOX, 123
CHECKED, 122
Ciclo de Vida de un Applet, 137
Ciclo de Vida de un Thread, 88
Ciclos, 27
Control de Flujo, 27
Clase
Atributos de, 41
Metodos de, 41
Miembro de, 47
Clases, 40
Ejecucion de las, 60
Internas, 51, 53
Anonimas, 55
Estaticas, 52
Locales, 55
Miembro, 53
CLASSIFICATION, 120
CLASSPATH, 61
CODE, 136
CODEBASE, 136
codebase, 60
COLOR, 118
COLS, 122, 126
COLSPAN, 125
Comentarios, 11
De Fin de Lnea, 11
De Parrafo, 11
194

COMPACT, 116, 117


Comparable, 25
Compilacion, 6
Component, 138
createImage(), 138
getBackground(), 138
repaint(), 138
Comunicacion entre Applet y Browser, 139
Concatenacion de Metodos, 42
Conceptos Basicos de Red, 95
Conectividad a Base de Datos (JDBC), 80
config, 133
Connection, 82
commit(), 85
createStatement(), 83
getTransactionIsolation(), 86
rollback(), 86
setAutoCommit(), 85
setTransactionIsolation(), 86
Constructores, 43
Sobrecarga de, 43
Ejemplo, 43
Container, 137
paint(), 137
update(), 137
contentType, 131
continue, 28
Control de Acceso, 12
Control de Flujo, 26
Controlador de Seguridad, 144
Instalacion de un, 147
Conversion de Tipos, 15
Automatica, 15
Incompatibles, 15
Creacion de Hilos, 87
Crear una Conexion a la Base de Datos, 82
Daemon, 87
Datagramas, 107
DatagramPacket, 107
getAddress(), 108
getData(), 110
getPort(), 108
DatagramSocket, 107
close(), 108, 110
receive(), 108
send(), 108
DataInput, 78
readFloat(), 79
readInt(), 79
readUTF(), 79
DataOutput, 78
Departamento de Informatica. U.T.F.S.M.

Michael Moossen

INDICE ALFABETICO

writeFloat(), 79
writeInt(), 79
writeUTF(), 79
Date, 70
compareTo(), 71
getTime(), 71
setTime(), 71
toString(), 71
Datos Compartidos, 40
DD, 117
Declaraciones JSP, 131
DefaultListModel, 176
DefaultTableModel, 176
DESCRIPTION, 120
Destructores, 44
Dimension, 138
height(), 138
width(), 138
Directivas JSP, 131
Distribuciones, 5
DIV, 113
DL, 117
Doble Buffer, 138
Driver, 80
DriverManager, 80, 81
getConnection(), 82
Drivers JDBC, 80
DT, 117
Ejecucion, 7
Ejecutar una Instruccion SQL, 83
Elementos de Script JSP, 129
Encapsulamiento, 37
ENCTYPE, 121
Entrada y Salida de Datos, 74
equals(), 32
errorPage, 132
Especializacion, 37
Estructura jerarquica de Directorios, 60
Eventos, 158
Excepciones
Capturar, 30
Declaracion en Metodos, 31
Lanzar, 30
Exception, 29
Expresiones JSP, 129
extends, 132
Extensibilidad, 36
FACE, 119
File, 74
canRead(), 74
Michael Moossen

canWrite(), 74
delete(), 74
exists(), 74
getAbsolutePath(), 75
getName(), 75
getParent(), 75
getPath(), 75
isDirectory(), 74
isFile(), 74
lastModified(), 74
length(), 74
list(), 74
mkdir(), 74
renameTo(), 74
file, 132
FileInputStream, 77
FileOutputStream, 77
FileReader, 76
read(), 76
FileWriter, 76
write(), 76
Final, 50
Finalizador, 44
Finalize(), 44
finally, 29
Flexibilidad, 35
Flickering, 138
FONT, 118
for, 27
FORM, 121
FRAME, 126
Frame, 142
add(), 142
addWindowListener(), 142
setSize(), 142
setVisible(), 142
FRAMEBORDER, 128
FRAMESET, 126
FTP, 95
Fully Qualified Name, 59
Generalidad, 40
Generalizacion, 37
GENERATOR, 120
Graphics, 137
clipRect(), 138
drawImage(), 138
setClip(), 138
setColor(), 138
GregorianCalendar, 71
Grupos de Thread, 94

Departamento de Informatica. U.T.F.S.M.

195

INDICE ALFABETICO

H1, 111, 113


H2, 113
H3, 113
H4, 113
H5, 114
H6, 114
Hashtable, 66
get(), 67
put(), 67
rehash(), 66
remove(), 67
toString(), 67
HEAD, 111
HEIGHT, 117, 136
Herencia, 37
Ejemplo, 38
Multiple, 37, 56
HIDDEN, 123
Hilos y Sincronizacion, 87
HR, 111, 114
HREF, 115
HSPACE, 136
HTML, 111
HTTP, 95
HttpServletRequest, 130, 133
getParameter(), 129
getQueryString(), 130
getRemoteHost(), 130
HttpServletResponse, 130, 133
setContentType(), 131
HttpSession, 130, 133
I, 114
Identificadores, 9, 10
if, 26
IllegalMonitorStateException, 90
IllegalThreadStateException, 88
Imagenes en Applets, 140
Image, 138
getGraphics(), 138
ImageObserver, 141
IMG, 117, 136
implements, 58
import, 60, 131
include, 132
InetAddress, 108
getByName(), 110
info, 132
INPUT, 121, 122
Instalacion, 4
instanceof, 25
Integracion en la Red, 4
196

interface, 57
Interfaces, 56
InterruptedException, 90
isErrorPage, 132
isThreadSafe, 131
Iteradores, 65
Iterator, 65
hasNext(), 65
next(), 65
Java e Internet, 95
java.math, 70
javadoc, 185
JButton, 172
JCheckBox, 172
JComboBox, 173
getSelectedItem(), 173
setEditable(), 173
setEnabled(), 173
setSelectedItem(), 173
JDBC URL, 82
Jerarqua, 37
JLabel, 171
setIcon(), 171
setText(), 171
JList, 174
ensureIndexIsVisible(), 174
getModel(), 174
getSelectedIndex(), 174
getSelectedValue(), 175
getSelectionModel(), 174
HORIZONTAL WRAP, 175
MULTIPLE INTERVAL SELECTION, 175
setLayoutOrientation(), 175
setSelectionMode(), 175
SINGLE INTERVAL SELECTION, 175
SINGLE SELECTION, 175
VERTICAL, 175
VERTICAL WRAP, 175
JMenu, 170
add(), 170
addSeparator, 170
JMenuBar
add(), 169
getMenu(), 170
setMargin(), 170
JPasswordField, 173
getPassword(), 174
setEchoChar(), 174
JRadioButton, 172
JSplitPane
setDividerLocation(), 168
Departamento de Informatica. U.T.F.S.M.

Michael Moossen

INDICE ALFABETICO

setDividerSize(), 168
setOneTouchExpandable(), 168
setResizeWeight(), 168
JspWriter, 130, 133
JTabbedPane, 168
addTab(), 169
getSelectedIndex(), 169
setEnabledAt(), 169
JTable, 176
getSelectionModel(), 176
setSelectionMode(), 176
JTextArea, 174
setFont(), 174
setLineWrap(), 174
setWrapStyledWord(), 174
JTextField, 173
getText(), 173
setColumns(), 173
setHorizontalAlignment(), 173
JToggleButton, 172
JToolBar, 169
add(), 169
addSeparator(), 169
setFloatable(), 169
KEYWORDS, 120
Lectura y Escritura sobre Sockets, 102
Leer Directamente desde una URL, 98
LEFT, 118
length, 14
Lenguaje Interpretado, 2
Lenguajes
Basados en Clases, 35
Basados en Objetos, 35
Orientados a Objetos, 35
LI, 116
Limitaciones para el Programador, 36
LINK, 120
ListModel, 176
ListSelectionEvent, 175
getFirstIndex(), 175
getLastIndex(), 175
getValueIsAdjusting(), 175
ListSelectionListener, 175
valueChanged(), 175
ListSelectionModel, 175
addListSelectionListener(), 175
getMaxSelectionIndex(), 175
getMinSelectionIndex(), 175
isSelectedIndex(), 175
isSelectionEmpty(), 175
Michael Moossen

Literales, 10
Metodos, 41
De Clase, 49
Estaticos, 49
Firma De, 42
Header De, 42
Signatura De, 42
Metodos para Dibujar un Applet, 137
Manejo de Excepciones, 28, 40
Manejo de Transacciones, 85
Mantenibilidad, 36
MARGINHEIGHT, 121, 128
MARGINWIDTH, 121, 128
Math, 68
abs(), 69
acos(), 69
asin(), 69
atan(), 69
ceil(), 69
cos(), 69
E, 69
exp(), 69
floor(), 69
log(), 69
max(), 69
min(), 69
PI, 69
pow(), 69
random(), 69, 130
round(), 69
sin(), 69
sqrt(), 69
tan(), 69
MAXLENGTH, 122
META, 120
METHOD, 121
MIDDLE, 118
Miembros
Estaticos, 48
Modificadores, 48
Modularidad, 37
MouseEvent
getComponent(), 170
getX(), 170
getY(), 170
isPopupTrigger(), 170
MULTIPLE, 123
Multitarea, 4, 40
Numeros de Fibonacci, 31
NAME, 115, 121, 126, 128, 136

Departamento de Informatica. U.T.F.S.M.

197

INDICE ALFABETICO

NaN, 68
native, 42
NEGATIVE INFINITY, 68
nested classes, 52
new, 45
NOFRAME, 126
NORESIZE, 128
NOWRAP, 125
null, 10
Number, 68
intValue(), 68
Object, 32, 38
notify(), 89
notifyAll(), 89
wait(), 89
ObjectInputStream, 79
readObject(), 79
ObjectOutputStream, 78
flush(), 78
writeObject(), 78
Objetos, 17, 45
Obtencion de Resultados de Sentencia SQL, 83
OL, 116
Operaciones con Objetos, 25
Operador
Condicional, 23
instanceof, 25
Punto, 17, 42
Ternario, 23
Operadores, 18
Aritmeticos, 19
De Asignacion, 23
De Comparacion, 21, 25
De Rotacion, 20
Logicos, 21
Precedencia de, 23
Unarios, 18
OPTION, 122
Orientacion a Objetos, 3
out, 130, 133
Override, 40
P, 111, 113
Packages, 59
page, 131, 134
PageContext, 133
pageContext, 133
Palabras Clave, 9
Panel, 138
size(), 138
Paquetes, 59
198

Nombres de, 59
Uso de, 60
Parametros, 42
Parametros Opcionales, 42
PARAM, 136
Parpadeo, 138
parseDouble(), 68
ParsePosition, 73
Persistencia, 40
Plantilla de Texto, 129
Polimorfismo, 39
Portabilidad, 2
POSITIVE INFINITY, 68
POST, 121
PRE, 113
Primera Clase, 5
PrintWriter, 76, 77, 133
print(), 77
println(), 77
Prioridades, 93
private, 12
Programacion Estructurada, 36
Programacion Orientada a Objetos, 35
Caractersticas, 36
Caractersticas Adicionales, 40
Desventajas, 36
Ventajas, 35
Promocion de Tipos, 16
Propiedades del Sistema, 189
protected, 12
public, 12
Puertos, 96
RADIO, 122
Random, 129
nextInt(), 129
RandomAccessFile, 78
getFilePointer(), 78
read(), 78
seek(), 78
skipBytes(), 78
write(), 78
Recursividad, 31
Referencia a un Objeto, 42
Registrar un Driver JDBC, 81
request, 130, 133
Resena Historica, 1
RESET, 123
response, 130, 133
Restricciones de Seguridad en Applets, 143
ResultSet, 83
close(), 85

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

INDICE ALFABETICO

getAsciiStream(), 85
getBigDecimal(), 85
getBoolean(), 85
getByte(), 85
getBytes(), 85
getDate(), 85
getDouble(), 85
getFloat(), 84, 85
getInt(), 85
getLong(), 85
getShort(), 85
getString(), 84, 85
getTime(), 85
getTimestamp(), 85
next(), 84
Return, 43
Reusabilidad, 35
RGB, 118
RIGHT, 118
Robustez, 4
ROWS, 122, 126
ROWSPAN, 125
Runnable
run(), 88
S, 114
Scriptlets, 130
SCROLLING, 128
SecurityException, 143, 145
SecurityManager, 143, 144
checkAccept(), 148
checkAccess(), 144, 148
checkConnect(), 148
checkCreateClassLoader(), 148
checkDelete(), 148
checkExec(), 148
checkExit(), 144, 148
checkLink(), 148
checkListen(), 148
checkPackageAccess(), 148
checkPackageDefinition(), 148
checkPropertiesAccess(), 148
checkPropertyAccess(), 144, 148
checkRead(), 145, 148
checkSetFactory(), 148
checkTopLevelWindow(), 148
checkWrite(), 145, 148
Seguridad, 4
SELECT, 122
SELECTED, 123
Sentencia SQL, 83
Separadores, 10
Michael Moossen

Serializable, 79
Serializacion de Objetos, 78
ServerSocket
accept(), 104
close(), 104
Servlet
getServletConfig(), 133
getServletInfo(), 132
ServletConfig, 133
getContext(), 133
ServletContext, 133
getAttribute(), 133
setAttribute(), 133
ServletRequest, 133
session, 130, 131, 133
SimpleDateFormat, 72
format(), 73
parse(), 73
SimpleTimeZone, 73
Sincronizacion, 91
SIZE, 119, 122, 123
SMALL, 114
Sobrecarga de Metodos, 39
Socket, 102
close(), 103
getInputStream(), 103
getOutputStream(), 103
SocketServer, 102
Sonidos en Applets, 140
SRC, 117, 126, 128
START, 117
Statement, 83
close(), 83
executeQuery(), 83
executeUpdate(), 83
static, 48
StrictMath, 68
String, 63
charAt(), 63
compareTo(), 64
indexOf(), 64
length(), 64
replace(), 64
substring(), 64
toLowerCase(), 64
toUpperCase(), 64
trim(), 64
StringBuffer, 64
append(), 64
insert(), 64
length(), 64
StringTokenizer, 65

Departamento de Informatica. U.T.F.S.M.

199

INDICE ALFABETICO

hasMoreTokens(), 65
returnDelims, 65
SUB, 114
subclase, 38
SUBMIT, 121, 123
SUP, 114
super, 46
superclase, 38
switch, 26
System, 67
err, 67
exit(), 67
getProperty(), 67
getSecurityManager(), 144
in, 67
out, 67
setErr(), 67
setIn(), 67
setOut(), 67
setProperty(), 67

getName(), 94
getParent(), 94
parentOf(), 94
setMaxPriority, 94
Threads en Applets, 141
throw, 30
throws, 31
Tipificacion Fuerte, 40
Tipos de Dato, 14
Basicos, 14
Tipos de Drivers JDBC , 80
TITLE, 111
TOP, 118
toString(), 33
TR, 124
Trabajo en Red, 95
Transacciones, 85
transient, 51
try, 29
try...catch...finally, 29
TYPE, 116, 117

TABLE, 124
TableModel, 176
fireTableCellUpdated(), 177
isCellEditable(), 177
setValueAt(), 177
Tamano Excesivo en las Aplicaciones, 36
TARGET, 128
Taxonoma de Lenguajes Orientados a Objetos, 35
TCP, 95
TD, 124
Telnet, 95
TEXT, 120
TEXTAREA, 122
this, 45
Thread, 87
currentThread(), 94
getName(), 87
getPriority(), 93
isAlive(), 91
MAX PRIORITY, 93
MIN PRIORITY, 93
NORM PRIORITY, 93
resume(), 90
run(), 87
setPriority(), 93
sleep(), 89
start(), 88
suspend(), 90
yield(), 89
ThreadGroup, 94
getMaxPriority(), 94
200

U, 114
UDP, 95
UL, 116
UnknownServiceException, 102
URL, 96
Absoluta, 97
getFile(), 98
getHost(), 98
getPort(), 98
getProtocol(), 97
getRef(), 98
openConnection(), 99
openStream(), 98
Relativa, 97
toExternalForm(), 98
toString(), 98
URLConnection, 99
getInputStream(), 100
getOutputStream(), 101
setDoOutput(), 101
URLEncoder, 101
encode(), 101
URLs de Conexion, 82
VALIGN, 125
VALUE, 122, 123, 136
valueOf(), 68
Variables, 11

Ambito
de, 12
Declaracion de, 11

Departamento de Informatica. U.T.F.S.M.

Michael Moossen

INDICE ALFABETICO

Vector, 65
addElement(), 66
elementAt(), 66
indexOf(), 66
isEmpty(), 66
iterator(), 66
removeElement(), 66
setElementAt(), 66
toString(), 66
Velocidad de Ejecucion, 36
VLINK, 120
volatile, 51
VSPACE, 136
while, 27
WIDTH, 117, 124, 125, 136
WindowAdapter, 142
windowActivated(), 142
windowClosing()(), 142
windowDeactivated(), 142
WindowEvent, 142
Wrappers, 14

Michael Moossen

Departamento de Informatica. U.T.F.S.M.

201

Vous aimerez peut-être aussi