Está en la página 1de 91

Descargado de: http://technologycompartida.blogspot.

com

JAVA DESDE
QUÉ
CEROES
JAVA
LENGUAJE DE
INDEPENDIENTE
OBJETOS
3 DE LA
PLATAFORMA
3
ALGUNAS
CARACTERÍSTICAS…
3 JAVA DEVELOPMENT
EL
4EMPECEMOS
KIT DE UNA
4VEZ!
JAVASCRIPT
5
LAS CLASES EN
5ESTRUCTURA
6
JAVA DE UNA
CLASE
ESTRUCTURA DE
7CLASES
DECLARACIÓN DE LA
8EL
CLASE
CUERPO DE LA
12
CLASE
EL CUERPO DE LOS
12
DECLARACIÓN
MÉTODOS DE VARIABLES
14
LOCALES
ASIGNACIONES A
17
VARIABLES
OPERACIONES
18
MATEMÁTICAS
LLAMADAS A
18
MÉTODOS
LAS ESTRUCTURAS DE
IF…[ELSE]
18
CONTROL
19
SWITCH…CASE…BRAKE…DEFAULT
21
WHILE
DO…
22 WHILE
FOR
22
23
BREAK Y
CONTINUE
23
OTRAS...
HAGAMOS
23
ALGO...
LA
24 CLASE
COMPLEJO
ALGO SOBRE LOS
24
MÉTODOS
JAVA A TRAVÉS DE LA
VENTANA PRIMERA
25
NUESTRA
28
VENTANA
UNA VENTANA CON
30
VIDA
VIAJANDO CON
30
JAVA
COMPLETANDO LA
34
VENTANA
UN PARÉNTESIS DE
34
PRIMERA
ENTRADA/SALIDA
41
CAPTURANDO
LECTURA
EXCEPCIONES
LOS
46 APPLETS Y LOS
ARCHIVOS MODESTO
46
NUESTRO
47
"EDITOR"
VOLVIENDO AL
49
MENÚ
AWT A LA
JAVA
51
DIÁLOGOS
54
DIBUJAVA
57
59
CANVAS EN
ACCIÓN
EL
60 APPLET-
CONTAINER
NUESTRO CANVAS A
60
MEDIDA
DIBUJAVA
61
VECTORES
II EN
62
ACCIÓN
FLICKER
MOLESTO!
64
64
66 Descargado de: http://technologycompartida.blogspot.com

Página 1
Descargado de: http://technologycompartida.blogspot.com

ANIMATE!
JAVA EN
67
HEBRAS
LOS PASOS
BÁSICOS
REUNIÓN DE
69
AMIGOS
CREANDO
69
THREADS
Y LOS
69
APPLETS...?
LA LIEBRE Y LA TORTUGA (Y EL
GUEPARDO)
71
SINCRONICEMOS LOS
72
RELOJES
MÁS
74
SINCRONIZACIÓN
CAPÍTULO XV - SOLUCIÓN AL PROBLEMA
75
PROPUESTO
MULTIMEDIA!
77
PARAMETRIZANDO UN
80
APPLET
PASEANDO
83 POR LA
LOS
RED
85
SOCKETS
86
87

Descargado de: http://technologycompartida.blogspot.com

Página 2
Descargado de: http://technologycompartida.blogspot.com

Java desde
Cero
Con ésta comienzo una serie de notas sobre Java,
especialmente
conocerlo para Esto
y usarlo. aquellos que quieren
se originó en un comenzar
interés quea surgió en
desarrolladores de web, y que
algunos de los suscriptores delpongo a list de
mailing
Seguramente muchosdel
disposición también dede
ustedes sabrán mucho más sobre
webmasters.
Java que yo, oy les agradeceré todo tipo de
comentarios
La idea es dar una guía ordenada para el estudio de este lenguaje,
correcciones.
muy poderoso
todavía adoleceydede algunas
gran coherencia, aunque
limitaciones que
seguramente se irán superando con el tiempo.
Qué es
Java
Java es un lenguaje originalmente desarrollado por un grupo de
ingenieros de Sun,
posteriormente comoutilizado porJavascript.
base para Netscape Si bien su uso se
aplicaciones
destaca en el (locales,
Web, sirve para crear todo tipo de
intranet
Java es uno internet).
• de
lenguaje:
• independiente de
objetos
la plataforma
Algunas

características
• gestiona
notables: rob la memoria
•usto no permite el uso de técnicas de
automáticamente

programación inadecuadas
• cliente-
multithr
• mecanismos de
eading
servidor
• herramientas
seguridad incorporados
de
documentación incorporadas
Lenguaje de
Objetos
Por qué puse "de" objetos y no "orientado a" objetos? Para
destacar
C++, no que,
es unallenguaje
contrario de otros lenguajes
modificado como
para poder trabajar con
objetos sino
trabajar que es un
con objetos lenguaje
desde cero. creado paraTODO
De hecho,
lo que hay en Java son objetos.
Qué es un
objeto?
Bueno, se puede decir que todo puede verse como un objeto.
nuestro puntomás
Pero seamos de vista,
claros.puede verse como
Un objeto, desdeuna pieza de

software que cumple con ciertas características:
• encapsul
amiento
here
Encapsulamiento significa que el objeto es auto-contenido, o sea
tantoncia
que la misma
los datosdefinición
que éste usadel(atributos)
objeto incluye
como los procedimientos
(métodos)
Cuando se que actúan
utiliza sobre los mismos.
programación orientada a objetos, se definen
forma
clases en
(queque los objetos
definen objetosinteractúan
genéricos)entre
y la ellos, a través de
dice que seAlcrea
mensajes. unauninstancia
crear objeto dedeuna
la clase,
clase odada,
un objeto
se
propiamente
"autos", y un dicho. Por ejemplo,
auto dado es una una clase podría ser
La ventajadedelaesto
instancia es que como no hay programas que actúen
clase.
modificando al objeto, éste del
cierto modo independiente se mantiene
resto de laenaplicación. Si es
necesario modificar el objeto (por
darle más capacidades), esto se puede ejemplo,
hacerpara
sin tocar el resto de
la aplicación… lo que ahorra mucho tiempo

Descargado de: http://technologycompartida.blogspot.com

Página 3
Descargado de: http://technologycompartida.blogspot.com

de desarrollo y debugging! En Java, inclusive, ni siquiera


existendelasaceptar,
difícil variables globales!
esto (Aunque
es una gran parezca
ventaja desde
En cuanto
el punto deavista
la herencia, simplemente significa que se pueden
del desarrollo).
crear nuevas clases
preexistentes; que hereden
esto simplifica de otras
la programación, porque las
métodos de incorporan
clases hijas las madres. automáticamente
Por ejemplo, nuestralos clase "auto" podría
simplemente
heredar de otra redefinir los métodos
más general, para ely caso particular de los
"vehículo",
automóviles…
buena bibliotecalode que significa
clases, que, con
se puede una mucho código
reutilizar
inclusive sin saber lo que tiene adentro.
Un ejemplo
simple
Para ir teniendo una idea, vamos a poner un
ejemplo de una clase Java:
public class Muestra
extends Frame
// atributos de {
Button
la clase
si;
Button
// métodos de
no;
public
la clase:
Muestra
Label () {
comentario = new Label("Presione
un=botón",
si new Label.CENTER);
no = new
Button("Sí");
Button("No");
add("North",
add("East
comentario);
add("West
", si);
}", no);
}

Esta clase no está muy completa así, pero da una idea… Es una
ventana) que tiene
clase heredera de launclase
par de botones
Frame y unde
(un tipo texto. Contiene dos
tipo Button,
atributos y un
("si" únicoque
y "no"), método llamado
son dos Muestra
objetos del (igual que
la clase, por lo que es lo que se llama un
construc
tor).
Independiente de la
plataforma
Esto es casi del
todorealidad,
En cierto…Java podría hacerse correr hasta sobre una
Commodore
todo 64! La
su potencial, realidadunessistema
requiere que para utilizarlo en
operativo
Cómo es esto? Porque
multithreading (como Unix, Windows95,
en realidad Java es OS/2…).
un lenguaje
interpretado…
Al compilar un al menos enJava,
programa principio.
lo que se genera es un
seudocódigo
genérica. definido
Luego, por Sun,
al correr sobrepara
una una máquina
máquina dada, el software
instrucciones,
de ejecución Javaemulando a dichainterpreta
simplemente máquina lasgenérica. Por supuesto
esto no escomo
Netscape muy eficiente,
Hotjava opor lo que tanto
Explorer, al ejecutar el código por
primera
JIT: Justvez, lo van
In Time compilando
compiler), (mediante
de modo que aluncrear por ejemplo la
esté compilado
segunda específicamente
instancia de un objeto el código ya
Además, Sun e Intel
para la máquina se han puesto de acuerdo para desarrollar
huésped.
procesadores
Java, con lo quequeplanean
trabajenhacer
directamente
máquinasenmuy baratas que puedan
Java cliente-servidor
conectarse a
a la red y ejecutar aplicaciones
muy
El bajo costo.
lenguaje de dicha máquina genérica es público, y si uno
quisiera hacersólo
Commodore un intérprete
tendría queJava para una y pedirle a Sun la
implementarlo
los requisitos
aprobación de Java
(para en cuantoque
que verifique a cómo interpreta
cumple con
cada instrucción, la seguridad, etc.)
Algunas
características…
Entre las características que nombramos nos referimos a la
robustez.
diseñado, Justamente por laelforma
Java no permite en directo
manejo que estádel hardware ni de
la memoria (inclusive no permite modificar
Descargado de: http://technologycompartida.blogspot.com

Página 4
Descargado de: http://technologycompartida.blogspot.com

valores de punteros, por ejemplo); de modo que se puede decir


que es virtualmente
programa imposible colgar un
Java. El intérprete
Inclusive el compilador
siempre tiene el control. es suficientemente inteligente como para
no permitir
traer un montón
problemas, de cosas
como usar que podrían
variables sin inicializarlas, modificar
métodos
valores deo punteros
variables directamente,
en forma incorrecta,
acceder a
Además, Java implementa
utilizar herencia mecanismos de seguridad que limitan
múltiple, etc.
el
se acceso
ejecuta,a especialmente
recursos de lasen máquinas donde
el caso de los Applets (que son
aplicaciones
ejecutan en el que se cargan desde un servidor y se
También está diseñado específicamente para trabajar sobre una
cliente).
red, de modo
permiten que aincorpora
acceder archivos objetos
en formaque
Además,
remota (viaconURL
el JDK
por (Java Development Kit) vienen
ejemplo).
generador
incorporadasautomático de documentación
muchas herramientas, entre que,
ellascon
un un poco de
atención
crea al poner
inclusive todalos
la comentarios
documentación en las
de clases,
las
mismas en formato HTML!
El Java
Development
Todo lo que puedan pedir para desarrollar

aplicaciones en Java está en:
Kit
En http://java.sun.com/abo
particular, deberían bajarse el JDK y
•utJava/index.html
el API Documentation de:
(Tambiénhttp://java.sun.com/java.sun.com/pro
les puede interesar en particular el Tool Documentation
Nota: ducts/JDK/1.0.2/index.html
y alguno de los
en este otros
site paquetes
también de tutorial
hay un la página)
de Java, aunque es un
El JDK
poco (versión
difícil 1.0.2)para
de seguir estáeldisponible para SPARC/Solaris,
principiante.
También
x86/Solaris, estáMS-Windows
disponible el 95/NT,
fuente para el que quiera adaptarlo
y MacOS.
parahay
que otrouna
sistema
versión operativo, y he leído por ahí
dando vueltas
Básicamente,
para Linux y HP-UX. el JDK
• de:
consiste el compilador
• eljavac
Java, intérprete
• unjava
Java, visualizador de
• el debugger
applets, appletviewerJava, jdb (que para trabajar
• el generador
necesita conectarse deal server de Sun)
documentación, javadoc
También se puede bajar del mismo site un browser que soporta
Java),
Java (yelde hecho está escrito totalmente en
Hotjava.
Para instalarlo simplemente hay que descompactar el archivo
(sugiero
pero tengan queen creen un directorio
cuenta NO java para eso),
Importante
DESCOMPRIMIR para los el usuarios
archivodeclasses.zip!
Windows95: todas estas
DOS. En particular,
aplicaciones utilizan nombres
deben ejecutarse largos
desde una y distinguen
ventana
mayúsculas
esto de minúsculas,
que es fuente de así que tengan en cuenta
Una
muchos cosaerrores.
muy importante: para que todo
ande•bienelaceitado,
directorioagreguen:
de los programas en
•el path
las (ej: c:\java\bin)
variables
de entorno:•
• CLASSPATH=.;C:\ja
•va\lib\classes.zip
HOMEDR
•IVE=C:
HOMEP
con los valores ATH=\HOM
Noten
adecuados que en
a su E=C:\
CLASSPATH
entorno. agregué el directorio actual (.), para
poder compilar y ejecutar desde cualquier
directo
rio.
Empecemos de
una
comenzar vez!
Bueno, suponiendo que hayan instalado todo, y antes de
aclaraci a programar en Java, una pequeña
ón :

Descargado de: http://technologycompartida.blogspot.com

Página 5
Descargado de: http://technologycompartida.blogspot.com

En realidad se puede decir que


• Javas
hay tres Javascript:por ahí:
es una versión de Java directamente
interpretada,
página HTML, que se incluye
lo que locomo
hace parte de una
muy fácil y cómodo para
aplicaciones
realidad tienemuy pequeñas, pero que en
muchas
• no soporta
limitaciones:
•clases noniseherencia
• no es obligatorio
precompila
•declarar las variables
verifica las referencias en
•tiempo de ejecución
no tiene protección del código,
•ya que
no se bajalos
todos enbrowsers
ascii lo soportan completamente;
Explorer,
últimas poradiciones
ejemplo,de noNetscape,
soporta lascomo
• Java standalone: las imágenes animadas.
programas Java que se ejecutan
•directamente mediante elJava
Applets: programas intérprete java. bajo el entorno
que corren
En sídelosundosbrowser
últimos (o son
del el
appletviewer)
mismo lenguaje, pero cambia un
poco la forma
principal en que se implementa
(la aplicación). Vamos a verelcómo
objetocrear las
casi igual en para
aplicaciones formaque, standalone o como
sin cambios, applet (en
se puedan realidad hay
ejecutar
cosas que
acceder los applets
a archivos sinno pueden hacer, como
autorización).
Javasc
ript
No vamos a detenernos mucho en Javascript, por las
dedicarnos
limitacionesunantedichas;
poco a estesilenguaje en el
les interesa futuro. Por
podemos
ahora, sólo un
Calculadora enejemplo sencillo:
Javascript:
<HTM
<HEA
L>
D>
<SCRIPT
function
LANGUAJE="Javascript
"> if (confirm("¿Está
calcula(form) {
seguro?"))
form.resultado.value =
eval(form.expr.value)
else alert("Vuelva a
intentarlo...")
}</SCRI
</HEA
PT>
D>
<BOD
<FOR
Y>
M>Introduzca una
expresión:
<INPUT TYPE="text"
<INPUT TYPE="button"
NAME="expr" SIZE=15> NAME="Boton" VALUE="Calcular"
ONCLICK="calcula(this.form)">
<BR
> <INPUT TYPE="text"
Resulta
NAME="resultado"
do: SIZE=15>
<BR
</FOR
>
</BOD
M>
</HT
Y>
ML>
Básicamente, el código se encuadra entre los tags
mismo mediante un form (<FORM>…</FORM>).
<SCRIPT>…</SCRIPT>, y los parámetros se pasanElal
lenguaje utilizado
básicamente es muy
el código parecido
se ejecuta al C++,una
mediante y acción de un
botón
Al (…ONCLICK="calcula(this.form)").
presionar el botón, se llama a la función calcula con el
pertenece
parámetroel this.form, que se refiere al form al que
botón.

Descargado de: http://technologycompartida.blogspot.com

Página 6
Descargado de: http://technologycompartida.blogspot.com

La función asigna al valor del campo resultado del


(form.resultado.value)
form que se le pasa comoel resultado
parámetrode evaluar el valor de la
expresión del campo expr de dicho form
(eval(form.exp
r.value)).
Hay MUCHOS ejemploes

de Javascript en:
incluyendohttp://www.c2.net/~and
decenas de calculadoras,
Allí reww/javascript/
juegos y otrasencontrarán
también yerbas! la documentación y
un tutorial sobre Javascript.

Las clases
en
montón Java
Bueno, antes que nada conviene saber que en Java hay un
de clases
Éstas vienen en lasya definidas y utilizables.
• java.lang
bibliotecas estándar: - clases esenciales, números, strings, objetos,
compilador,
el único runtime,
paquete que seguridad y threads (es
se incluye
• java.io - clases que
automáticamente en todo programa Java)
• java.util
manejan entradas y salidas
- clases útiles, como estructuras genéricas,
manejo de fecha,
aleatorios hora y strings, número
• java.net
, etc. - clases para soportar redes:
• java.awt
URL, TCP, UDP, IP, para
- clases etc. manejo de
• java.awt.image - clasesetc.
interface gráfica, ventanas, para
• java.awt.peer
manejo de imágenes - clases que conectan la interface gráfica
a implementaciones
plataforma (motif, dependientes de la
• java.applet - clases para la creación de applets y
windows)
Pararecursos para
que se den unareproducción de audio.
idea, los números enteros, por ejemplo,
son
Integer, que desciende de la claseredefinible,
"instancias" de una clase no Number e
implementa los siguientes atributos y métodos:
public final class java.lang.Integer
// java.lang.Number {
extends
Atributos
public final static int
MAX_VALUE;
public final static int
// Métodos
MIN_VALUE;
Constructores
public
public
Integer(int
// Más
Integer(String
value);
Métodos
s);public double
doubleValue();
public boolean
public float obj);
equals(Object
floatValue();
public static Integer
public static Integer
getInteger(String nm);
public static Integer
getInteger(String nm, int val);
getInteger(String
public int nm, Integer val);
hashCode();
public int
public long
intValue();
longValue();
public static int
public static int
parseInt(String s);
public static String
parseInt(String s, int radix);
toBinaryString(int
public static String i);
toHexString(int i);
public static String
public String i);
toOctalString(int
toString();
public static String
toString(int i);

Descargado de: http://technologycompartida.blogspot.com

Página 7
Descargado de: http://technologycompartida.blogspot.com

public static String


toString(int i, int
public static radix);
Integer
public static Integer
valueOf(String s);
}valueOf(String s, int radix);
Mucho,
Esto también nos da
no?
• ideas:
algunas la estructura
• una
de clase hay
caramba,
métodos repetidos!
De la estructura enseguida hablaremos; en cuanto a los métodos
repetidos (como
llamarse al método parseInt por ejemplo),
el compilador decidealcuál de las
implementaciones del mismo usar
cantidad y tipo de parámetros que le basándose
pasamos.enPorla ejemplo,
compilarse, generarán
parseInt("134") llamados a
y parseInt("134",16), al
dos métodos distintos.
Estructura de
unaclaseclase
Una
consiste en:
algunas_palabras class
nombre_de_la_clase [lista_de_atri
[algo_más] {
butos]
[lista_de_mé
} todos]
Lo que está entre [ y ]
es opcional…
Ya veremos qué poner en "algunas_palabras" y
La lista de atributos
"algo_más", por ahora (nuestras
sigamosviejas variables
un poco más. locales) sigue el
ymismoluegoformato
el nombrede del atributo,
C: se define primero el tipo
ypublic
finalmente el ";".int
final static
;
MAX_VALUE
También tenemos "algunas_palabras" adelante,
perocuanto
En en seguida las analizaremos.
a los métodos, también siguen la
sintaxis del C; un ejemplo:
public int incContador() { //
declaración
cnt++; y apertura de { //
instrucciones, separadas por ";"
}return(cn
Finalmente,
t); se aceptan comentarios entre /* y */, como en C, o
bien usando
// cierre
comentario // al principio
de }termina al del comentario (el
Veamos
final de launlínea).
ejemplo:
// Implementación de un
// GRABAR
contador EN UN ARCHIVO"Contador.java"
sencillo
// COMPILAR CON: "javac
Contador.java"
(OJO
// ESTA CON LAS(NO
CLASE NOOLVIDAR
MAYUSCULAS!) EL .java!)
ES UNA APLICACION,
pero nos va a servir enseguida
public class Contador
{
//
//int
Secnt;
Atributodefine la clase Contador
s /
/ //
Un entero para guardar el valor actual
Constructor
public Contador() { //
…lleva
cnt = el mismo nombre que la clase
//}Un método constructor…
0;

////Simplemente, inicializa (1)


Método
s
Descargado de: http://technologycompartida.blogspot.com

Página 8
Descargado de: http://technologycompartida.blogspot.com

public int incCuenta() { //


Un método para incrementar el contador
return
cnt++;
cnt;
}
//public int getCuenta()
incrementa cnt { //
// yreturn
Este desólo
pasodevuelve
devuelve el el
valor
nuevo
actual
valor
cnt;
}
}
// del contador
Cuando, desde una aplicación u otro objeto, se crea una
instancia de la clase Contador, mediante la
instrucc
new
ión:
Contador()
el compilador busca un método con el mismo nombre de la
clase y al
cuanto que se ycorresponda
tipo número de con la llamada
parámetros. en método se llama
Dicho
Constructor,
un constructor y una clase
(no así unpuede
objetotener más de ya que una vez
o instancia,
mism
que fue creado no puede recrearse sobre sí
o).
En tiempo de ejecución, al encontrar dicha instrucción, el
crea su estructura
intérprete y
reserva espacio para el objeto/instancia,
O sea al
llama que el efecto de new Contador() es, precisamente, reservar
constructor.
espacio para el contador e inicializarlo en
cer
o.
En cuanto a los otros métodos, se pueden llamar desde otros
mismo
objetos modo
(lo queque se llama
incluye a las aplicaciones) del
una ejemplo,
Por función desde
usemos C. nuestro contador en un programa bien
sencillo que nos muestre cómo evoluciona:
// Usemos nuestro contador en
una
// mini-aplicación
GRABAR EN UN ARCHIVO"Ejemplo1.java"
// COMPILAR CON: "javac
(OJO
// EJECUTAR
CON LAS
Ejemplo.java" CON:
MAYUSCULAS!)"java (NO OLVIDAR
Ejemplo1"
EL .java!) (SIN el .java)
import java.io.*;

public
// Uso laclass
biblioteca
Ejemplo1 de entradas/salidas
{ //
IMPORTANTE: Nombre de la clase // igual al nombre
// entero para asignarle el valor del del archivo!
contador
// aunquee en
imprimirlo
realidad
nostatic
me hace falta.
int// n;
y una variable tipo Contador
para instanciar
static Contadorel objeto…
laCuenta;
// ESTE METODO, MAIN, ES EL QUE
HACE// COMO QUEAPLICACION.
ESTO SE COMPORTE Es donde arranca el
// NOTA:cuando
programa main debe ser "java Ejemplo1"
ejecuto
public&static
public void main (
static.
StringSystem.out.println
args[] ) { ("Cuenta…
");laCuenta = new
System.out.println (laCuenta.getCuenta()); // 0
Contador();
-// Imprimo
Imprimo
n= el
elvalor
títuloactual (cero!)
System.out.println
// Creo
laCuenta.incCuenta();
una instancia del Contador
(n);laCuenta.incCuenta();
// 1System.out.println
- Asignación e incremento
- Lo incremento
// 2Ahora imprimo n (no uso el valor…
(laCuenta.getCuenta());
System.out.println
}
(laCuenta.incCuenta());
}// …de retorno) y lo imprimo
En
// 3 el capítulo
- Ahora todoIII en
vamos a analizar este programa en detalle. Por
un paso!
haga
ahoraloveamos la diferencia con un applet que
mismo:

Descargado de: http://technologycompartida.blogspot.com

Página 9
Descargado de: http://technologycompartida.blogspot.com

// Applet de acción similar a la


// GRABAR
aplicación EN
Ejemplo1
ARCHIVO:
// COMPILAR CON:
// PARA EJECUTAR: Crear una página
import "Ejemplo2.java"
HTML
"javac como se indica luego
Ejemplo2.java"
java.applet.*;
import
java.awt.*;
public class Ejemplo2
extends
static Applet {
intstatic
n; Contador
laCuenta;
//
Constructo
public
r…laCuenta()={ new
Ejemplo2
Contador();
}

// El método paint se ejecuta cada


vez que hay que
// NOTAR redibujar DE ESTO CUANDO
EL EFECTO
SE CAMBIA DE
// VENTANA DELTAMAÑO LA
public void paint
NAVEGADOR!
(Graphics g) {
g.drawString
g.drawString
("Cuenta...", 20, 20);
n=
(String.valueOf(laCuenta.getCuenta()),
laCuenta.incCuen
20,g.drawString
35 );
ta();
(String.valueOf(n), 20, 50
); g.drawString
laCuenta.incCu
(String.valueOf(laCuenta.getCuenta()),
enta();
g.drawString
20,
} 65 );
(String.valueOf(laCuenta.incCuenta()),
}20, 80 );

Ahora es necesario crear una página HTML para poder


ejemplo2.htm conesto,
visualizarlo. Para un browser
crear y que
luegosoporte
cargarJava (o bien
el archivo
ejecutar en la ventana DOS: "appletviewer
ejemplo2.
htm"):
<HTM
L>
<HEA
D>
<TITLE>Ejemplo 2 - Applet
</HEA
Contador</TITLE>
<BOD
D>
Y>
<applet code="Ejemplo2.class"
</appl
width=170 height=150>
et>
</BOD
Y>
</HT
ML>
Para terminar este capítulo, observemos las diferencias
entre• la aplicación standalone
La aplicación y el applet:
usa un método
• El applet, en cambio, se arranca desde un constructor
main, desde donde arranca
Adem (método con el mismo nombre que la clase)
ás: • En la aplicación utilizamos System.out.println
• En
para imprimir en necesitamos
el applet la salida estándar
"dibujar" el texto sobre un
fondo gráfico, por lo que del
g.drawString dentro usamos
métodoel método
paint (que es llamado cada
Con pocovez trabajo se necesario
que es pueden combinar
redibujarambos casos en un solo
el applet)
objeto, dede
utilizarla modo
las que la misma clase sirva para
dos maneras:
Descargado de: http://technologycompartida.blogspot.com

Página 10
Descargado de: http://technologycompartida.blogspot.com

// Archivo:
// Compilar con: javac
Ejemplo3.java
Ejemplo3.java
import
import
java.applet.*;
import
java.awt.*;
java.io.*;
public class Ejemplo3
static Applet {
extends
intstatic
n; Contador
laCuenta;
public
Ejemplo3
laCuenta()={ new
Contador();
}

public static void


laCuenta =args[])
main(String new {
Contador();
paint()
}
;
public static
void paint () {
System.out.println
System.out.println
("Cuenta...");
n=
(laCuenta.getCuenta());
laCuenta.incCuen
ta();
System.out.prin
tlnSystem.out.println
(n);
laCuenta.incCu
(laCuenta.getCuenta());
enta();
System.out.println
}
(laCuenta.incCuenta());
public void paint
(Graphics g) {
g.drawString
("Cuenta...",
g.drawString20, 20);
n=
(String.valueOf(laCuenta.getCuenta()),
laCuenta.incCuen
20,g.drawString
35 );
ta();
(String.valueOf(n), 20, 50
g.drawString
laCuenta.incCu
);
(String.valueOf(laCuenta.getCuenta()),
enta();
g.drawString
20,} 65 );
(String.valueOf(laCuenta.incCuenta()),
}20, 80 );
Esta clase puede ejecutarse tanto con "java Ejemplo3" en una
HTML
ventana DOS, como cargarse desde una página
con:
<applet code="Ejemplo3.class"
width=170 height=150>
</appl
Notar que conviene probar el applet con el appletviewer
et>
la ventana DOSejemplo3.htm"),
("appletviewer si hay algún errorya durante
que éstelaindica
ejecución.
en Los
browsers
simplemente dejan pasar muchos
suprimiendo errores,
la salida a
pantalla del código erróneo.
Notar que en todo este desarrollo de las clases Ejemplo1,
Ejemplo2 aytocar
volvimos Ejemplo3,
la en ningún momento
clase Contador!

Descargado de: http://technologycompartida.blogspot.com

Página 11
Descargado de: http://technologycompartida.blogspot.com

Estructura de
clases
Vamos a comenzar analizando la clase Contador, para ir viendo
las detalle.
en partes que
Esteforman unavaclase
capítulo a seruna por una
un poco y
aburrido por lo
exhaustivo
como (aunque algunos
las excepciones puntos los
y los threads másdejaremos
complicados
para
completo
después), de la me parece bueno tener un resumen
pero
Luego
sintaxisiremos
desde armando
ahora. pequeñas
aplicaciones
Recordemos para probar cada
la definición de cosa.
la clase Contador:
// Implementación de un
public
contadorclass
sencillo
Contador {
//
int
Atribut
//
cnt;
os
Construc
public
tor
Contador()
cnt = {
}
0;
//
public
Métod int
cnt+
incCuenta()
os {
+;
return
cnt;
}
public int
getCuenta()
return {
}
cnt;
}

Declaración de
laclase
La clasese declara mediante la línea public class Contador. En el
caso
clase más general,
puede la declaración
contener los de una
siguientes elementos:

Descargado de: http://technologycompartida.blogspot.com

Página 12
Descargado de: http://technologycompartida.blogspot.com

[public] [final | abstract] class Clase [extends ClaseMadre]


bien, para Interfase1 [, Interfase2 ]…]
o[implements
[public] interface Interfase [extends
interfaces:
InterfaseMadre1
Como [, InterfaseMadre2
se ve, lo único ]…] y el nombre de la
obligatorio es class
particular
clase. Las que veremos
interfases son un caso de clase
más adelante.
Public, final o
abstract
Definir una clase como pública (public) significa que puede
ser usadaSi
paquete. pornocualquier clase enpuede
lo es, solamente cualquier
ser utilizada por clases del
básicamente,
mismo paquete se (más
trata sobre
de un paquetes
grupo de luego;
clases e interfaces
incluídos
relacionadas, como los paquetes de biblioteca
con Java).
Una clase final (final) es aquella que no puede tener clases que
razones de seguridad
la hereden. (parabásicamente
Esto se utiliza que una clase porno pueda ser
reemplazada
aplicac por otra que la herede), o por diseño de la
ión.
Una clase abstracta (abstract) es una clase que puede tener
literalmente,
herederas, peroabstracta
no puede (como la clase Number
ser instanciada. Es, definida en
conceptos. Por ejemplo,
java.lang). ¿Para la clase
qué sirve? ParaNumber
modelar es una clase abstracta
que métodos
sus representanocualquier tipo de números
están implementados: son(yabstractos); las clases
sí implementandelos
descendientes métodos
ésta, como de la madre
Integer o Float,
Number,
Por y se una
lo dicho, puedenclaseinstanciar.
no puede ser final y abstract a la
vez (ya que la clase abstract requiere
descendien
tes…)
¿Un poco complejo? Se va a entender mejor cuando veamos
definición son abstractas
casos particulares, como lasya que no (que por
interfases
implementan sus métodos).
Exten
ds
La instrucción extends indica de qué clase desciende la nuestra.
Si se omite, Java asume que desciende de la
superclase
Cuando una clase desciende de otra, esto significa que hereda
Object.
menos que losy redefinamos,
sus atributos susdecir
sus métodos (es métodos
que, son
a los mismos que
los de transparente,
forma la clase madrea ymenos
pueden
queutilizarse en
sean privados en la clase
protegidos o propios
madre o, para delde
subclases paquete). Veremos la calificación
otros paquetes,
de métodos muy pronto, a no desesperar!
Implem
ents
Una interfase (interface) es una clase que declara sus métodos
implementa (implements)cuando
pero no los implementa; una o más interfases, debe contener la
una clase
implementación
las mismas listasde detodos los métodos (con
parámetros)
Esto sirve interfases.
de dichas para dar un ascendiente común a varias clases,
obligándolas
por lo tanto, aacomportarse
implementarde losforma
mismos métodos
similar y, a su
en cuanto
interfase con otras clases y subclases.
Interfa
ce
Una interfase (interface), como se dijo, es una clase que no
implementación a otras clases.
implementa sus métodos Lasdeja
sino que interfases
a cargopueden,
la asimismo,
clase
descender de otras interfases pero no de otras
s.
Todos sus métodos son por definición abstractos y sus atributos
son finales
cuerpo de la(aunque esto no se indica en el
Son útiles para generar relaciones entre clases que de otro
interfase).
modo no estánlos
implementen relacionadas (haciendo
mismos métodos), que distribuir paquetes de
o para
pero
clasesnoindicando
las claseslaindividuales
estructura de la interfase
Si bien diferentes
(objetos anónimos). clases pueden implementar las mismas
interfases,
no y a la vez
es en realidad descender
herencia de otras
múltiple clases,
ya que esto no puede
una clase
heredar
las clasesatributos ni métodosuna
que implementan de interfase
una interface; y no
pueden
estar ni siquiera relacionadas entre sí.

Descargado de: http://technologycompartida.blogspot.com

Página 13
Descargado de: http://technologycompartida.blogspot.com

El cuerpo de
lacuerpo
El clase de la clase, encerrado entre { y }, es la lista de
constituyen
atributos (variables) y métodos (funciones) que
la
Noclase.
es obligatorio, pero en general se listan primero
los atributos y luego los métodos.
Declaración de
atributos
En Java no hay variables globales; todas las variables se declaran
método.
dentro delLas variables
cuerpo de ladeclaradas dentro
clase o dentro de de
un un método son
locales de
cuerpo al método;
la clase selasdice
variables
que sondeclaradas
miembros ende
el la clase y son
Por otra parte,
accesibles además
por todos losdemétodos
los atributos de la propia clase se puede
de la clase.
la que desciende;
acceder a todos lospor ejemplo,
atributos decualquier
la clase declase que descienda de la
clase Polygon
xpoints e hereda los atributos npoints,
ypoints.
Finalmente, los atributos miembros de la clase pueden ser
que son atributos
atributos de clase de clase si se
o atributos deusa la palabra
instancia; clave static: en
se dice
ese caso la(objetos)
instancias variable es de única para
la clase todasun
(ocupa lasúnico lugar en memoria).
nuevo
Si no separa
usaesa variable
static, con cada
el sistema creainstancia
un lugar (o sea que
La declaración sigue
es independiente parasiempre
cada objeto).
el mismo esquema:
[private|protected|public] [static] [final] [transient]
[volatile] Tipo NombreVariable [= Valor];
Private, protected
oJava
public
tiene 4 tipos de acceso diferente a las variables o métodos de
paquete
una clase:(siprivado,
no se protegido, público o por
De acuerdonada).
especifica a la forma en que se especifica un atributo, objetos de
otras
accederclases tienen distintas posibilidades de
los:
Acceso desde:
la propia claseSSSS privateprotectedpublic(p
ackage)
subclase en
paquete NSSS
el mismo
otras clases en el NSSSmismo
paquete
subclases
paquetes NXSN
en otros
otras clases
paquetes NNSN
en otros
S: puede
acceder
N: no puede
X: puede acceder al atributo en objetos que pertenezcan a la
acceder
subclase,
madre. Espero no en
un caso los que; pertenecen
especial a la clase
más adelante
veremos ejemplos de todo esto.
Static y
final
Como ya se vio, static sirve para definir un atributo como de
clase, o sea único para todos los objetos de la
clas
En cuanto a final, como en las clases, determina que un atributo no
e.
pueda
no ser sobreescrito
se trata o redefinido. O sea:
de una variable,
sino de una constante.
Transient y
volatile
Son casos bastante particulares y que no habían
Transient denomina atributos
sido implementados que no se graban cuando se
en Java 1.0.
estado
archivapermanente
un objeto, o sea que no forman parte del
del mismo.

Descargado de: http://technologycompartida.blogspot.com

Página 14
Descargado de: http://technologycompartida.blogspot.com

Volatile se utiliza con variables modificadas asincrónicamente por


objetos en
"hilos", diferentes
tareas que se threads
ejecutan(literalmente
en paralelo); básicamente esto
modificar
implica quela distintas
variable tareas
simultáneamente, y volatile asegura
pueden intentar
que se vuelvacada
modificada) a leer
vezlaque
variable (por
se la va si fue(esto es, en lugar de usar
a usar
registros de almacenamiento como buffer).
Los tipos
de
Los Java
tipos de variables
• tipos
disponibles sonbásicos
básicamente
(no 3:
•son objetos)
arreglos
• clases e
(arrays)
Con interfases
lo que vemos que cada vez que creamos una clase o
Los tiposestamos definiendo un nuevo tipo.
interfase
básicos son:
TipoTamaño/FormatoDescripción
byte8-bit complemento a 2Entero de un
byte
short16-bit complemento a 2Entero
corto
int32-bit complemento a 2Entero
long64-bit complemento a 2Entero
largo
float32-bit IEEE 754Punto flotante, precisión
simple
double64-bit IEEE 754Punto flotante, precisión
doble
char16-bit caracter UnicodeUn
caracter
booleantrue, falseValor booleano (verdadero o falso)
Los arrays son arreglos de cualquier tipo (básico o no). Por
objetos
ejemplo,deexistedichauna clase Integer; un arreglo de
Integer
clase se notaría:
vector[
Los ];
arreglos siempre son dinámicos, por lo que
Integer
no es válido poner algo como:
cadena[5];
Aunque sí es válido inicializar
un arreglo,
int días[ ] =como{ 31, en:
28, 31, 30, 31, 30,
char
31, 31, letras[ ] = 30,
30, 31, { 'E',
31'F',
}; 'M', 'A', 'M',
String nombres[
'J', 'J', 'A', 'S', 'O',]'N',
= 'D' };
new
NotaString[12];
al margen: no confundir un String (cadena de caracteres)
distint
con un arreglo de caracteres! Son cosas bien
as!
Ya hablaremos más adelante de las
clases
En Java,String
paraytodas
StringBuffer.
las variables de tipo básico se accede al
conoce la dirección
valor asignado de memoria
a la misma que ocupa).
directamente (no sePara las demás
un puntero
(arrays, a laovariable.
clases El valor
interfases), del puntero
se accede a travésnodees accesible ni
se puedeesto
necesita modificar
y además(como
eso en C); Java no
atentaría
De
contrahecho, en Java del
la robustez no existen
lenguaje.los tipos pointer, struct o union.
Un objeto
uniones noessemás
hacenquenecesarias
una estructura,
con uny método
las de programación
adecuado (y además
acceder a los datos se evita la posibilidad de
Algo más respecto a los arreglos: ya que Java gestiona el
incorrectamente).
excepciones
manejo de memoria si se intenta
para violar el espacio
los mismos, asignado a una
y lanza
variable,ase
acceder evitande
lugares problemas
memoria típicos de Cocomo
prohibidos fuera del lugar
subíndice
definido para máslagrande
variableque(como
lo cuando se usa un
previsto para un arreglo…).
Y los
métodos…
Los métodos, como las clases, tienen
unadeclaración
La declaración y un cuerpo.
[private|protected|public]
es del tipo: [static] [abstract] [final] [native]
([synchronized]
[tipo1 nombre1[, tipo2 nombre2
TipoDevuelto ]…] ) [throws
NombreMétodo
excepción1
A [,excepción2]…
no preocuparse: ]
poco a poco
aclararemos todo con ejemplos.

Descargado de: http://technologycompartida.blogspot.com

Página 15
Descargado de: http://technologycompartida.blogspot.com

Básicamente, los métodos son como las funciones de C:


implementan,
estructuras de acontrol,
través de funciones,
el cálculo operaciones
de algún y que es el
parámetro
pueden devolver
que devuelven al un valorque
objeto (del
lostipo TipoDevuelto),
llama. Sólo aunque
pueden no devolver
TipoDevuelto ninguno
es void). Como(en ya ese caso el valor de retorno se
veremos,
del
especifica con la instrucción return, dentro
Los métodos pueden utilizar valores que les pasa el objeto que
método.
nombre1,
los tipo2 nombre2…
llama (parámetros), en el con tipo1
indicados
esquema de la declaración.
Estos parámetros pueden ser de cualquiera de los tipos ya
valor
vistos.del
Si parámetro; si son arrays,
son tipos básicos, el métodoclases o interfases,
recibe el recibe un
puntero a los datos (referencia). Veamos un
pequeño
ejemplo:
public int
AumentarCuenta(int
cnt = cnt +
cantidad) {
cantidad;
return
}
cnt;

Este método, si lo agregamos a la clase Contador, le suma


• el
cantidad al método
acumuladorrecibe unEn
cnt. valor
detalle:
•enterolo (cantidad)
suma a la variable
•de instancia
devuelvecnt la
¿Cómo suma
hago(return cnt) devolver más de un valor? Por ejemplo,
si quiero
dentro de unaque
supongamos clase que devuelva
queremos hacer un método
la posición
Lo siguientedel mouse.
no sirve:
void
x = ….;
GetMousePos(int x, //
int y) { yesto
= ….;
no sirve! //
} esto tampoco!
porque el método no puede modificar los parámetros x e y
(que hanrecibe
método sido pasados
el valor por valor, opero
numérico sea noquesabe
el
La solución
adónde estáneslas
utilizar, en lugar
variables de
en memoria).
tipos básicos, una clase:
class MousePos {
y luego utilizar esa clasepublic
en int x, y; }
nuestro método:
void GetMousePos(
MousePos mm.x ) {=
……;
m.y =
} ……;

El resto de la
declaración
Public, private y protected actúan exactamente igual para los
métodos que para los atributos, así que veamos
el
Los métodos estáticos (static), son, como los atributos, métodos
resto.
de clase;desi instancia.
método el métodoEl nosignificado
es static eses
unel mismo que para los
todas las instancias
atributos: un método static es compartido por
de
Ya lahemos
clase.hablado de las clases abstractas; los métodos abstractos
declaración
(abstract) son pero no la implementación
aquellos de los que se da (o
la sea que consiste sólo
contenga al menos un Cualquier
del encabezamiento). método abstracto (o cuya clase madre
clase que
contenga
esté al menos un
implementado en método abstracto que no
la hija) es
unafinal
Es claseunabstracta.
método que no puede ser redefinido por
ningún descendiente de la clase.

Descargado de: http://technologycompartida.blogspot.com

Página 16
Descargado de: http://technologycompartida.blogspot.com

Las clases native son aquellas que se implementan en otro


lenguaje (por
máquina. Sun ejemplo
aconsejaCutilizarlas
o C++) propio de la propio, ya que
bajo riesgo
posibilidad de usar
en realidad son viejas
ajenas bibliotecas
al lenguaje. quelauno armó y
Pero
no tiene
Las ganas
clases de reescribir
synchronized existe!.sincronizar varios threads
permiten
concurrentemente
para el caso en queadoslos omismos datos. De nuevo, más detalles
más accedan
Finalmente, la cláusula
habrá en el futuro, cuandothrows sirve para
hablemos indicar que la
de threads.
clase genera determinadas excepciones.

El cuerpo de los
métodos
Otra vez recordaremos nuestra
vieja clase Contador:
// Implementación de un
contador
public sencillo
class
…………
Contador {
……..
public int
incCuenta()
cnt+ {
return
+;
}
cnt;
…………
………
}

Dentro de los métodos


• incluirse:
pueden Declaración de
• Asignaciones
variables locales
a variables
Descargado de: http://technologycompartida.blogspot.com

Página 17
Descargado de: http://technologycompartida.blogspot.com

• Operaciones
• Llamados a
matemáticas
• dentro de
otros métodos:
• clase
la de instancia, de
• de
otras clases
clase, de
• Estructuras clase
cualquier
• control
de Excepciones (try, catch, que
veremos más adelante)
Declaración de
variables
Las locales
variables locales se declaran igual
Tipo
que los atributos de la clase:
Ej: int
NombreVariable [=
suma;
Valor];
float
Contador
precio;
laCuenta;
Sólo que aquí no se declaran private, public, etc., sino que las
variables definidas dentro del método sólo son
accesibles
Las variables pueden
por él.
Ej: int
inicializarse al crearse:
sumaprecio
float = 0;
Contador
= 12.3; laCuenta =
new Contador ( );
Asignaciones a
variables
Se asigna un valor a una variable
mediante
Variable =elConstante
signo =:
|Ej:Expresión
suma = ;
precio
suma +=1;1.05
* precio;
laCuenta.c
El
nt =último
0; caso es válido si cnt es una variable pública de la
conveniente
clase Contador. acceder directamente
Personalmente no acreo
variables de otro objeto, ya
oquedelfuturas
que llama puede propender
modificaciones la difusión
del objeto de errores… Es
llamado
mejor usarinicializarContador
hipotético métodos como getCuenta o unDe hecho, algunos
para ello.
declaren
sugieren como
que todas las variables de una clase se
private.
En el primer caso, o
Variable = Variable
sea en general:
se puede escribir
Operador en
Expresión;
forma más
Variable sencilla:
Operador=
Expresión;
Por ejemplo, suma =
puede
suma +escribirse: suma
9 - cantidad;
y+=precio
9-cantidad;
=
como:
precio *precio
0.97;
*= 0.97;
Operaciones
matemáticas
Hay varios tipos de
operadores:
Unarios: + - ++ -- ~ !
(tipo)
Se …..etc.
colocan antes (o en algunos casos
después)
Por de la-cnt;
ejemplo: constante o expresión.
// cambia de signo; por ejemplo si cnt es
12 el resultado
++cnt; es -12; cnt no cambia.
// equivale
cnt++;
a cnt +=// 1;
equivale a cnt +=1; veremos la diferencia
--cnt; // equivale
al hablar de estructuras de control
a cnt -=
cnt--; 1;
// equivale
Binarios:
a cnt -= 1;+ - * /
% …..etc.
Van entre dos constantes o expresiones
o combinación de ambas.
Descargado de: http://technologycompartida.blogspot.com

Página 18
Descargado de: http://technologycompartida.blogspot.com

Por ejemplo: cnt + 2; //


debuelve la+ suma
promedio ( valorde/ 2);
ambos.
// como se ve,
horas / hombres;
se pueden usar paréntesis.
// división. % 3; // resto de la
acumulado
Nota: + sirve
división enteratambién para concatenar cadenas de caracteres;
entre ambos.
Cuando
hablaremosse mezclan
de StringStrings y valores pronto.
y StringBuffer numéricos, éstos se
convierten automáticamente
"La frase tiene "+ a cadenas:
cant + " letras"
se convierte en: "La frase tiene 17 letras"
// suponiendo que cant = 17
Precedencia de
operadores
La siguiente es laen Java de los operadores en expresiones
precedencia
compuestas.
los lenguajes,De se todos modos,usar
recomienda como en todos
Posfijos
paréntesis [] en
. (params)
caso de duda.
Operadores
expr++ expr-- unarios ++expr --
expr +expry "cast"
Creación -expr ~ !
Multiplicativ
new (type)
Aditivos
os * / %
+-
Desplazamiento
<< >> >>> < > <=
Relacionales
Igualdad
>= instanceof
==
AND != bit a
OR
bit &exclusivo
OR
bit ainclusivo
bit ^
bit a bit |
AND
lógico &&
OR
Condicion
lógico ||
al ? :
Asignación = += -= *= /= %= ^=
&= |= <<= >>= >>>=
Algunos
[] define arreglos:
ejemplos:
int lista[];es la lista de parámetros cuando se llama a
(params)
new permiteconvertir(valor,
un método: crear una instancia
base);de un
objeto:cambia
(type) new Contador();
el tipo de una expresión
a otro:
>> (float)(total
desplaza bit a bit%un10);
valor
<= devuelve
binario: base "true"
>> 3; si un valor es menor o
instanceof
igual que otro:devuelve "true"
total <= si el objeto es una instancia
maximo;
||dedevuelve
la clase: "true"
papa instanceof Comida;
si cualquiera de las
expresiones es verdad: (a<5) || (a>20)
Llamadas a
métodos
Se llama a un método de la misma clase simplemente con el
paréntesis,
nombre delcomométodo se yve,losentre otros, entre
parámetros
en el ejemplo en negrita:
// Archivo:
// Compilar con:
Complejo.java
public final class Complejo java
extends Number {
c Complejo.java
//
atributo private
s: float x;
private
// float y;
public Complejo(float
construct
rx, float iy) {xor:=
rx;
y=
} iy;
//
método
s:
Descargado de: http://technologycompartida.blogspot.com

Página 19
Descargado de: http://technologycompartida.blogspot.com

public float
Norma() { return
} (float)Math.sqrt(x*x+
// obligatorios
y*y);
(son
public double abstractos en Number):
doubleValue()return
{
} (double)Norma(
public float );
floatValue()return
{
} Norma();
public int
intValue() {return
} (int)Norma()
public long ;
longValue()return
{
} (long)Norma(
public String);
toString() { return
} "("+x+")+i("+y+
}")";

Pueden probar la clase (mínima) con el siguiente ejemplo de


un llamado la
aplicación; a un método
línea de unesobjeto
en negrita de otrade
un ejemplo clase. Notar que
sobre
es esteun objeto
caso, (instancia)llamar al método
es necesario
existente, por lo que se indica:

Nombre_del_Objeto<punto>Nombre_
del_Método(parámetros)
// Archivo:
Ejemplo4.java
// Compilar con: javac
Ejemplo4.java
// Ejecutar con: java
import
Ejemplo4
java.io.*;
public class
public static
Ejemplo4 { void
main(String
Complejo args[]) { = new
numComp
Complejo(4,-3);
System.out.println(numCom
System.out.println(numCo
p.toString());
}
mp.Norma());
}

En la clase Complejo tenemos también un ejemplo de un


llamado a un método de clase, o sea static:
return
(float)Math.sqrt(x*x+
Como el método es de clase, no hace falta llamarlo para un
y*y); endeparticular.
nombre
objeto un objeto En
existente se puede
ese caso, utilizar
en lugar del
directamente el nombre de la clase:
Nombre_de_la_Clase<punto>Nombre_
del_Método(parámetros)

Descargado de: http://technologycompartida.blogspot.com

Página 20
Descargado de: http://technologycompartida.blogspot.com

Las estructuras
de control
Las estructuras de control en Java son básicamente las misma que
(al fincon
en C, un excepción del goto, que no existe
lenguaje serio! )
if…[e
lse]
La más común de todas, permite ejecutar una instrucción (o
dada (o, mediante
secuencia la cláusulasielse,
de instrucciones) se daejecutar
una condición
otra secuencia en caso contrario).
if (expresión_booleana)
instrucción_si_true;
[else
instrucción_si_fa
lse;]
Descargado de: http://technologycompartida.blogspot.com

Página 21
Descargado de: http://technologycompartida.blogspot.com

o
bien:
if
(expresión_bool
instrucciones_
}eana) { si_true;
else
{ instrucciones_s
} i_false;
Por
ejemplo:
public final String
toString() { if
(y<0) return x+"-
else i"+(-y);
return
} +x+"+i"+y;

Switch…case…bra
ke…default
Permite ejecutar una serie de operaciones para el caso de que
ejecución
una variable saltea todos
tenga los case
un valor hasta
entero que La
dado. encuentra uno con el
final
valordel case
de la o hastayque
variable, encuentre
ejecuta desde unallíbreak, en cuyo caso salta
hasta el
al
unafinal deldecase.
serie El defaultque
instrucciones permite poner en caso de que la
se ejecutan
igualdad no se de para ninguno de los case.
switch
case (valor1):
(expresión_entera
){ instrucciones_1; [break;
case (valor2): ]
instrucciones_2; [break;
….. ]
case (valorN):
instrucciones_N; [break;
default: ]
} instrucciones_por_def
ecto;
Por
ejemplo:
switch
(mes) { case (2): if
(bisiesto()) dias=29;
else
dias=31;
break
case ;
(4):
case
case
(6):
case (11):
(9):
dias = 30; break
default: ;
} di
as = 31;
Whi
le
Permite ejecutar un grupo de instrucciones
mientras se cumpla una condición dada:
while
instruccion
(expresión_boolea
na) { es…
Descargado de: http://technologycompartida.blogspot.com

Página 22
Descargado de: http://technologycompartida.blogspot.com

}
Por
ejemplo:
while ( linea
linea = {
!= null)
System.out.prin
archivo.LeerLine
tln(linea);
}a();

Do…w
hile
Similar al anterior, sólo que la condición se evalúa
al final del ciclo y no al principio:
do
{ instruccion
} while es…
(expresión_boolea
Por na);
ejemplo:
do
{linea =
archivo.LeerLine
if (linea != null)
}a();
while (linea
System.out.println(linea);
!= null);
Fo
r
También para ejecutar en forma repetida una serie de
instrucciones; es un poco más complejo:
for ( instrucciones_iniciales;
instruccion
condición_booleana; instruccion_repetitiva_x )
}{ es…
Si bien las instrucciones pueden ser cualquiera (el bucle se
usual
repite es utilizarlo
mientras para "contar"
la condición sea la cantidad de
verdadera), lo veces que se
repiten las instrucciones; se podría indicar así:
for ( contador = valor_inicial; contador <
valor_final; instruccion
contador++ ) {
} es…
Por
ejemplo:
for ( i=0;
i<10; i++ ) {System.out.pri
} ntln( i );
o, para contar
hacia atrás:
for ( i=10;
I>0; I-- ) { System.out.pri
} ntln( i );

Break y
continue
Estas instrucciones permiten saltar al final de una ejecución
repetitiva (break) o al principio de la misma
(contin
Por
ue).
ejemplo,
import
en:
java.io.*;
class
Bucles {

Descargado de: http://technologycompartida.blogspot.com

Página 23
Descargado de: http://technologycompartida.blogspot.com

public static void main


(String argv[int]) {
for (i=1; i<5;i=0;
i++) { System.out.println(
if (i==2)
"antes "+i);
if (i==3)
continue;
break;
System.out.println("
} después "+i);

La
salida
antes
es:
1después
1antes
2antes
3Por qué? "i" comienza en 1 (imprime "antes" y "después");
bucle
cuando(no imprime
pasa a 2, elel "después").
continue salta Finalmente, cuando "i" vale
al principio del
3, el break da por terminado el bucle for.
Otras
...
Hay otras instrucciones que
• synchronized
controlan (para ver
el flujo del programa:

junto con los threads)
• cat
• thr
ch,
•ow, finally
tr (para ver con
Ahora y, sí,excepciones)
las podemos usar todo nuestro conocimiento sobre Java
para
ir ir creando
viendo las algunas aplicaciones y de paso
bibliotecas estándar...

Hagamos
algo...
Bueno, vamos a hacer una pequeña
Para empezar,
aplicación paravamos a desarrollar
practicar un poco. un poquito una clase
para trabajar con números complejos.
Descargado de: http://technologycompartida.blogspot.com

Página 24
Descargado de: http://technologycompartida.blogspot.com
http://www.zonazof
t.com

La clase
Complejo
// grabar como
// compilar con "javac
Complejo.java
Complejo.java"
public final class Complejo
extends Number {
//
atributo private
s: private
float x;
float y;
//
constructor
public
es:
Complejo() x{ =
0;
y=
} 0;
public Complejo(float
rx, float iy) {x =
rx;
y=
} iy;

//
//
método
Norm
s:
public final float
a
Norma() { return
} (float)Math.sqrt(x*x+
public final y*y);
float
Norma(Complejo return c) {
} (float)Math.sqrt(c.x*c.x+
// c.y*c.y);
Conjuga
public final Complejo
do
Conjugado() Complejo
{ r = new
Complejo(x,-y);
return
} r;
public final Complejo
Conjugado(Complejo
Complejo c) r ={new
Complejo(c.x,-c.y);
return
} r;
// obligatorios (son
public finalendouble
abstractos Number):
doubleValue() return
{
} (double)Norma
public final ();
float
floatValue()return
{
} Norma();
public final int
intValue() {return
} (int)Norma();
public final long
longValue()return
{
} (long)Norma()
public final ;String
toString() { if
(y<0) return x+"-
i"+(-y);
Descargado de: http://technologycompartida.blogspot.com

Página 25
Descargado de: http://technologycompartida.blogspot.com

else
return
} x+"+i"+y;
// Operaciones
public static final Complejo
matemáticas
Suma(Complejo returnc1,
newComplejo c2) {
} Complejo(c1.x+c2.x,c1.y+c
public static2.y);
final Complejo
Resta(Complejoreturnc1,new Complejo(c1.x-
Complejo c2) {
} c2.x,c1.y-c2.y);
public static final Complejo
return new
Producto(Complejo c1,Complejo(c1.x*c2.x-
Complejo c2) {
} c1.y*c2.y,c1.x*c2.y+c1.y*c2.x);
// Nos va a venir bien para
// como división
aprender excepciones...
por cero!
public static final Complejo
return newc, float f) {
DivEscalar(Complejo
} Complejo(c.x/
public staticf,c.y/f);
final Complejo
Cociente(Complejo
float x =c1, Complejo c2) {
float y=-
c1.x*c2.x+c1.y*c2.
c1.x*c2.y+c1.y*c2.
y; n =
float
x;
Complejo r = new
c2.x*c2.x+c2.y*c2.
return
Complejo(x,y);
y;
} DivEscalar(r,n
} );

Podemos hacer algunos


Primero: no hay include aquí, ya que la única biblioteca
comentarios...
automática
que usamos es java.lang y se incluye
mente.
Segundo: la clase es public final, lo que implica que cualquier
clase en éste uclase
pero ninguna otrospuede
paquetes puede(o
heredarla utilizarla,
sea
Hagamos
que es unaun resumen
clase de los
estéril...).
atributos y métodos de la clase:
//
atributo private
s: float x;
private
Siendo privados, no podemos float y;acceder a ellos desde el exterior.
de acceder
Como ademása x elay.clase
Además, al no
es final, no ser
haystatic,
formacada
instancia de la clase tendrá su propio x e y.
//
public
constructor
Complejo()
es:
public Complejo(float
La clase tienerx,dos
float iy)
constructores, que se diferencian por su "firma"
parámetros.
(signature), oElsea
primero
por la nos sirve para
cantidad y tipocrear
de un objeto de tipo
realidad
Complejoelymétodo lo inicializa
valor indefinido en cero);
(aunque en con el
segundo, podemos definir el valor al crearlo.
//
métodofinal float
public
s:
Norma()
public final float
public final Complejo
Norma(Complejo c)
public final Complejo
Conjugado()
Estos métodos también son duales;c)cuando los usamos sin
Conjugado(Complejo
parámetros devuelven la norma o el conjugado del
objeto individual
(instancia):

Descargado de: http://technologycompartida.blogspot.com

Página 26
Descargado de: http://technologycompartida.blogspot.com

v=
miComplejo.Norma(); otroComplejo =
Con parámetros, en cambio, miComplejo.Conjugado();
devuelven la norma
o// el
porconjugado
ejemplo del parámetro:
v=
unComplejo.Norma(mi
otroComplejo =
Notar que lo Complejo);
unComplejo.Conjugado(miCompl
otroComplejo =
siguiente es inválido: ejo);
Complejo.Norma(miComplejo);
...porque el método no es static, por // NO SE debe llamarse para
lo tanto
PUEDE!
una instancia en particular (en este caso,
unCompl
ejo).
// obligatorios (son
public finalendouble
abstractos Number):
doubleValue()
public final float
public final int
floatValue()
public final long
intValue()
Estos métodos longValue()
es obligatorio definirlos, ya que en la clase madre
Number son métodos abstractos, o sea que
debemos
Como todos los métodos de esta clase son final, o sea que no
implementarlos
puede
aquí. serpuesto
realidad redefinido.
que laNo es no
clase importante en
puede tener descendientes...
public final String
Este métodotoString()
nos sirve para representar el complejo como una
cadena de caracteres, de la forma x+iy.
// Operaciones
public static final Complejo
matemáticas
Suma(Complejo
public static finalc1, Complejo c2)
Complejo
public static finalc1,
Resta(Complejo Complejo
Complejo c2)
Producto(Complejo c1, Complejo c2)
public static final Complejo
DivEscalar(Complejo c, float f)
public static final Complejo
Aquí definimos varias operaciones
Cociente(Complejo c1, matemáticas.
Complejo c2)Notar que se
métodos son como
han definido únicosstatic,
independientemente
o sea que los de las instancias. Esto
permite que
instancia los podamos ejecutar sobre una
o directamente
sobre la clase:
miComplejo =
unComplejo.Suma(comp1,comp2);
miComplejo =
Por ejemplo, la siguiente aplicación nos muestra cómo
Complejo.Suma(comp1,comp2);
// vale usar algunos de estos métodos:
podemos
// Archivo:
TAMBIEN VALE!
Ejemplo5.java
// Compilar con: javac
Ejemplo5.java
// Ejecutar con:
import
java Ejemplo5
java.io.*;
public class
Ejemplo5 {
public static void
main(String
Complejo args[]) {
c1 = new
Complejo(4,-3);
System.out.println(c1+"\tNorm
Complejo c2 = new
a="+c1.Norma());
Complejo(-2,5);
System.out.println(c2+"\tNorma="
+c2.Norma()+"\n");
System.out.println("("+c1+")/4
:"+Complejo.DivEscalar(c1,4));
System.out.println("Suma :
"+Complejo.Suma(c1,c2));

Descargado de: http://technologycompartida.blogspot.com

Página 27
Descargado de: http://technologycompartida.blogspot.com

System.out.println("Resta :
"+Complejo.Resta(c1,c2).toString());
System.out.println("Multip:
System.out.println("Divis :
"+Complejo.Producto(c1,c2).toString());
"+Complejo.Cociente(c1,c2).toString());
}
}
Hay varias cosas para notar: por ejemplo, que podemos
declarar las variables a la vez que las creamos:
Complejo c1 = new
c1 y c2 son dos objetos (instancias)
Complejo(4,-3);
de la clase
Notar Complejo.
también que no hace falta
poner para imprimir:
System.out.println(c1.t
ya que println automáticamente usa el método toString() de la
oString().......);
clase para imprimir.
en el programa, Basta con poner c1, como
aunque
c1.toString() también
También se ve el uso de es válido.
los métodos static,
accediéndolos directamente por la clase, en:
System.out.println("Suma :
Y tampoco aquí usamos toString(), aunque no está mal si se
"+Complejo.Suma(c1,c2));
usa Complejo.Suma(c1,c2).toString().
Algo sobre los
métodos
Analicemos un poco ahora cómo implementamos
los métodos de la clase Complejo.
public final int
intValue() {return
} (int)Norma();
Ya que no podemos convertir así nomás un complejo en un
elegido usar implementar
entero, para como valor de retorno
estos la norma
métodos hemos del complejo. En
este caso,un
devuelve y dado
float,que el método
usamos Norma()
typecasting, es decir, lo
convertimos en entero precediéndolo con (int).
public final String
toString() { if
(y<0) return x+"-
else i"+(-y);
return
} x+"+i"+y;
Aquí representamos el complejo en forma de cadena de
adecuadamente
caracteres. Hemos el signo
usadode el la
if parte imaginaria. Noten también
para representar
la asombrosa
convertir ayuda que noslas
automáticamente brinda Java,xale y a String para la
variables
concatenación (mediante el signo "+")!
public static final Complejo
float x =c1, Complejo c2) {
Cociente(Complejo
c1.x*c2.x+c1.y*c2.
float y=-
y; n =
float
c1.x*c2.y+c1.y*c2.
Complejo r = new
c2.x*c2.x+c2.y*c2.
x;
Complejo(x,y);
y;
return
} DivEscalar(r,n
Aquí tengan en cuenta que ); las variables x e y, definidas como
float, no tienen
(atributos) de lanada
claseque
quever
estáncondefinidas
las variables
al principio de la
Podemos
misma, sino usarque
return DivEscalar(r,n),
son variables locales ya que DivEscalar es un
al método.
método propio de la clase; no hace falta
poner
Complejo.DivEsca
Qué pasa con r, el new Complejo(x,y) que creamos? Nada; cuando
lar.objetodeno
un
basura" se usa
Java más, elautomáticamente
lo elimina "recogedor de
(tarde o temprano) de la memoria.
public final float
Norma(Complejo c) {
Descargado de: http://technologycompartida.blogspot.com

Página 28
Descargado de: http://technologycompartida.blogspot.com

return
} (float)Math.sqrt(c.x*c.x+
Aquí estamos usando otra c.y*c.y);
clase, Math, que nos permite realizar
varias operaciones
dispone matemáticas.
de las constantes E y Esta clase
PI, y los métodos:
abs(x)
acos(x)
valor
asin(x)absoluto
arco coseno
atan(x)
arco seno
atan2(x,y) componente angular de
arco
ceil(x)
la tangente
representación polar de x,y
cos(x) m
exp(x)
enor entero mayor que x
coseno
floor(x) mayor
eIEEEremainder(x,y)
entero
x menor que x resto de la división
x/y
log(x) según el estándar IEEE 754
max(x,y) el
min(x,y)
mayor
logaritmo de xnatural
ey el
pow(x,y)
menor de x e y
random() número
xy
rint(x)
aleatorio entre 0 y 1 entero más
cercano a x (devuelve unentero
round(x) doble)más cercano a x
sin(x)
(devuelve un entero o un long)
sqrt(x)
seno
tan(x)
raíz cuadrada
Algunos de estos métodos disparan excepciones, como sqrt o
tangente
veremos
log cómo se
de números usan
negativos. Más adelante
las excepciones.
Otra clase que hemos estado usando mucho es la PrintStream,
a la que pertenece el método println. En
System.out.pri
out es un atributo de la clase ntln(...)
System, del
tipo (clase) PrintStream:
public final class System
{extends Object
//
public static
Fields
PrintStream err;
public static
InputStream in;
public static
PrintStream out;
//
Methods
.........
}
....
Veremos otras bibliotecas (para
entrada/salida, gráficos, etc) muy pronto.

Descargado de: http://technologycompartida.blogspot.com

Página 29
Descargado de: http://technologycompartida.blogspot.com

Java a través de
la ventana
Para hacer algo un poco más divertido, vamos a empezar a
trabajar
contiene con
todolaun
biblioteca
grupo dejava.awt, que es
objetos para la quecon
trabajar
ventanas y sus contenidos: botones, listas, etc.
Nuestra primera
ventana
En Java, la clase Window (descendiente de Container), en la
biblioteca"peladas",
ventanas java.awt, espermite
decir,implementar
sin bordes ni menús. Son la base para
up, diálogos,
cualquier tipoetc.). El otro descendiente
de ventanas (normales, pop- de Container, Panel, es
más
que unasencillo aún y sirve
aplicación comodentro
incorpore espacio para
suyo otros
La interface(incluyendo
elementos Java dirigeotros
tantopaneles).
a uno como a otro todos los
(en seguida
eventos veremosmouse
de teclado, cómo y foco que los afecten
usarlaestos
De claseeventos).
Window descienden Dialog (para implementar
diálogos) yyaFrame,
completa: que esyuna
tiene borde menú,ventana algo los
así como más
El siguiente
botones ejemplo
de cerrar, crea una ventana
maximizar, etc. que no hace nada pero
contiene varios
directamente elementos;
(desde se puede
la ventana DOS usaro Unix con java Ejemplo7) o
Si
comobienapplet
los elementos
dentro deno disparan
una página ninguna
HTML. acción, se pueden
editar
utilizarelcontexto dentro
toda de los cuadros
su funcionalidad de ejemplo,
(por
texto o presionar el botón).
// grabar como
// compilar con "javac
"Ejemplo7.java"
import
Ejemplo7.java"
java.awt.*;
public class Ejemplo7
extends
boolean Frame {
inAnApplet = true;
public static void
Ejemplo7
main(String window
args[]) { =
new Ejemplo7();
window.inAnApplet
window.setTitle("Eje
= false;
mplo");
window.pac
k();
window.sho
}w();
public
Ejemplo7() Panel{ panelAlto =
new Panel();
panelAlto.add("West", new
Label("Cartel", Label.CENTER));
panelAlto.add("East", new
add("North",
TextArea("Area de texto", 5, 20));
panelAlto);
Panel panelBajo =
panelBajo.add(new
new Panel();
TextField("Campo de Texto"));
panelBajo.add(new
Button("Botón"));
add("South",pa
nelBajo);
}
public boolean
if (ev.id == ev) {
handleEvent(Event
Event.WINDOW_DESTROY)
if
{
(inAnApplet) {

Descargado de: http://technologycompartida.blogspot.com

Página 30
Descargado de: http://technologycompartida.blogspot.com

dispose();
}
else {
System.exit(0);
}
} return
super.handleEvent(ev
);
}

Un poco de
detalle
La clase desciende de Frame (o sea que será una ventana con
Vamos a usar el
borde, aunque noflag inAnApplet
le vamos a ponerpara saber si se arrancó como
menú).
applet
cerrarlao en
como aplicación standalone (hay que
manera
diferente en cada caso)
public class Ejemplo7
boolean
extends Frame {
Si se llama como
inAnApplet = true;aplicación standalone, lo primero que se ejecuta
es main(...);
una instanciaendeeste caso la (ejecutando
Ejemplo7 aplicación crea
el constructor
Ejemplo7()
applet, a través
y llama a tresdemétodos
new), define
de que no es un
• setTitle
la "abuela" window:que define cuál va a ser el
• pack
título que que
aparece en la ventana
dimensiona los elementos que
•componen
show quela ventana a su tamaño preferido
muestra la ventana
public static void
main(String
Ejemplo7args[]) { =
window
new Ejemplo7();
window.inAnApplet
window.setTitle("Eje
= false;
mplo");
window.pac
k();
window.sho
}
w();
Ojo! No confundir el objeto (instancia)
Si se carga
window concomo applet,
la clase entonces se ejecuta el constructor
Window!
Ejemplo7() como en el caso anterior:
public
Ejemplo7() Panel panelAlto =
{ new Panel();
panelAlto.add("West", new
panelAlto.add("East", new
Label("Cartel", Label.CENTER));
add("North",
TextArea("Area de texto", 5, 20));
panelAlto);
Panel panelBajo =
panelBajo.add(new
new Panel();
TextField("Campo de Texto"));
panelBajo.add(new
add("South",pa
Button("Botón"));
nelBajo);
}
Este constructor define dos paneles que forman el contenido de la
con un par
ventana de componentes
(panelAlto y los pone
y panelBajo), dentro de la ventana
los llena
(recordar
Para verloquemásEjemplo7
claro, se es una
crea el ventana!).
panel (o
espacio para contener objetos) con:
Panel panelAlto =
new Panel();
Se agregan componentes al
panel con el método add:
Descargado de: http://technologycompartida.blogspot.com

Página 31
Descargado de: http://technologycompartida.blogspot.com

panelAlto.add("West", new
panelAlto.add("East", new
Label("Cartel", Label.CENTER));
TextArea("Area de texto", 5, 20));

Se agregan el panel dentro de


nuestro objeto con:
add("North",
que panelAlto);
equivale
a: this.add("North",
panelAlto);
lo que se puede ver (aunque es inválido
porque la clase no es static) como:
Ejemplo7.add("North
Como nuestra ", panelAlto);
clase Ejemplo7 desciende de Frame, ésta de
está heredando
Window, y éstade... su bisabuela!
de Container, Por otraadd
el método parte,
lo Panel es hija de
agregar
Container,susycomponentes.
usa el mismo Interesante,
método para
no? Veamos la estructura:
Object --- Component ---
Container --+-- Panel
| +-- Window
--- Frame --- Ejemplo7
Noten que hemos usado dos métodos
add con diferente signature:
panelAlto.add("West", new
........
Label("Cartel", Label.CENTER));
panelBajo.add(new
..
Button("Botón"));
El método add(Component) agrega un componente al final; el
método add(String,Component)
en un lugar especificado por unalopalabra agregaque depende del
LayoutManager,
ordenar los componentesel objeto que se encarga de
LayoutManager es una interface, y como tal debe implementarse
dentro del contenedor.
hay varios
a través de predefinidos en la librería
objetos no abstractos java.awt:
de los que BorderLayout,
yCardLayout, FlowLayout, GridBagLayout
El Layout por defecto es BorderLayout, que define en el
GridLayo
contenedor
ut.
"East" las áreas
y "Center" "North",
y es "South",
que usamos aquí."West",
CardLayout permite
"apilar"
uno los componentes
por vez, FlowLayout como cartasdey izquierda
los ordena ver a derecha
cuadrícula donde
como un texto, cada componente
GridLayout los ordenatiene
en un
unatamaño fijo y
GridBagLayout
cada uno puede tenerlos pone
el en una cuadrícula pero
Noten
tamañoque no hace falta llamar, en el caso
deseado.
del applet, a Pack() y Show().
Y los
eventos...
Ahora vamos a ver un método que viene de la clase tatarabuela!
objeto
Hace falta decir que me gusta esto de los
Vamos a redefinir handleEvent(Event), que es el método que
s?
analiza
toma laslos eventos dirigidos al componente y
acciones
adecuadas.
La clase Event define básicamente una serie de métodos que
presionada
permiten saber y muchas
si hay constantes
alguna teclaque
deindican
control si se presionó o
movió el mouse,
particular, si se presionó
si se cambió el tamañoalguna
de latecla en etc. En
ventana,
• idhay
particular quealgunos
indica elatributos interesantes:
•tipo target
de evento
que indica sobre qué
•componente
key qué se produjo
tecla el evento
se presionó si
etc fue un evento de teclado
.

Descargado de: http://technologycompartida.blogspot.com

Página 32
Descargado de: http://technologycompartida.blogspot.com

En los descendientes de Component, el método handleEvent se


llama automáticamente
produce un evento sobrecada vez que se En este caso,
el componente.
objeto de clase
simplemente Ejemplo7)
vamos a mirarfue si "cerrar
el eventola (sobre
ventana", que
nuestro
WINDOW_DESTROY
se identifica mediante event.id (una constante
= estática de la clase Event,
de la clase
y como tal como
la podemos usar con el nombre
Event.WINDOW_DESTROY)
:public boolean
handleEvent(Event
if (ev.id == ev) {
if
Event.WINDOW_DESTROY)
(inAnApplet)
{ {
dispose();}
else {
System.exit(0);
}
} return
super.handleEvent(eve
nt);
}
En ese caso, si nuestro ejemplo se disparó como aplicación
llamamos alymétodo
aplicación; si era unSystem.exit(0),
applet llamamos quea cierra la
dispose(),
implementación de
ComponentPeer queunsemétodo
encargade delaremover
interfacetodos los
Noten que cualquier
componentes otro ventana.
y la propia tipo de evento deja seguir hasta return
método handleEvent de la clase
super.handleEvent(event), madre:
que llama al así como el prefijo this. se
prefijo
refiere asuper. llama al
un método demétodo
la propiadeclase,
la clase
el madre (aunque esté
redefinido).
remonta EnComponent.handleEvent,
hasta este caso, la llamada se que determina el tipo
de evento
action, y llama lostFocus,
gotFocus, a uno de los métodos keyUp, mouseEnter,
keyDown,
mouseExit, mouseMove,
mouseDown o mouseUp según mouseDrag,
sea apropiado (y devuelve true).
Si ningún método es aplicable, devuelve
fals
Es muy común, al redefinir un método, tener en cuenta
e.
llamar antespara
antecesora o después al método
inicializar o de la clase
terminar alguna tarea.

Descargado de: http://technologycompartida.blogspot.com

Página 33
Descargado de: http://technologycompartida.blogspot.com

Una ventana
con
(aunque vida
Antes que nada, vamos a crear una página HTML para cargar
también
nuestra clase la podremos
Ejemplo8, ejecutar
que será en forma standalone
un applet
con "java Ejemplo8"), por ejemplo:
<!-- Archivo Ejemplo8.htm -
<HTM
HTML de ejemplo -->
L>
<HEA
<TITLE>Ejemplo 8 - Ventana
D>
</HEA
de datos</TITLE>
D>
<BOD
Y>
Aqu&iacute; se tiene que abrir una
<applet
ventana code="Ejemplo8.class"
de entrada de datos
width=170 height=150>
</appl
</BOD
et>
</HT
Y>
ML>
Nuestro applet será muy sencillo, ya que utilizará clases que
sólo creará
iremos una ventana
definiendo que
en este capítulo; por empezar
definiremos en la clase Ventana8:
// Archivo:
// Compilar con "javac
Ejemplo8.java
Ejemplo8.java"
import
import
java.awt.*;
java.applet.*;
public class Ejemplo8
extends Applet {
public static void main (String arg[]) { // para
poderVentana8("Ejemplo
new llamarla con "java Ejemplo8"
}Standalone", true);

public void init() {


new Ventana8("Ejemplo /
Applet", false);
}/ se ejecuta al abrirse un applet

Con los parámetros que le pasamos a la clase Ventana8 le


como applet
indicamos el otítulo
no (ya
de que el
la ventana y si se carga
método de cierre varía).
Viajando
con vamos
Ahora Javaa trabajar con nuestra clase Ventana8, una ventana
ciudades (desde seleccionar
que nos permita y hasta) queuna
simula una
fecha ventana de compra de
y dos
pasajes de, por ejemplo, una terminal de
ómnib
us.
El ejemplo está basado en uno del libro "Programación Java" de
amplia
Macary y Nicolas, aunque algo mejorado y
En nuestra ventana podremos entrar una fecha a mano o
do.
directamente
elegiremos la mediante
ciudad delos botones
salida Hoy
y la de y Mañana,
llegada de dos listas, y
los servicios disponibles,
presionaremos nos permitirá
luego un botón que nos mostrará
comprar
A medidalos pasajes,
que etc.los datos, en el botón se irá mostrando
entramos
el detalle de lo que se fue seleccionando.

Descargado de: http://technologycompartida.blogspot.com

Página 34
Descargado de: http://technologycompartida.blogspot.com

Nuestra ventana quedará


más o menos así:

Empecemos por armar la estructura


de la clase Ventana8:
import
java.awt.*;
class Ventana8 extends Frame
{
// aquí
// hija de Frame
algunas
agregaremos variables
para
luego
// guardarde
(ciudades datos
salida y
buttonok;
llegada, fecha) //
booleanenApplet;
también el botón de // ycompra
otra para indicar
de pasajes
si es un applet o no
Ventana8 (String titulo, boolean
super(titulo);
enApplet)
{
this.enApplet =
// llamacrearemos
aquí
enApplet; al de Frame los
// con
botones, suslistas, etc
un constructor
valores
// iniciales
yguardamos
los pondremos
esto
enpor
// la ventana.
ok = new Button("Viaje:
ejemplo:
de ? a ? el ?/?/?");
add("Sout
pack();
h",ok);
show();
}// dimensionamos la ventana
// y la mostramos!
public boolean handleEvent(Event e)
{ (e.id ==
if
if (enApplet)
Event.WINDOW_DESTROY)
else
dispose();
{// para manejar los eventos
System.exit(
}
0);
// aquí
cerrarmiraremos
la ventanasi se
// o se eligió
presionó algo
un botón
deyuna
// lista
actuaremos en
return super.handleEvent(e);
consecuencia // los
}demás eventos los maneja Frame

void
// aquí pondremos un
ActualizaBoto
n() { método que servirá
// para actualizar el botón de
// ya quede
compra elpasajes,
texto del mismo
//
sevez que secada
actualiza selecciona una
} ciudad o se cambia la fecha

void
Activar() // y aquí un método para
{ // dicho se
cuando botón, que se supone
presione
//
queuna
vabase de datos y
a consultar
abrir una ventana
Descargado de: http://technologycompartida.blogspot.com

Página 35
Descargado de: http://technologycompartida.blogspot.com

// para
}vendernos el
}pasaje

Nuestro programa ya funciona! Aunque un


Igual
poquito vamos a analizarlo
incompleto, un poco el constructor,
claro...
que es lollamamos
Primero más interesante aquí. de la clase madre,
al constructor
que se encarga de crear la ventana:
Ventana8 (String titulo, boolean
enApplet)
super(titulo);
{
Esto sería
// llama al como
de Framellamar a super.Frame(titulo), o bien
Frame(titulo),
nombreyadeque
// un constructor
mismo la el método constructor tiene el
clase. Luego, con:
this.enApplet =
enApplet;
asignamos a nuestra variable enApplet de la clase el valor del
llama igual.que
// guardamos
parámetro Elesto
prefijo
se pasó this, que se refiere
al constructor, queasela instancia particular
de la clase,
(esto permite
es válido tantodiferenciar uno de otro
para variables
como para métodos).
ok = new Button("Viaje:
add("Sout
de ? a ? el ?/?/?");
h",ok);
Aquí hemos creado un botón ubicado al pie de la ventana
(por ahora lo único
dimensionamos que pusimos), y luego
la ventana
y la mostramos:
pack(); //
show();
dimensionamos la ventana

// y la mostramos!
Preparando
listas
Ahora vamos a empezar a crear otros objetos para ir
completando
listas de nuestra aplicación. Comencemos con las
Para eso, vamos a crear un objeto descendiente de Panel que
ciudades.
simplemente ycontenga
predefinidas un títulouna
quelista
digade ciudades ciudad de",
"Seleccione
También
y a continuación "salida" o "llegada".
agregaremos un
import
método
java.awt.*;
class SelecPueblo
private
extends Panel {
ListlistaPueblos
;SelecPueblo (String
setLayout (new {
salidaOllegada)
BorderLayout (20,20));
// armamos el título, que
StringBuffer titulo = new
va a ser un Label:
StringBuffer();
titulo.append("Seleccion
e ciudad de ");
titulo.append(salid
titulo.appen
aOllegada);
d(": ");
add("North", new
Label(titulo.toString()));
// armamos la lista de ciudades,
que va a ser un
listaPueblos List:
= new
List (4, false);
Descargado de: http://technologycompartida.blogspot.com

Página 36
Descargado de: http://technologycompartida.blogspot.com

listaPueblos.addItem("B
uenos Aires");
listaPueblos.addItem
listaPueblos.addIte
("La Plata");
m("Azul");
listaPueblos.addIte
listaPueblos.addItem
m("Rosario");
listaPueblos.addItem("
("Cordoba");
Bahía Blanca");
add("South",
listaPueblos);
}

public String
return
getDescription() {
}listaPueblos.getSelecte
}dItem();

No hay mucho para analizar aquí, creo. La variable listaPueblos es


ciudad
privada,seleccionada mediante getDescription
pero puede consultarse cuál es la (que es
getSelectedItem
public). Este método de lallama
lista, al
quemétodo
devuelve
En el texto seleccionado.
el constructor, armamos el texto del título como un
los de clase String
StringBuffer. pero pueden
Los objetos ser modificados.
StringBuffer En cambio
son similares a los
ser
objetosmodificados directamente:
String, una vez creados,sus nométodos
pueden (concat, toLowerCase,
etc.)elsimplemente crean un nuevo String
con
Esto
nuevolovalor.hicimos para introducir esta nueva clase; por supuesto
comprobar,
hubiera sidocon máselfácil poner, como pueden
mismo resultado:
String tit = "Seleccione ciudad de
"+salidaOllegada+":
add("North", new ";
Label(tit));
Por otra parte, creamos el objeto listaPueblos como new List(4,
false), queyindica
renglones sólo seque la lista
puede va a tenerun4 ítem por vez.
seleccionar
Agregamos luego 6 ítems mediante addItem y la
agregamos
Ahora
al panel. ya podemos agregar las listas a nuestra ventana y
poner un par de variables para guardarlas:
class Ventana8 extends Frame
{
SelecPueblocs;
SelecPueblocl;
// hija de Frame
// ciudad de salida
buttonok; //
// ciudadeldebotón
también
booleanenApplet; llegada
de// ycompra de pasajes
otra para indicar
si es un applet o no
Ventana8 (String titulo, boolean
super(titulo);
enApplet)
this.enApplet
{ =
enApplet;
// llama
cs = newal de Frame
add
SelecPueblo("SALIDA");
// un constructor
// guardamos
("Center",
cl = new esto
cs);
// CIUDAD DE SALIDA
SelecPueblo("LLEGADA");
add
ok = new Button("Viaje:
("East",
add("Sout
//
de
cl);CIUDAD
? a ? el ?/?/?");
DE LLEGADA
h",ok);
pack();
show();
}// dimensionamos la ventana
// y la mostramos!
.................
Ya pueden ir probando cómo queda, aunque por ahora
..........
mucha funcionalidad no tenemos...

Descargado de: http://technologycompartida.blogspot.com

Página 37
Descargado de: http://technologycompartida.blogspot.com

Agregando
fechas
Otro panel más nos servirá para
seleccionar o entrar la fecha:
import
java.util.*;
import
java.awt.*;
class DiaPartida
extends Panel {
private
TextFieldelDia;
private Buttonhoy;
private Buttondiasiguiente;

DiaPartid
setLayout
a() { (new
GridLayout
elDia = new (4,1));
TextField();
elDia.setText(G
hoy = new
etHoy());
Button ("Hoy");
diasiguiente = new
add
Button (new Label
("Mañana");
add
("Día salida: "));
(elDia);
add
(hoy);
add
}(diasiguient
e);
private String
Date d = new
GetHoy() {
Date();
int dia =
d.getDate();
int mes =
int ano =
d.getMonth();
d.getYear();
return
}dia+"/"+mes+"/"+
ano;
private String
GetManana()
Date d = new {
int dia =
Date();
d.getDate();
int mes =
int ano =
d.getMonth();
dia =
d.getYear();
dia++;
switch
(mes) {
case
(1): case
(3):
case
case
(5):
case
(7):
(8):
case (10): if
(dia>31) { dia =
1; mes++
} ;
brea
case (12): if k;
(dia>31) { dia =
mes = 1;
1; ano++;
}

Descargado de: http://technologycompartida.blogspot.com

Página 38
Descargado de: http://technologycompartida.blogspot.com

break;
case
(4): case
(6):
case
case (11): if
(9):
(dia>30) { dia =
mes+ 1;
+; }
break;
default: if (dia>28) { // ojo, hay que
corregir para bisiestos! dia =
mes+ 1;
+; }
}
return
dia+"/"+mes+"/"+
}
ano;
public String
getDescription() {
return
}elDia.getText(
);
public boolean
if (e.target (Event e) {
handleEvent
elDia.setText(G
== hoy)
etHoy());
if (e.target ==
diasiguiente)
elDia.setText(Get
return
Manana());
}super.handleEven
t(e);
}

Este es un poco más largo pero no más


complejo. Vamos por parte:
DiaPartid
setLayout
a() { (new
elDia
GridLayout= new (4,1));
TextField();
elDia.setText(G
etHoy());
hoy = new
diasiguiente
Button ("Hoy"); = new
Button
add (new ("Mañana");
Label
add
("Día salida: "));
add
(elDia);
(hoy);
add
}(diasiguient
e);
El constructor crea un panel con cuatro campos en forma de
salida: ", el campo
grilla vertical, dondedemostrará
entrada deel texto elDia
"Día y
El
losmétodo
botonesprivado getHoy usa los métodos getDate, getMonth y
hoy y diasiguiente.
getYearcon
String delala fecha
clase actual.
date paraEl armar
método unprivado getManana hace lo
1mismo
al día para
para leer
tenerlaelfecha actual, y leElsuma
día siguiente. switch siguiente verifica que
el mes siguiente
si pasó de fin de (o mes el tome
primer
el día del año
primer día ysiguiente si es en
diciembre).
bisiestos en Notar
febreroque paranono
se complicar
consideraronel los años
método, pero no es difícil de corregir.

Descargado de: http://technologycompartida.blogspot.com

Página 39
Descargado de: http://technologycompartida.blogspot.com

Otra manera sería armar un array con los días de cada mes,
corregir los
bisiestos, días de febrero
y comparar contrapara
estelos años
array en lugar de usar un switch.
La ideacon
String siempre
la fechaes la
delmisma: devolver un
Notar algo interesante: como estas clases se cargan y ejecutan en
día siguiente.
la del clientecliente,
máquina y no laladel servidor
fecha (que puede
que aparece es ser diferente
depende la hora y el lugar del mundo en que estén
ambas
El método getDescription es público y se usa para acceder a la
máquinas).
fecha
clases;que se ha ingresado
simplemente desde
devuelve el las demás del
contenido
campo elDia, de clase TextField.
Aquí hemos desarrollado también el
método handleEvent:
public boolean
if (e.target (Event e) {
handleEvent
== hoy)
elDia.setText(G
etHoy());
if (e.target ==
elDia.setText(Get
diasiguiente)
Manana());
return
}super.handleEven
t(e);
En caso de alguna acción sobre uno de los botones, el método
setTextde
campo (detexto
la clase
elDiaTextField) pone en el
el valor del
día actual
Notar que osólo
el siguiente.
hemos considerado que haya algún evento y no un
método va a actuar
tipo de evento por ejemplo
en particular; tanto al presionar
en realidad el el mouse sobre
moles
el botón como al soltarlo. Pero esto no nos
super.handleEvent se encarga de otros eventos dirigidos al panel,
ta.
como ladeentrada
campo texto de datos por teclado al
por ejemplo.
Juntando todo
hasta aquívamos a reunir las piezas que tenemos hasta ahora
Bueno, ahora
Ventana8
agregandopara estosver cómo queda
métodos a nuestra clase
la ventana completa:
class Ventana8 extends Frame
{
SelecPueblocs;
// hija de Frame
SelecPueblocl;
DiaPartidadp;
// ciudad de salida
// ciudad de llegada
buttonok;
// día de salida
booleanenApplet; // para indicar si
es un applet
// botón o no de pasajes
de compra
Ventana8 (String titulo, boolean
super(titulo);
enApplet)
this.enApplet
{ =
enApplet;
// llama
dp = newal de Frame
add
DiaPartida();
// un constructor
// guardamos
("West",
cs esto
= new SelecPueblo("SALIDA"); //
dp);
// DIA DEDE
CIUDAD
add SALIDA
SALIDA
cl = new
("Center",
add
SelecPueblo("LLEGADA");
cs);
("East",
ok = new Button("Viaje:
cl);
add("Sout
// CIUDAD
de ? a ? el ?/?/?");
DE LLEGADA
h",ok);
pack();
show();
}// dimensionamos la ventana
// y la mostramos!

Descargado de: http://technologycompartida.blogspot.com

Página 40
Descargado de: http://technologycompartida.blogspot.com

Completando la
ventana
Vamos a empezar por completar nuestro método
medida que seleccionemos
ActualizaBoton, las el texto del botón ok a
que modificará
ciudades y la fecha:
void
ActualizaBoto
StringBuffer b = new
n()if{(cs.getDescription()
StringBuffer("Viaje: != null)
de ");
b.append(cs.getDescription());
else
b.append("?")
if (cl.getDescription() != null)
;b.append("
b.append(cl.getDescription());
a "); else
b.append("?")
;b.append("
if (dp.getDescription() != null)
b.append(dp.getDescription());
el ");
else
b.append("?/?/?
}
ok.setLabel(b.toS
");
tring());
Nuestro método comienza por crear un StringBuffer con las
palabras• "Viaje:
la ciudaddede ", partida, llamandoel al
y va agregando método
resto:
• el texto de cs (ciudad de salida)
getDescription
•constante " a "de llegada, llamando al método
la ciudad
•getDescription
el texto de cl (ciudad de llegada)
•constante " elseleccionada,
la fecha " llamando al método
Si engetDescription
cualquier casode dp (día
recibe un de partida)
string nulo, pone un
signo
El método de pregunta
setLabel,(o sobre
?/?/? para la fecha).
el objeto ok de tipo Label,
modifica la nos
Realmente "etiqueta"
devuelven del botón.
null los métodos que
Veam
llamamos si no hay selección hecha?
os:
class SelecPueblo
extends Panel {
private
ListlistaPueblos
..................
;
public
.......... String
getDescription() {
return
}listaPueblos.getSelecte
}dItem();

El método getSelectedItem de la clase List devuelve null si


no hay ítems
andamos bien.seleccionados,
En cuanto a laasí queDiaPartida,
clase acá de entrada
que aquí no
inicializa se daría
el valor delnunca
texto este
en lacaso... Aunqueasí
fecha actual, al crear el objeto
el botón, yestamos
Ventana8 no el queponiendo un texto fijo en
devuelve
Sería mejor,el objeto dp.más consistente, modificar el constructor de
para ser
el método para que arme el texto mediante
Ventana8
ActualizaBotón:
Ventana8 (String titulo,
.........................
boolean enApplet) {
............... ok = new
Button("cualquiera");
ActualizaBo
add("South"
ton();
,ok);
pack(
);
show(
} );

Descargado de: http://technologycompartida.blogspot.com

Página 41
Descargado de: http://technologycompartida.blogspot.com

Esto ya se ve mejor! Y de paso


probamos el método...
Un poquito de
actividad
Ahora sí, pasemos a completar
nuestro manejador de eventos:
public boolean
handleEvent(Event e) {
if (e.id ==
Event.WINDOW_DESTR
if (enApplet)
OY) { else
dispose();
} System.exit(
if ( 0);
ActualizaBo
(e.target==dp)||(e.target==cs)||(
ton();
e.target==cl) )
if
Activa
(e.target==
r();
}ok)
return
}super.handleEven
t(e);
Simplemente, si detectamos un evento sobre alguno de nuestros
paneles
se actualizamos
presiona dicho botónel texto del botón;
llamamos y si Activar que se
al método
datos,
suponeindicarnos servicios
que va a tomar los datos de la base de
disponibles,
Algo importanteetc. a notar es que el simple hecho de mover el
ActualizaBoton
mouse sobre uno(se denota porque ya
los paneles titila el texto,
llama a sobre todo en una
el botón Hoy
máquina o Mañana
lenta). Además,sin si mover el mouse,
hacen click sobreel texto del botón ok
nobotón
al se actualiza ya que el evento va dirigido
presionado
y no forma
Una al panel.
de filtrar sólo los eventos que nos
interesan sería usar, por ejemplo:
if ((e.target=cs.listaPueblos) &&
(e.id==Event.LIST_SELECT)) ActualizaBoton();

que está dirigida a la lista y no al panel en general, y


tiene en cuenta el tipo
Lamentablemente, de evento.es privada dentro de la clase
listaPueblos
es mejor así, yporque
SelecPueblo por lo declararla
tanto dentropública
de cs.yPero
leerla desde afuera
sería bastante sucio (así como la leemos
podríamos
Hay varias formas de mejorar esto sin cometer la torpeza de
escribirla).
es verificar,
declarar usando
pública cs.getDescription(),
a listaPueblos. si el texto cambió (y sólo
Una posibilidad
en
Otra,eseescaso modificar
hacer que los el texto de
objetos dellabotón).
clase SelecPueblo pasen a
sus
mejor padres cualquier
solamente evento sobre
la selección de unellos, o
elemento de la lista; para
eso basta agregar a la clase SelecPueblo:
public boolean
if ((e.target==listaPueblos)
handleEvent(Event e) { &&
e.target=
(e.id==Event.LIST_SELECT)) {
this;
}
return
}super.handleEven
t(e);
En resumen: si el evento en el panel es una selección de la lista
con
(tantolascon
flechas),
mousecambio el target del
como moviendo evento para que indique el
la selección
panel (y no la lista); si no, lo paso a la clase
anteces
ora.
Lo mismo podemos hacer con handleEvent
para la clase DiaPartida:
public boolean
handleEvent
if (e.target (Event e) {
elDia.setText(G
== hoy) {
etHoy());
Descargado de: http://technologycompartida.blogspot.com

Página 42
Descargado de: http://technologycompartida.blogspot.com

e.target=
this;
}
if (e.target ==
diasiguiente) {
elDia.setText(Get
e.target=
Manana());
}
this;
if (e.target ==
elDia)
e.target= {
}
this;
return
}super.handleEven
t(e);
Esto no anda como esperaríamos! El campo de
texto es
Esto noporque
se comporta muydependiente
el código bien... de la plataforma
procesa los eventos
handleEvent, de mouse
pero procesa los antes de llamar a
de teclado
Lo que significa
después de llamarque, en el caso del campo de texto, handleEvent
a handleEvent.
antes
(y porde lo tanto ActualizaBotón) se llama
modificar
Para el esto, deberíamos procesar nosotros las teclas
corregir
texto! que(lo
verificar
presionadas se que
presiona
podríamos aprovechar para
una tecla válida).
Cuidado! En futuras versiones de Java podría implementarse el
mismo
lo tantocomportamiento
tendríamos que para el mouse, y por
Para colmo,
repensar sólo los eventos que la plataforma envía llegan a
la estrategia.
movimiento de mouse
Java; por ejemplo, Motifdentro de uneventos
no envía campo dede texto... lo que
significa
de eventos. queSólo
nunca podríamos capturar ese tipo
el componente
Para
Canvas simplificar,
pasa todos sólo
losactualizaremos
eventos. el texto del botón
cuando se presiona Enter (Event.key=10):
if ((e.target ==
elDia)&&(e.id==Event.KEY_PRE
if (e.key==10)
}SS)) { e.target=this;

Ahora debemos modificar el método handleEvent en nuestra


clase
event Ventana8 para que soporte todos estos
os:
public boolean
handleEvent(Event e) {
if (e.id ==
if (enApplet)
Event.WINDOW_DESTR
OY) { dispose();
else
} System.exit(
if ( 0);
||((e.target==cs)&&(e.id==Eve
((e.target==dp)&&((e.id==Event.ACTION_EVENT)|
nt.LIST_SELECT))
||((e.target==cl)&&(e.id==Even
|(e.id==Event.KEY_PRESS)))
t.LIST_SELECT)) ) ActualizaBo
if ton();
Activa (e.target==
r(); ok)
return
} super.handleEven
t(e);
Obviamente, procesar todas las teclas nosotros sería bastante más
complicado...
DiaPartida de más
sería todos modos, el método en
o menos así:
if ((e.target ==
// 1- leer el contenido del campo
elDia)&&(e.id==Event.KEY_PRE
SS)) { con:
// elDia.getText()
2- modificarlo de acuerdo a la
// 3- poner
tecla el resultado
presionada: e.key en el campo
con: elDia.setText(texto)

Descargado de: http://technologycompartida.blogspot.com

Página 43
Descargado de: http://technologycompartida.blogspot.com

// 4- modificar el objeto del evento al


panel
// con: e.target=this;
5- enviar el evento al objeto
//
padreen(no
estela caso
claseVentana8,
padre), mediante:
getParent().deliverEvent(e)
// 6- evitar proceso posterior del
} evento mediante: result(true)

Me ahorro explicar estos dos últimos pasos; se complica bastante


todo
cursorporque
dentrohay
delque manejar
campo la posición
de texto, etcétera.delCon lo
que hicimos es bastante... creo!
Y para
terminar...
Bueno, sólo nos queda por definir el método Activar(). Primero
vamos
alguienalollamar últimoa ActualizaBoton()
que hizo fue entrarporunsitexto sin presionar Enter, y
un
dejoarchivo
para otro o base
día de másdatos con loconsultar
tranquilo que vamos a
mostrar
Por ahora al simplemente
usuario de nuestrovamosprograma.
a mostrar una ventana con
Primero
la selección vamos y una lindo
hacer botón
una muy pequeña modificación a
de OK.
ActualizaBoton()
del texto del botónpara que
(para nonos devuelva el valor
calcularlo de nuevo):
String
ActualizaBoton(
StringBuffer b = new
){
StringBuffer("Viaje:
............................. de ");
.................
ok.setLabel(b.toS
}
tring());
Y ahora vamos a definir nuestro método, teniendo en cuenta que
nuestro
todos losbotón sólo actuará si se han entrado
datos:
void
Activar()
if ( (cs.getDescription() != null) &&
{ también podríamos!=verificar
//
(cl.getDescription() null) ) que
Result8
la fecha resultado
sea válida=aquí new
Result8("Resultado",ActualizaBoton())
else
;}
ok.setLabel("Especificación
incompleta!");
Sólo nos falta definir una sencilla clase Result8
para nuestra ventanita resultado:
// archivo Result8.java, compilar
con
import javac Result8.java
java.awt.*;
class Result8
extends Frame {
Buttonr_ok
;
Result8 (String titulo, String texto)
{
super(tit
Label r_lbl = new
ulo);
r_ok = new
// constructor
Label(texto);
Button("Ok"); add("Center"
, r_lbl); add("South",
pack( r_ok);
); show(
} );

public boolean
if ((e.id ==
handleEvent(Event e) {
Event.WINDOW_DESTROY)||(e.tar
get==r_ok))
Descargado de: http://technologycompartida.blogspot.com

Página 44
Descargado de: http://technologycompartida.blogspot.com

dispose(); // cierra esta ventana


pero no la aplicación
return
} super.handleEven
} t(e);

Noten que usé dispose y no System.exit! Esto permite cerrar sólo


la ventana de
aplicación resultado,
hasta y seguir
que se nos usando
ocurra la mediante meta-F4, alt-
cerrarla
F4, el menú de sistema de la ventana,
de Windows 95 o lo que le resulte la cruz
a su sistema operativo.
Finale con
tutto
Espero que se haya entendido! Esta aplicación costó bastante pero
en el camino
aprender unashemos
cuantastenido oportunidad
cosas... Si logran de
juntar todo el código y
tiene quelasandar
generar sobre
varias rieles
clases queedefinimos, todo
independientemente de la también
Si no... avísenme, y subo plataforma.
los fuentes o las clases.
Por las dudas, pueden probar esta
aplicación como applet cargando:
http://www.amarillas.com/rock
/java/Ejemplo8.htm

Descargado de: http://technologycompartida.blogspot.com

Página 45
Descargado de: http://technologycompartida.blogspot.com

Un paréntesis de
Entrada/Salida
En Java hay muchas clases para leer y escribir archivos (u otros
biblioteca
dispositivos de E/S). Están reunidos en la
java.io.
Vamos a empezar como siempre con un pequeño ejemplo
necesario
funcional ycamino de lasnos meteremos en el
en seguida
excepciones...
Primera
Lectura
// archivo: Ejemplo9.java - compilar con
"javac Ejemplo9.java", etc. etc.
import
java.io.*;
public class
Ejemplo9
public { void main(String args[]) throws
static
FileInputStreamfptr;
FileNotFoundException,IOException {
DataInputStrea
mf;
Stringlinea = null;

fptr = new
FileInputStream("Ejemplo9.
f = new
java");
do
DataInputStream(f
{linea
ptr); =
f.readLine();
if (linea!=null)
}System.out.println(linea)
while (linea
fptr.clo
!=
; null);
se();
}
}

(Caramba! ¿Qué hace


El
eseprograma
throws ahí?)de ejemplo simplemente lee un archivo de texto y lo
muestra
del DOSen pantalla,
o el cat algo así como el type
Dejemos
de Unix. por ahora el throws
FileNotFoundException,IOException y vamos al
código.
fptr = new
FileInputStream("Ejemplo9.
java");
La clase FileInputStream (descendiente de InputStream) nos
sirve parade
(sockets) referirnos a archivos
una máquina. o conexiones
Podemos accederlos pasando un String
tipo
comoFileDescriptor,
aquí, un objetopero en esencia
de tipo es lodemismo. Al crear un
File o uno
objeto de este tipo estamos "abriendo" un
archivo,
clásicamente
Si el archivo no existe (por ejemplo reemplacen "Ejemplo9.java"
hablando.
al
porejecutarlo noscosa, como "noexiste.txt"),
alguna otra
aparece un error:
C:\java\curso>jav
a Ejemplo9
java.io.FileNotFoundExce
ption:atnoexiste.txt
at
java.io.FileInputStream.<init>(FileInp
Ejemplo9.main(Ejemplo
utStream.java:51)
(Caramba! ¿Dónde vi ese
9.java:9)
Justamente, cuando el archivo
FileNotFoudException antes?) al que quiero acceder no existe,
Java
de que"lanza" una excepción.
algo falló Esto ninguna
y, si no se toma es, un aviso
acción, detiene el programa.
La clase FileInputStream puede "lanzar" (throws) la
excepción FileNotFoundException.

Descargado de: http://technologycompartida.blogspot.com

Página 46
Descargado de: http://technologycompartida.blogspot.com

¿Cómo capturar y tratar las excepciones? En seguida;


primero terminemos con nuestro programa.
f = new
DataInputStream(f
La clase DataInputStream nos permite leer, en forma
ptr);
"corriente"
independiente (stream) que, en este
del hardware, tiposcaso, es unde
de datos archivo.
una Es
descendiente
DataInput, una de FilterInputStream e implementa
interface.
Al crear un objeto de tipo DataInputStream lo referimos al
esta claseque
archivo, tiene toda una como
le pasamos serie de métodos(fptr);
parámetro para
leernuestro
En datos enprograma
distintosusamos
formatos.
uno para leer líneas, que devuelve
String con else llega al final del archivo o un
null cuando
contenido de la línea:
do
{ linea =
f.readLine();
System.out.println
} while (linea
(linea);
!= null);
En seguida de leer la línea la imprimimos, y repetimos
estofinal,
Al mientras no nos devuelva null.
cerramos
el archivo:
fptr.clo
se();
Tanto readLine como close pueden lanzar la excepción
archi
IOException, en caso de error de lectura o cierre de
vo.
En realidad, podríamos no haber usado un
DataInputStream y trabajar en forma más directa:
import
java.io.*;
public class
public
Ejemplo10static{void main(String args[]) throws
FileNotFoundException,IOException
FileInputStreamfptr; {
intn;

fptr = new
FileInputStream("Ejemplo9.
do
{njava");
=
fptr.read(
if (n!=-1)
); while
}System.out.print((char
)n);
fptr.clo
(n!=-1);
}
se();
}

Ya que la clase FileInputStream también dispone de métodos


para leer que
métodos el archivo. Sólo que
nos permiten leerson
un unos pocos
entero por vez o un arreglo de
leer losDataInputStream
bytes. datos de muchastiene
formas distintas,
métodos paray en
general resulta más cómodo.
Capturando
excepciones
Ahora sí, vamos a ver cómo nos las arreglamos con las
excepciones
un para que no se nos pare el programa con
mensaje tan
En lugar
poco de lanzar las excepciones al intérprete, vamos a
estético...
procesarlas nosotros mediante la cláusula catch:
// Archivo:
Ejemplo11.java
// Compilar con:
java
c Ejemplo11.java
Descargado de: http://technologycompartida.blogspot.com

Página 47
Descargado de: http://technologycompartida.blogspot.com

// Ejecutar con: java


import Ejemplo11 <nombre_archivo>
java.io.*;
public class
public static{void
Ejemplo11
FileInputStreamfptr;
main(String args[]) {
DataInputStrea
mf;
Stringlinea = null;

try
{fptr = new
fFileInputStream(args[0]
= new
DataInputStream(f
);
do
ptr); =
{linea
if (linea!=null)
f.readLine();
System.out.println(linea)
} while (linea
; null);
fptr.clo
!=
}
se();
catch
System.out.println("Hey,
(FileNotFoundExcepti ese
on e) { no existe!\n");
}archivo
catch
System.out.println("Error
(IOException
}de
e) {E/S!\n");
}
}

También hicimos un cambio para elegir el archivo a imprimir


fijo,
desdeutilizando
la línea depara eso el argumento
comandos, en lugar dedelentrarlo
método main(arg[]),
que consisteque
parámetros en una lista de
se pasan en Strings
la línea con los
a continuación de java
nombre_programa.
este Por ejemplo, si llamamos a
programa
con: java Ejemplo11
archi.txt otro.xxx
arg[0] contendrá "archi.txt", arg[1] contendrá
"otro.xxx",
Por supuesto,y así sucesivamente.
si llamamos a Ejemplo11 sin parámetros se
lanzará otra excepción al intentar accederlo:
C:\java\curso>java
java.lang.ArrayIndexOutOfB
Ejemplo11
oundsException:
at 0
Ejemplo11.main(Ejemplo1
Pero también
1.java:10)
podríamos
Veamos uncapturarla!
poquito cómo es esto de
capturar
La cláusulaexcepciones.
try engloba una parte del programa donde se pueden
produce, Java busca Si
lanzar excepciones. una instrucción
una excepcióncatch
se
(nombre_de_la_excepción
ejecuta lo que ésta engloba.variable), y, si la un
Si no encuentra encuentra,
catch para esa
que se
excepción, para el programa y muestra el error
Por ejemplo, para evitar este último
produjo.
error bastaría con agregar:
catch
System.out.println("Debe
(ArrayIndexOutOfBoundsEx ingresar
System.out.println("Ej.:
un nombre
ception e) {de archivo!");java
}Ejemplo11 pepe.txt");

Descargado de: http://technologycompartida.blogspot.com

Página 48
Descargado de: http://technologycompartida.blogspot.com

Hay que notar que cuando se lanza una excepción el programa


igual se detiene,
lanzamiento de laporque el código
excepción no seque sigueVeremos
ejecuta. al luego cómo
se comporta
por esto usar
otro, y cómo en unlaobjeto que fue
instrucción creado
finally para poner una parte
de código que se ejecute pase lo que pase.
Los applets y los
archivos
Veamos cómo se comporta esta aplicación si la
modificamos para usarla como applet.
/*
// ----- Archivo:
*/
Ejemplo12.java
import
import
java.io.*;
import
java.awt.*;
java.applet.*;
public class Ejemplo12
extends Applet {
public void
init() { new
} Ventana12(
} );

/*
// -------- Esta clase es la que en
*/
realidad hace el trabajo

class Ventana12
extends Frame {
TextAreacont
enido;
Buttoncerrar;

Ventana1
2() {
super("Ejemplo
contenido
de E/S"); = new
TextArea();
cerrar = new
Button("Cerrar");
CargarArc
add("North",co
hivo();
add("South",
ntenido);
cerrar);
pack
show
();
();
}

public boolean
if
handleEvent(Event e) {
((e.id==Event.WINDOW_DESTRO
dispos
Y)||(e.target==cerrar))
return
e();
super.handleEven
}
t(e);
void
FileInputStreamfptr;
CargarArchivo
DataInputStrea
() {
mf;
Stringlinea = null;
try
{

Descargado de: http://technologycompartida.blogspot.com

Página 49
Descargado de: http://technologycompartida.blogspot.com

fptr = new
fFileInputStream("Ejemplo12
= new
.java");
do
DataInputStream(f
{linea
ptr); =
if
f.readLine();
contenido.appendTex
(linea!=n
t(linea+"\n");
}ull)while (linea
!= null);
fptr.clo
}
se();
catch
contenido.appendText("Hey,
(FileNotFoundExcept ese
}archivo
ion e) { no existe!\n");
catch
(IOException
contenido.appendText("E
e) { de E/S!\n");
}rror
}
}

Lo cargamos desde la página


Ejemplo12.html:
<HTM
L>
<HEA
<TITLE>Ejemplo 12 - Ejemplo
D>
</HEA
con archivo</TITLE>
D>
<BOD
Y>
<applet code="Ejemplo12.class"
</appl
width=170 height=150>
et>
</BOD
</HT
Y>
ML>
Mientras corramos esto en la misma máquina, no hay problema
(anda muy
cargarlo bien!).
desde PeroPara
la red? qué los
pasa si intentamos
que no tengan
http://www.amarillas.com/rock/j
server html puse una copia en:
ava/Ejemplo12.htm
El archivo no aparece! En su lugar se produce una excepción;
Explorer,
en la líneapor
de estado del Microsoft Internet
ejemplo, se lee:
exception: com.ms.applet.AppletSecurityException:
security.file.read: Ejemplo12.java

Esto es debido a una restricción de seguridad de Java: NO SE


PUEDEN
ESTEN ENCARGAR
UNA MAQUINAARCHIVOS QUE A AQUELLA
DISTINTA
applet
DESDE seLA
corre en elSE
CUAL cliente,
CARGO e intenta acceder aEl
EL APPLET. un archivo local.
Eso es lo que
supuesto, puedeprovoca la excepción
detectarse con (que, por
un catch
Por cuestionesy tratarse...)
de seguridad, los applets son más limitados que las
seguridad
aplicaciones lasJava
manejan los Las
locales. browsers (no de
políticas Java), y generalmente los
• que
límites Unseapplet no puede
imponen cargar bibliotecas
a los applets son:
• No puede
(libraries) ni definir
leer ométodos nativos
escribir normalmente archivos en el
•cliente Noque lo carga
puede desdeconexiones
establecer otro serverde red,
•salvoNo al puede
servidor del queprogramas
arrancar proviene en la
•máquina dondeleer
No puede se está ejecutando
ciertas
•propiedades del sistema
En las ventanas de los applets se
indica que se trata de un applet
Sin embargo,
pueden: • Reproducir
• Pueden establecer conexiones con el
sonidos
servidor del que provienen
Descargado de: http://technologycompartida.blogspot.com

Página 50
Descargado de: http://technologycompartida.blogspot.com

• Pueden llamar fácilmente páginas


•HTML desdeinvocar
Pueden el browser
métodos públicos de
•otrosSiapplets de ladesde
se cargan misma página máquina (localmente) no
la propia
• Pueden seguir corriendo aunque
tienen ninguna de las restricciones anteriores
se
cambie de página en el browser
En realidad, la especificación de Java permite que los applets lean
completa;
archivos ensin embargo,
otras los browsers
máquinas no lo permiten. Veremos
dando la URL
más adelante
máquinas paracómo
poderintercambiar datos entre
ver un archivo
del server, por ejemplo.
Nuestro modesto
"Editor"
Para terminar este capítulo, el siguiente applet nos permite
cargar, editar
Podemos usaryinclusive
grabar archivos ascii "cut
las acciones a elección.
& paste" del windows
Cargarlo con "appletviewer
manager (Ctrl-C y Ctrl-V enEjemplo13"
Windows)! luego de haberlo
compilado
brows (o usar una página html desde un
er):
/*
// ----- Archivo:
*/
Ejemplo13.java
import
import
java.io.*;
import
java.awt.*;
java.applet.*;
public class Ejemplo13
extends Applet {
public void
init() { new
} Ventana13(
} );

/*
// -------- Esta clase es la que en
*/
realidad hace el trabajo

class Ventana13
extends Frame {

TextAreacont
enido;
Botones13pieV
entana;
Ventana1
3()contenido
{
super("Ejemplo = new
de pieVentana
E/S");
TextArea(); = new
Botones13();
add("North",con
add("South",pieV
tenido);
pack()
entana);
;show()
}
;
public boolean
if
handleEvent(Event e) {
((e.id==Event.WINDOW_DESTR
dispose()
OY)||(e.id==2003))
if (e.id==2001)
; if (e.id==2002)
CargarArchivo(pieVentana.toStrin
g());
GrabarArchivo(pieVentana.toStrin
g());
Descargado de: http://technologycompartida.blogspot.com

Página 51
Descargado de: http://technologycompartida.blogspot.com

return
super.handleEvent(
}
e);
void
CargarArchivo(String
FileInputStreamf
nombre) {
DataInputStrea
ptr;Stringlinea = null;
mf;
try
contenido.setTe
{xt("");
fptr = new
f = new
FileInputStream(nombre)
DataInputStream(fptr
;
do { linea =
);
f.readLine();
if (linea!=null)
} while
contenido.appendText(linea+"\n")
(linea
; != null);
fptr.close(
} catch
);
(FileNotFoundExceptio
new Error13("El
n e) { archivo no existe!");
} catch
(IOException e) Error13("Error
new
{ leyendo archivo!");
}}

void
GrabarArchivo(String
FileOutputStream
nombre) {
fptr;try
DataOutputStre
{amf;fptr = new
FileOutputStream(nombre
f = new
);
DataOutputStream(fpt
r);
f.writeBytes(contenido.
fptr.close(
getText());
);
} catch
(IOException new
e) Error13("Error
{ grabando archivo!");
}}
}

/*
// -------- Esta es para los botones y
el nombre del archivo
*/

class Botones13
extends Panel {

TextFieldfn
Buttoncarga
ame;
r;
Buttongraba
r;
Buttoncerra
r;
setLayout(new
Botones1
3()fname = new
GridLayout(1,4));
{
TextField();

Descargado de: http://technologycompartida.blogspot.com

Página 52
Descargado de: http://technologycompartida.blogspot.com

cargar = new
Button("Cargar");
grabar = new
cerrar = new
Button("Grabar");
Button("Cerrar");
add(new
Label("Archivo:"));
add(fnam
add(carg
e);
ar);
add(grab
ar);
}
add(cerra
r);
public boolean
if
handleEvent(Event e) {
((e.id==Event.ACTION_EVENT)&
e.id=20
&(e.target==cargar))
if 01;
e.id=20
((e.id==Event.ACTION_EVENT)&&
02;
(e.target==grabar))
if
e.id=20
((e.id==Event.ACTION_EVENT)&
return 03;
&(e.target==cerrar))
super.handleEvent(
}
e);
public String
toString()
return {
}
fname.getText()
};

/*
// ------- Para mostrar
los errores...
*/

class Error13
extends Frame {

add("Center",new
Error13(String
error) { Label(error));
add("South", new
pack(
Button("Ok"));
show(
);
} );

public boolean
handleEvent(Event e) {
return
dispose(
);}
super.handleEvent(
}e);

Descargado de: http://technologycompartida.blogspot.com

Página 53
Descargado de: http://technologycompartida.blogspot.com

Volviendo
al
para
vamos AWT
Para aprender un poquito más sobre la biblioteca gráfica (AWT),
usar
a modificar nuestro último programa
menús.
Vamos a volver a poner todo el código (que ampliamos para usar
las
como diferencias
applet o aplicación local) marcando
más notables:
/*
// ----- Archivo:
*/
Ejemplo14.java
import
java.io.*;
import
import
java.awt.*;
java.applet.*;
public class Ejemplo14
extends Applet {
public void
init() { new Ventana14(true); //
} con "true" avisamos que es applet

public static void main(String args[])


{ Ventana14 v14 = new Ventana14(false); // con
"false" avisamos que no es applet
}// para usarlo como aplicación

/*
// -------- Esta clase es la que en
*/
realidad hace el trabajo

class Ventana14
extends Frame {

booleanenApplet;
TextAreacont // para
StringnombreArchivo;
indicar
enido; si lo llamamos como applet // para
guardar el nombre del archivo abierto
MenuItemmArchivoAbrir; // ACA
ESTAN LOS ITEMS DE LOS MENUS
MenuItemmArchivoGrabar;
MenuItemmArchivoSalir;
//
MenuItemmEditCortar;
//
MenuItemmEditCopiar;
.
MenuItemmEditPegar;
//
.
//
MenuItemmEditTodo;
//
Stringclipboard;
. booleaneditado = false; // acá
.
//
indicamos si modificamos el archivo
. buffer para cortar y pegar
//
v
Ventana14(boolean
enApp) {
enApplet =
super("Ejemplo
enApp;
de E/S");
Menu menuArchivo = new
// recordamos si es=applet
mArchivoAbrir
Menu("&Archivo"); new o no
mArchivoGrabar = new
MenuItem("&Abrir...");
MenuItem("&Grabar...");
// CREAMOS LOS MENUS!!!
Descargado de: http://technologycompartida.blogspot.com

Página 54
Descargado de: http://technologycompartida.blogspot.com

mArchivoSalir = new
MenuItem("&Salir");
menuArchivo.add(mArc
hivoAbrir);
menuArchivo.add(mArchi
menuArchivo.add(new
voGrabar);
MenuItem("-"));
menuArchivo.add(mArc
hivoSalir);
Menu menuEdit = new
mEditCortar = new
Menu("&Edit");
MenuItem("Cor&tar");
mEditCopiar = new
MenuItem("&Copiar");
mEditPegar = new
mEditTodo = new
MenuItem("&Pegar");
MenuItem("&Seleccionar todo");
menuEdit.add(mEdit
Cortar);
menuEdit.add(mEdit
menuEdit.add(mEdit
Copiar);
menuEdit.add(new
Pegar);
MenuItem("-"));
menuEdit.add(mEdi
MenuBar barraMenu =
tTodo);
new MenuBar();
barraMenu.add(menu
barraMenu.add(men
Archivo);
uEdit);
setMenuBar(barra
Menu);
contenido = new
TextArea();
add("Center",con
tenido);
// solo pongo una ventana de texto
pack()
;show()
; clipboard = new
String("");
mEditPegar.disable();
mArchivoGrabar.disable();
//}clipboard vacío,
// nada para pegar,
//public
nada para grabar
boolean
handleEvent(Event
if e) {
if (editado) System.out.println("Pedir
((e.id==Event.WINDOW_DESTROY)||(e.tar
confirmación!\n");
get==mArchivoSalir)) { // si se
ir sin quiere
grabar! // debería
if confirmar
(enApplet)
else
dispose();
System.exit(
} if (e.target==mArchivoAbrir)
0);
if (e.target==mArchivoGrabar)
CargarArchivo();
GrabarArchivo();
if
// acá proceso clipboard
(e.target==mEditCo =
selecciones
// de {menú mEditPegar.en
rtar) contenido.getSelectedText
();
able();
contenido.replaceText("",contenido.getSelectionStart(),
editado=t
contenido.getSelectionEnd());
rue;
} if
clipboard =
(e.target==mEditCo
contenido.getSelectedText
piar) {
mEditPegar.en
();
able();
} if
contenido.replaceText("",contenido.getSelectionStart(),
(e.target==mEditPe
gar) { contenido.getSelectionEnd());

Descargado de: http://technologycompartida.blogspot.com

Página 55
Descargado de: http://technologycompartida.blogspot.com

contenido.insertText(clipboard,contenid
editado=t
o.getSelectionStart());
rue;
} if (e.target==mEditTodo)
if
contenido.selectAll();
((e.id==Event.KEY_PRESS)&&(e.target==con
mArchivoGrabar.enable
tenido))
return editado=true;
(editado);
super.handleEvent(
}
e);
void
CargarArchivo(
FileInputStreamf
){
DataInputStrea
ptr; Stringlinea = null;
mf;if (editado)
System.out.println("Pedir
FileDialog fd = new
confirmación!\n");
FileDialog(this,"Abrir...",FileDialog.LOAD);
siste
fd.show();
nombreArchivo
// elijo
ma! archivo =
fd.getFile();
try
// usando el diálogo estándar del
{ fptr = new
f = new
FileInputStream(nombreArchi
DataInputStream(fptr
vo);contenido.setText(""); // vacío la
);
ventana antes de cargar nuevo archivo
do { linea =
f.readLine();
if (linea!=null)
contenido.appendText(linea+"\n")
} while
;
(linea != null);
fptr.close(
editado=false;
);
catch nuevo -> no editado
}// archivo
(FileNotFoundExceptio
new Error14("El
n e) { archivo no existe!");
} catch
(IOException e) Error14("Error
new
{ leyendo archivo!");
} catch
(NullPointerExceptio
;
n e) {
}}

void
GrabarArchivo(
FileOutputStream
){
fptr;
FileDialog fd = new
DataOutputStre
FileDialog(this,"Grabar...",FileDialog.SAVE);
amf;fd.setFile(nombreArchivo); //
usando el diálogo estándar del sistema!
// grabo archivo =
nombreArchivo
fd.show(
try
fd.getFile();
);
{ fptr = new
FileOutputStream(nombreArch
f = new
ivo);
DataOutputStream(fpt
f.writeBytes(contenido.
r);
getText());
fptr.close(
editado=false;
);
}
// recién grabado -> no editado
Descargado de: http://technologycompartida.blogspot.com

Página 56
Descargado de: http://technologycompartida.blogspot.com

catch
(IOException e) Error14("Error
new
{ grabando archivo!");
} catch
;
(NullPointerExceptio
n e) {
}}
}

/*
// ------- Para mostrar
*/
los errores...

class Error14
extends Frame {

add("Center",new
Error14(String
error) { add("South", new
Label(error));
Button("Ok"));
pack(
);
show(
} );

public boolean
handleEvent(Event e) {
dispose(
return
);}
super.handleEvent(
}e);

Menú a la
Javalo primero que vamos a
Bueno,
La
ver barra de menús.
son los menú está compuesta por menúes, que a su vez están
compuestos
ser menúes).dePorítems (que la
ejemplo pueden también
barra de
menú la declaramos con:
MenuBar barraMenu =
new MenuBar();
y le agregamos los menúes Archivo y Edit (que
habremos creado previamente) con:
barraMenu.add(me
nuArchivo);
barraMenu.add(
menuEdit);
Finalmente la declaramos como EL
menú de la ventana (Frame):
setMenuBar(bar
raMenu);
Cada uno de los menús los
declaramos previamente:
Menu menuArchivo = new
...
Menu("&Archivo");
Menu menuEdit = new
Menu("&Edit");
Noten que el "&" no se visualiza, sino que la letra que le sigue
aparece
que subrayada:
se pueda Archivo,
seleccionar Edit.tanto
el menú Esto permite
con el mouse como
subray
con la tecla alt- o meta-, seguida de la tecla
ada.
Descargado de: http://technologycompartida.blogspot.com

Página 57
Descargado de: http://technologycompartida.blogspot.com

A su vez, el método add está presente también en la clase


Menú y nos permite agregar los ítems:
mArchivoAbrir = new
MenuItem("&Abrir...");
mArchivoGrabar = new
mArchivoSalir = new
MenuItem("&Grabar...");
menuArchivo.add(m
MenuItem("&Salir");
ArchivoAbrir);
menuArchivo.add(mA
rchivoGrabar);
menuArchivo.add(new
menuArchivo.add(m
MenuItem("-"));
ArchivoSalir);
A estos ítems los hemos declarado como globales en la clase para
qu
usarlos luego en los eventos. Noten además
e
menuArchivo.add(new
MenuItem("-"));
no agrega un ítem al menú sino una línea de separación, y no
necesitamos
Si miramos lacrearlo como objeto
arquitectura permanente.
de las clases, tanto MenuBar como
A su vez, Menu
MenuItem desciende
descienden de MenuItem, por lo que
de MenuComponent.
implementa
decíamos los mismos
antes: un menúmétodos
puede ser y vamos
un ítema de
lo que
otro menú, y así
sucesivamente tantos subniveles de menús
como
Finalmente, en nuestro manejador de eventos simplemente
queramos.
si el evento ocurrió
necesitamos sobre
verificar si seeleligió un ítem probando
ítem determinado:
if
((e.id==Event.WINDOW_DESTROY)||(e.ta
if (editado)
rget==mArchivoSalir)) (enApplet){
System.out.println("Pedir
if
confirmación!\n");
else
dispose();
System.exit(
}if (e.target==mArchivoAbrir)
0);
...........
CargarArchivo();
if (e.target==mEditTodo)
.....
contenido.selectAll();
En resumen lo
• Si
que hago es:eligió Archivo/Salir (o alt-F4 o lo
•que sea) salgoArchivo/Abrir,
Si eligió del programa llamo al
•método CargarArchivo
Si eligió Archivo/Grabar, llamo al
•método GrabarArchivo
Si eligió Edit/Cortar copio el texto seleccionado a
•mi clipboard
Si eligió yEdit/Copiar
borro la selección
sólo copio el texto
• Si eligió Edit/Pegar borro el texto
seleccionado a mi clipboard
• Si eligió e inserto el de mi clipboard
seleccionado
En todos Edit/Seleccionar_todo marco el
los casos, si se modifica todo
texto del contenido lo
indico el texto
poniendo
presiono una tecla sobre eleditado en true; lo mismo si
área de edición:
if
((e.id==Event.KEY_PRESS)&&(e.target==
contenido)) editado=true;
Un par de
• getSelectionStart() y getSelectionEnd() marcan los límites
aclaraciones:
del texto
son seleccionado (si no lo hay,
• getSelectedText()
iguales). devuelve el texto
• replaceText()
seleccionado en el reemplaza
TextArea. una parte (o todo)
• TextArea
del insertText()porinserta
un String.
un String en un lugar
•determinado
selectAll()delselecciona
TextArea.todo el
texto del TextArea.

Descargado de: http://technologycompartida.blogspot.com

Página 58
Descargado de: http://technologycompartida.blogspot.com

• MenuItem.enable() habilita un ítem de menú. Lo utilizo


para cortar
habilitar Edit/Pegar
o copiar algo asólo luego de
• En mi clipboard.
el caso del ítem Archivo/Grabar, lo habilito o no
dependiendo de lade
la otra forma variable
enable:editado, utilizando
MenuItem.enable(boolean).
Diálo
gos
En Java disponemos de la clase Dialog para crear diálogos, es
decir, ventanitas
usuario, temporarias
que dependen de otrapara
(de entradas
hecho la de
clase
Dialog
Si bien es heredera
podemos de ladiálogos
crear clase Window).
a medida usando la clase Frame,
fácil. La realidad
se supone que usaresdiálogos
que por debe
ahoraserno más
se puede usar mucho más
que los es
la pena diálogos estándar
FileDialog), ya (y
queel las
único que vale
implementaciones actuales
plataformas
de Java tienen el un
programa
problema:queenabre el diálogo sigue, en lugar de
algunas
respue
esperar que se cierre el diálogo y devuelva la
sta.
Por eso hemos puesto solamente una indicación adonde
debería haber un diálogo de confirmación:
if (editado)
System.out.println("Pedir
confirmación!\n");
En ese lugar deberíamos llamar por ejemplo a un diálogo
que nos permita decidir por sí o por no:
if
(editado
sino = new
){
if
ConfirmarDlg(this,"Archivo
else
(sino.getResponse()
modificado!");
....;
}==true) ....;

o algo así. Esto mismo lo podemos hacer de otras maneras, por


ejemplo
entre usandopero
procesos, threads y comunicaciones
se complica mucho para esta altura del curso.
Sun me prometió
Esperemos un pocoquemásen adelante,
la versiónaunque
1.1 ya va a estar
corregido
Por (saleveamos
lo pronto, para fines del '96).
un caso simple
con la clase FileDialog:
FileDialog fd = new
fd.sho
FileDialog(this,"Abrir...",FileDialog.LO
w();
AD);
nombreArchivo =
fd.getFile();
Primero declaramos una variable de tipo FileDialog, y creamos
la instancia
pasa el padrecon new.
(this, Como
o sea parámetros
"esta ventana"),seel título de la ventanita
de diálogo,
(son y una
static, por lo constante LOAD odirectamente
que se denominan SAVE con el
instancia)
nombre deque indica
la clase si elnecesariamente
y no diálogo es paradecargar
una o grabar un
archivoel(Obviamente
grabar la tarea en
archivo la tenenmos quesíhacer
de cargar o
nosotros, el
El método
diálogo sóloshow()
esperamuestra el diálogo
que elijamos y espera que seleccionemos y
un nombre).
presionemos
fallan los demásOk diálogos
o Cancel.ya Aquí
queesesdonde
programa sigue
Finalmente, sin esperar.
el diálogo se cierra pero no se elimina el objeto
método hide(), está
(posiblemente que implementado
lo oculta de la vista
usandopero
el no se pierde hasta no
salir
el del método
recogedor que lo de
de basura creó, donde actuaría
la memoria). Esto hace que aunque
getFile()
no lo veamossobrepodamos
este objeto, quealnos
llamar devuelve el nombre del
método
archivo seleccionado (o null si se presionó
Cance
l).

Descargado de: http://technologycompartida.blogspot.com

Página 59
Descargado de: http://technologycompartida.blogspot.com

DibuJ
ava
Además de los componentes estándar (botones, listas, etc.), hay
permite implementar
un componente cualquier
para dibujo otroque
"libre" tiponos
de control: la clase
Canvas. Típicamente
corresponde a una zona se rectangular
usa para dibujar, y
La clasedeenuna
dentro sí no hace prácticamente nada; el programador debe
ventana.
AWT
definirleuna
envía todos de
subclase losCanvas
eventosade la mouse
que el y teclado.
Redefiniendo
keyDown, los métodos
keyUp, gotFocus,
mouseEnter, lostFocus,
mouseExit, mouseMove,
mouseDrag, mouseDown
programador puede hacer ylomouseUp, el
que se le ocurra dentro de ese
generar un applet
rectángulo. Vamosdonde
a hacerhabrá
uso una
de unzona rectangular
Canvas para dentro
de la que, haciendo
moviéndolo click
sin soltar con el dibujaremos
el botón, mouse y
Esto nos permitirá
un rectángulo ver cómo usar un Canvas para dibujar,
dinámicamente.
capturar
redibujar,eventos,
pero ya etc. El borde tiembla un poco al
veremos
cómo evitar eso.
Canvas en
acción
Primero vamos a poner, como ya se está haciendo costumbre,
el códigodesde
cargarse del applet (Recordar
una página htmlque
paradebe
verlo! Aquí no creamos
aplicación standalone)
ninguna ventana y luego verlo como
y no podremos
intentaremos explicar cómo funciona.
import
import
java.awt.*;
java.applet.Appl
et;
public class Ejemplo15
publicApplet {
extends
void init() { Label label = new Label("Pique y
arrastre conzonaDib
miCanvas el mouse!");
=
zonaDib.resize(new
new miCanvas();
Dimension
add("North", (200,200));
label);
add("Center",
resize(300,
zonaDib);
250);
}

class miCanvas
extends Canvas {
Rectangle
rectActual;
public boolean
mouseDown(Event e, int
rectActual x, int
= new
y) { repaint
Rectangle(x, y, 0, 0);
();
return
false;
}
public boolean
mouseDrag(Event e, int x, int y)
rectActual.resize(x-
{ repaint
rectActual.x, y-rectActual.y);
();
return
false;
}
public boolean
mouseUp(Event e, int x, int y)
rectActual.resize(x-
{ repaint
rectActual.x, y-rectActual.y);
();
return
false;

Descargado de: http://technologycompartida.blogspot.com

Página 60
Descargado de: http://technologycompartida.blogspot.com

}
public void
paint(Graphics g) {
Dimension d
g.setColor(Co
= size();
g.drawRect(0, 0,
lor.red);
d.width-1, d.height-1);
g.setColor(Col
or.blue);
if (rectActual
!= null) { Rectangle box =
cortarRect(rectActual,
g.drawRect(box.x, d);
box.y,
} box.width-1, box.height-1);

}
Rectangle cortarRect(Rectangle
int xDimension
miRect, = areaDib) {
miRect.x;
int y =
int ancho =
miRect.y;
int alto =
miRect.width;
miRect.height;
if
(ancho < ancho
0) { =
-ancho;x = x -
ancho +if1;(x
< 0) {
ancho += x;
x = 0;
}
} if (alto
< 0) { alto
= -alto; y = y -
alto + 1;if (y
< 0) {
alto += y;
y = 0;
}
}
if ((x + ancho) >
areaDib.width)
ancho = {
areaDib.width - x;
} if ((y + alto) >
alto = {
areaDib.height)
areaDib.height - y;
}
return new
Rectangle(x, y, ancho,
}
alto);

El applet-
container
En primer lugar hemos tenido en cuenta que un Applet es un
Panel,
que en ylugar
por lo
detanto
creartambién un Container,
una ventana así
aparte simplemente le
agregamos dos componentes: un Label y un Canvas.
zonaDib.resize(new
Dimension (200,200));

Descargado de: http://technologycompartida.blogspot.com

Página 61
Descargado de: http://technologycompartida.blogspot.com

add("North",
label);
add("Center",
resize(300,
zonaDib);
250);
El método rezise, sobre la clase miCanvas, nos permite
redimensionar
Igualmente, el mismo
usamos al sobre
resize tamañoel deseado.
applet para darle un tamaño
ventana
adecuado.enSi
el se
appletviewer
modifica else observará
tamaño de laun comportamiento
algo extraño
relativo en cuanto yalelposicionamiento
del rectángulo cartel, pero
para simplificar esto bastará.
Nuestro Canvas
a medida
Como no vamos a tomar ninguna acción especial al crear el
canvas,elno
utiliza hemos definido
constructor el constructor (se
por defecto
Simplemente hemos redefinido algunos métodos para actuar al
de la clase Canvas).
presionar,elarrastrar
redibujar área de ydibujo
soltar(canvas)
el mouse,y para recortar el rectángulo
del espacio
dibujado que vamos con el mouse fuera
si nos
La variable
ocupa global rectActual, de la clase Rectangle, contendrá las
el canvas.
coordenadasEldel
dibujando. rectángulo
método Paint que estamos
se llama automáticamente cada vez
llamamos explícitamente
que es necesario redibujaralel componente, o si
método repaint():
public void
paint(GraphicsDimension
g) { d
g.setColor(Co
= size();
lor.red);
g.drawRect(0, 0,
d.width-1, d.height-1);
g.setColor(Col
if (rectActual
or.blue);
!= null) { Rectangle box =
g.drawRect(box.x, box.y,
cortarRect(rectActual, d);
} box.width-1, box.height-1);

}
En primer lugar le asignamos a una variable d el tamaño del
canvas
un colorusando
(rojo) el
paramétodo
dibujarsize(), luegoy elegimos
un borde dibujamos un
rectángulo del tamaño del componente:
Dimension d
= size();
g.setColor(Co
lor.red);
g.drawRect(0, 0,
d.width-1, d.height-1);
Dos atributos de la clase Dimension, width y height, se han
cargado
usamos paracon el dartamaño
el del canvas y son los que
Luego,
tamaño si delserectángulo.
está dibujando un rectángulo (rectActual != null)
simplemente
hayamos lo recortamos
arrastrado el mouse (enfuera
casodel
de que
canvas)
El método y loque
dibujamos.
lo recorta a los límites del canvas, cortarRect,
rectángulo
asigna a cuatro(quevariables
se le pasaron como
las coordenadas del
parámetro miRect al llamarlo):
int x =
int y =
miRect.x;
miRect.y;
int ancho =
miRect.width;
int alto =
miRect.height;
Si el ancho (o el alto) es negativo, simplemente lo cambia de
signo
el otroyvértice
toma como coordenadaque
del rectángulo, x (y) de origen al x que se pasó
corresponderá
origen
menos de coordenadas
el ancho empieza
y más uno en cero
(recordar queyelno en uno). Si este
vértice
cero y leestá fuera
resta del canvas
al ancho (x<0),
la parte lo pone
recortada en que ancho+=x,
(notar
como x es negativo, es en realidad una resta).

Descargado de: http://technologycompartida.blogspot.com

Página 62
Descargado de: http://technologycompartida.blogspot.com

if (ancho
< 0) { ancho =
-ancho;x = x -
ancho +if1;(x
< 0) {
ancho += x;
x = 0;
}
}
Si nos vamos del área de dibujo por la derecha (o por abajo),
exceso de modo
simplemente que llegue al
le recortamos hasta el borde
ancho (alto) del
el área de dibujo
(que también hemos pasado al método como
paráme
tro):
if ((x + ancho) >
ancho = {
areaDib.width)
}areaDib.width - x;
Sólo nos quedan por ver los métodos
que responden
Cuando al mouse.
presionamos el mouse dentro del canvas, comenzamos la
creación
alto cero de
queuncomienza
nuevo rectángulo deen
en el punto ancho y
que hemos
presionado el mouse, y redibujamos el canvas:
public boolean
rectActual
mouseDown(Event = new
e, int x, int
y) { Rectangle(x, y, 0, 0);
repaint
();
return
false;
}
Al mover el mouse, redimensionamos el rectángulo con ancho x
menos de
origen el origen
dibujo),deydibujo (y alto y menos el
repintamos:
public boolean
rectActual.resize(x-
mouseDrag(Event e, int x, int y)
{ rectActual.x, y-rectActual.y);
repaint
return
();
false;
}
Finalmente, al soltar el mouse,
redimensionamos como antes y redibujamos:
public boolean
mouseUp(Event e, int x, int y)
rectActual.resize(x-
{ repaint
rectActual.x, y-rectActual.y);
();
return
false;
}
Como no se toma ninguna medida para guardar el rectángulo
dibujado,
rectActualala crear uno nuevo
un nuevo (reasignando
rectángulo),
el anterior se pierde.

Descargado de: http://technologycompartida.blogspot.com

Página 63
Descargado de: http://technologycompartida.blogspot.com

DibuJa
va
borren II
Vamos a retocar un poquito nuestro ejemplo15 para que no se
dibujar unorectángulos
los nuevo. Aprenderemos algo sobre la clase
cuando queremos
Vector, perteneciente al paquete java.util.
Vectores en
acción
Los vectores nos permiten hacer arreglos de cualquier tipo de
elemento del vector,individualmente
objeto, y referirnos aunque para utilizarlos (debido a que para
a cualquier
tendremos
java el vector quecontiene
decirle qué clasegenéricos)
objetos de objeto es mediante un "cast".
Vamos a ver(ex
Ejemplo16 cómo quedan nuestras clases
Ejemplo15) y miCanvas:
import
import
java.awt.*;
java.util.*;
import
java.applet.Appl
public class Ejemplo16
et;
extends
publicApplet {
................
void init() (esta{ parte no
cambia)................
}

class miCanvas
VectorCanvas
extends v = new
{ Vector(); //
inicializamos con tamaño indeterminado // Java se encarga de manejar la
memoria necesaria!
public boolean
v.addElement(
mouseDown(Event e, int x,new
int Rectangle(x, y, 0, 0)
y) { );
repaint
();
return
// nuevo elemento!
false;
}
public boolean
Rectangle
mouseDrag(Event e, intr =x, int y)
{ (Rectangle)v.lastElement();
r.resize( x - r.x, y - r.y
);
repaint
// cast: v son rectángulos
return
();
// (creé r sólo por claridad)
false;
}
public boolean
Rectangle
mouseUp(Event r =int y)
e, int x,
{ (Rectangle)v.lastElement();
r.resize( x - r.x, y - r.y
);
repaint
// cast: v son rectángulos
return
();
// (creé r sólo por claridad)
false;
}
public void
int g) {
paint(Graphics
i;
Dimension d
g.setColor(Co
= size();
// contador de rectángulos
lor.red);
g.drawRect(0, 0,
g.setColor(Col
d.width-1, d.height-1);
if (v.size()
or.blue);
> 0)

Descargado de: http://technologycompartida.blogspot.com

Página 64
Descargado de: http://technologycompartida.blogspot.com

for (i=0;
i<v.size(); i++) { Rectangle box = cortarRect(
(Rectangle)v.elementAt(
g.drawRect(box.x, box.y,i ), d);
box.width-1, box.height-1);
}
}........................ (el resto no
cambia)
} ........................

Les sugiero utilizar un HTML que reserve espacio


suficiente para ver todo el applet, como:
<HTM
<HEA
L>
<TITLE>Ejemplo 16 - Ejemplo
D>
con canvas</TITLE>
</HEA
D>
<BOD
<applet code="Ejemplo16.class"
Y>
width=300
</appl height=250>
</BOD
et>
</HT
Y>
ML>
Veamos los pasos ahora. En primer lugar creamos una variable
y(global
sin asignarle un llamada v, de clase Vector,
a la clase)
tamaño definido:
Vector v = new
Vector();
Al crear un nuevo rectángulo agregamos un elemento
(objeto) al vector mediante el método add:
v.addElement( new
Rectangle(x, y, 0, 0) );
Para acceder a un atributo de un objeto del vector no basta
utilizar directamente el vector, como:
v.lastEleme
nt().x
(lastElement() nos permite acceder al último elemento
agregado al vector).
explícitamente que elEselemento
necesarioenaclarar
cuestión es un rectángulo,
ya que el vector
cualquier puede
tipo. Para esocontener objetos de
usamos el casting:
(Rectangle)v.lastEl
ement().x
En nuestro código original
reemplazaríamos por:
(Rectangle)v.lastElement().resize( x -
(Rectangle)v.lastElement().x, ......

Pero es más claro si usamos una variable local de clase


acabamos
Rectangle,dele agregar
asignamos al vector, y objeto que
el mismo
lo usamos en su lugar:
Rectangle r =
(Rectangle)v.lastElement(
r.resize( x - r.x,
y); - r.y );
Finalmente, en el método paint() no podemos asignar el elemento
hasta no
vector sabervacío!).
estaba que existe
Así(originalmente el
que un if nos permite verificar que el
tamaño del vector
elementos), y un for es nos
mayor que cero (tiene
permite
dibujarlos uno por uno.

Descargado de: http://technologycompartida.blogspot.com

Página 65
Descargado de: http://technologycompartida.blogspot.com

Se puede acceder a todos los elementos, uno por uno, mediante


ésimo elemento
el método del vector.
elementAt(x), queElnos
método
da el size()
x- nos da la cantidad
de elementos (el primero es el número 0, y
así)
:
if (v.size()
for (i=0;> 0)
i<v.size(); i++) { Rectangle box = cortarRect(
(Rectangle)v.elementAt(
g.drawRect(box.x, box.y,i ), d);
box.width-1, box.height-1);
}
Aquí no hemos creado variables intermedias ya que
igualmente es claro (eso creo...).
Flicker
molesto!
Bueno, el problema que nos queda es el molesto "flicker", o
movemos
sea la manera el mouse.
en queEsto
titilaeselporque
dibujo cada vez que se llama a
cuando
paint(), el fondo se borra y se redibuja todo el
canva
Básicamente, la manera de evitarlo es reescribiendo el método
s.
update(),
llamar que es para
a paint() el que
que borra
no loelborre;
fondo otro
antesmétodo
de (que es el que
vamos
sino a usar)
sobre es dibujar
un "buffer" no sobre
gráfico, la pantalla
y luego copiar ese buffer sobre la
dibujar
pantallasobre (lo que la es mucho más eficiente que
misma).
Para eso vamos a crear un
par de objetos:
class miCanvas
extends
VectorCanvasv= {
new Vector();
GraphicsgrafBuff;
ImageimgBuf
f;
...................
..........
Image es una clase abstracta, madre de todas las clases que
representan
también imágenes
abstracta y nosgráficas.
permiteGraphics es
obtener un
Lo que vamos
contexto a hacer
en el cual es modificar nuestro método paint()
dibujar.
redefinir
para que el simplemente llame a update(), y
método update():
public void
paint(Graphics update(
g) {
} g);

El método update() es el que hará todo el trabajo y básicamente


es como nuestro viejo paint() con algunos
agregad
os:
public void
int g)
update(Graphics
{ i;
Dimension d
= size();
if (grafBuff
== null) { imgBuff =
grafBuff =
createImage(d.width,
} imgBuff.getGraphics();
d.height);
grafBuff.setColor(getBa
grafBuff.fillRect(0, 0,
ckground());
grafBuff.setColor(
d.width, d.height);
Color.red);
grafBuff.drawRect(0, 0,
d.width-1, d.height-1);
grafBuff.setColor(
Color.blue);

Descargado de: http://technologycompartida.blogspot.com

Página 66
Descargado de: http://technologycompartida.blogspot.com

if (v.size() > 0) for (i=0;


i<v.size(); i++) {
Rectangle box =
grafBuff.drawRect(box.x, box.y,
cortarRect((Rectangle)v.elementAt(i
} box.width-1,
), d); box.height-1);
g.drawImage(imgBuff
} , 0, 0, this);

En negrita hemos indicado


Si
losno está creado todavía (grafBuff==null), creamos nuestro
agregados.
buffer
(de de Graphics),
clase dibujo. Para crear dicho
primero creamosbuffer
unagráfico
imagen que en este
canvas (d.width
caso tiene x d.height),
las mismas y luegoque
dimensiones asignamos
el a grafBuff el
contexto de dicha
getGraphics(). imagen mediante
Imagínense el método
que con createImage(...) crean una
"pantalla
una formavirtual",
de accedery getGraphics()
a esa nos da
Utilizando
pantalla como dicho contexto,
si fuera real. elegimos como color el mismo color
de fondo del
dibujamos unapplet (getBackground())
rectángulo y
lleno (fillRect(...)), borrando así
cualquier cosa que hubiera estado dibujada.
En itálica hemos indicado las modificaciones a nuestro método
anterior.
contexto Simplemente,
de la pantalla (el en parámetro
lugar de usar el método),
g del
Finalmente,
dibujamos sobrey para podercontexto-pantalla
nuestro visualizar nuestrovirtual.
dibujo, usamos el
pantalla real (g), quesobre
método drawImage copiaelnuestro
contexto contexto
de la imgBuff en las
coordenadas
también (0,0) sobre
referencia la pantalla.
al canvas (...this):Seelhace
cuarto parámetro
de drawImage esuna
ImageObserver, un objeto
interfacede que
clasesirve para que el objeto
asincrónicos
dentro del cual queseledibuja
indican cómo
reciba está siendo
mensajes
construida la imagen, y cuándo está lista.
Anim
ate!
Si bien puede ser un poco más complejo de entender que un
implementación es directa
dibujo directo sobre y no trae
la pantalla, ningún
notarán queproblema.
la Esta
animaci
misma aproximación puede utilizarse para crear
ones.
En este ejemplo, para manejar la ejecución cuadro a cuadro
preocupen por eso,
de la animación, lo veremos
usamos pronto.
Threads. No seÚnicamente tengan en
clase
cuentarunnable, y el applet
que nuestro thread debe
se encarga de ejecutar
implementar la el método run()
que
100 simplemente
milisegundosllama
entre a repaint() y espera
El trabajo
cuadro de cálculo y dibujo lo hace update(). Se los dejo para
y cuadro.
que lo estudien;
también usa doblenobuffering
es nada complicado y
(como el ejemplo anterior).
import
java.awt.*;
import
java.util.*;
import
java.applet.Appl
public class Ejemplo18 extends Applet
et;
implements Runnable {

Threadanima
dor;
ImageimgBu
ff; double
Graphicsgraf
ang
Buff;= 0.0;
public
void init() { resize(new
Dimension
} (200,200));
public void
start() { if (animador == null) animador
= new Thread(this);
animador.s
tart();
}

Descargado de: http://technologycompartida.blogspot.com

Página 67
Descargado de: http://technologycompartida.blogspot.com

public
void run() { while
(Thread.currentThread()
repaint ==
animador) {();
try
{ Thread.sleep
} (100);
catch
break
(InterruptedExceptio
}n e) { ;
}

}
public void
int g) {
update(Graphics
i;
int dx,
dy;
Dimension d
= size();
if (grafBuff
== null) { imgBuff =
createImage(d.width,
grafBuff =
} d.height);
imgBuff.getGraphics(
grafBuff.setColor(get );
Background());
grafBuff.fillRect(0, 0,
d.width, d.height);
grafBuff.setColor(
grafBuff.drawRect(0, 0,
Color.red);
d.width-1, d.height-1);
grafBuff.setColor(
dx = (int)(50 *
Color.blue);
Math.abs(Math.cos(ang)))
dy = (int)(50 *
;ang = ang
Math.abs(Math.sin(ang)))
; 0.1;
if
+
(ang>2*Math.PI)
grafBuff.drawRect(100-dx,
ang = 0.0;
100-dy, 2*dx, 2*dy);
g.drawImage(imgBuf
f, 0, 0, this);
}

Descargado de: http://technologycompartida.blogspot.com

Página 68
Descargado de: http://technologycompartida.blogspot.com

Java en
hebras
La clase anterior usamos, en el último ejemplo, un concepto al
los
que vamos a dedicar ahora nuestra atención:
threads.
La traducción literal de thread es hilo o hebra, y se utiliza
concepto
también parade threads
referirse enallos ambientes
hilo y sistemas
de un discurso. El operativos es un
poco complejo
entender: de explicar perodel
independientemente sencillo
sistemadeelegido, puede pensarse
que un thread
ejecución de unes algo así como el lugar de
En la mayoría de los programas que hemos visto, hemos usado
programa.
comienza y su ejecución
un solo thread; es decir que sigue
un un camino
programa
único:escomo
Java un monólogo.
multithreading. Esto significa algo así como que tiene
ejecutar
capacidad muchos threads
de diálogo, en paralelo,
y más como si tratáramos de
aún: puede
una conversación
No confundir aquímúltiple y simultánea.
multithreading con la capacidad de
ejecutar varios
posibilidad, programas
pero también un a lamismo
vez. Esta es una puede utilizar
programa
simultánea
varios threads ("caminos de ejecución"?)
Esto, por supuesto, depende fundamentalmente de la
mente.
capacidad del sistema
multithreading, y por estooperativo
Java nopara soportar
puede ejecutarse (al menos
soport
en forma completa) en sistemas que no lo
en.
El uso de threads nos permite, por ejemplo, ejecutar
simultáneamente
ellos; o, también, varios
que unprogramas
programa,que interactúen
mientras entre
por ejemplo
serie de cálculos
actualiza sin tener
la pantalla, que
simultáneamente realice una
Una
hacerforma
esperarsencilla de verlo es imaginar que tenemos un grupo
el usuario.
de microprocesadores
cada uno, un solo thread; queypueden
nosotrosejecutar,
asignamos programas (o
Además,
partes de podemos
programas) imaginar que esos
a cada uno microprocesadores
de ellos.
comparten
de una memoria
lo que surgirá una serie común y recursos
de problemas comunes, a
importantes
tener en cuenta cuando se usan threads.
Los pasos
básicos
Hay tres cosas a tener en cuenta para
usar •threads en unque
La clase programa:
queremos asignar a un thread debe
• Debemos crear
implementar la interface Runnable.
una variable (instancia) del tipo Thread,
que nos permitirán acceder
thread. En los applets, en y manejar
el métodoel start() simplemente
crearemos
pondremos a el thread (y, posiblemente, lo
• Y por último tenemos que crear un método run() que
ejecutar)
es elpropiamente
que ejecuta el código del programa
dicho.
La interface Runnable,
simplemente definida como:
public interface
java.lang.Runnable
{
//
public abstract
Methods
}void run();
le asegura al compilador que nuestra clase (la que utilizará el
Vamos a verejecutarse)
thread para un par de ejemplos,
dispone deprimero
métodounarun().
aplicación standalone y luego un applet.
Reunión de
amigos
El siguiente ejemplo (Ejemplo19.java) usa threads para activar
simultáneamente tres los
clase, que comparten objetos de ladel
recursos misma
procesador
peleándose para escribir a la pantalla.
class
Ejemplo19
{ public static void
main(String argv[])

Descargado de: http://technologycompartida.blogspot.com

Página 69
Descargado de: http://technologycompartida.blogspot.com

throws
InterruptedExcepti
Thread Juan = new Thread
on { Thread Luis = new Thread
(new Amigo("Juan"));
(new Amigo("Luis"));
Thread Nora = new Thread
Juan.star
(new Amigo("Nora"));
Luis.star
t();
t();
Nora.sta
rt();
Juan.joi
Luis.joi
n();
n();
Nora.joi
} n();

class Amigo
implements Runnable
{ String
mensaje;
public
Amigo(String
mensaje = "Hola, soy "+nombre+" y
}nombre) { este es mi mensaje ";

public void
run() { for (int i=1;
i<6; i++) { String msg =
mensaje+i;
System.out.print
} ln(msg);
}

Como siempre, compilarlo con javac Ejemplo19.java


En un sistema
y ejecutarlo conoperativo preemptivo, la
java Ejemplo19.
salida será más o menos así:
Hola, soy Juan y este
Hola, soy Juan1y este
es mi mensaje
es mi mensaje
Hola, soy Luis 2y este
es mi mensaje
Hola, soy Luis 1y este
Hola, soy Nora2y este
es mi mensaje
es mi mensaje
Hola, soy Nora1y este
Hola, soy Nora2y este
es mi mensaje
Hola, soy Juan3y este
es mi mensaje
es mi mensaje 3
...........
etc.
Qué significa que un sistema operativo es preemptivo? Casos
típicos una
utiliza son parte
Unix del
o Windows 95:procesador,
tiempo del cada tarea y luego lo libera
threads). Por eso ejecutarse
para que puedan se mezclanotras
los mensajes de salida. Si el sistema
tareas (otros
no se libera
operativo eshasta que no termina
no preemptivo, con el thread
el procesador
actual, y por lo tanto la salida sería así:
Hola, soy Juan y este
Hola, soy Juan1y este
es mi mensaje
Hola, soy Juan2y este
es mi mensaje
es mi mensaje
Hola, soy Juan3y este
Hola, soy Juan4y este
es mi mensaje
es mi mensaje 5

Descargado de: http://technologycompartida.blogspot.com

Página 70
Descargado de: http://technologycompartida.blogspot.com

Hola, soy Luis y este


es mi mensaje
Hola, soy Luis 1y este
...........
es mi mensaje 2
etc.
Si ustedes están utilizando un sistema operativo no preemptivo,
cúando puede ejecutarindicarle
deben explícitamente (dar paso) a otra tarea; para eso
al procesador
simplemente modifiquen el método run():
public void
run() { for (int i=1;
i<6; i++) { String msg =
System.out.print
mensaje+i;
Thread.yiel
ln(msg);
} d();
}

En este ejemplo, tanto en sistemas preemptivos


como no preemptivos la salida será:
Hola, soy Juan y este
es mi mensaje
Hola, soy Luis 1y este
es mi mensaje
Hola, soy Nora1y este
Hola, soy Juan1y este
es mi mensaje
Hola, soy Luis 2y este
es mi mensaje
es mi mensaje
Hola, soy Nora2y este
Hola, soy Juan2y este
es mi mensaje
es mi mensaje
Hola, soy Luis 3y este
es mi mensaje 3
...........
etc.
Esto es porque en seguida de imprimir estamos liberando al
procesador
alguno para queNoten
esperando). pase alaotro thread (si
diferencia conhay
el primer caso, sin
procesador
usar yield(),reparte su trabajo
para sistemas en forma (aparentemente)
preemptivos: el
impredecible, por eso elmáquina
el mismo en cualquier orden de los mensajes no será
oYasistema operativo.
lo vimos funcionar, pero sería bueno que lo
entendamos! Por eso, vamos paso a paso.
Creando
Threads
Thread es una clase básica en Java, que implementa la interface
por defecto.
Runnable Lo importante
y dispone de unosa cuantos
tener enmétodos
cuenta que, para usar
Threads, adebemos crearlas como instancias y
ponerlas
"andar":
Thread Juan = new Thread
(new Amigo("Juan"));
...........
...
Juan.star
...........
t();
Juan.joi
...
n();
Un thread tiene cuatro
estados
creado: posibles:
ha sido creado mediante new(), pero no
se ha puesto
activo: enejecución,
está en marcha todavía.
ya sea porque arrancó con
dormido: ha "despertado"
start() o fue sido suspendida consu ejecución
resume().
muerto: se ha detenido
momentáneamente definitivamente,
mediante ya sea
wait(), sleep() porque se terminó
o suspend().
En este ejemplo
el programa hemos creado
o mediante el llamado un thread asignándole
a stop().
simultáneamente yunseguidamente
Amigo("Juan")), objeto que loloutilizahemos(new
activado, llamando al
inicializar el thread
método start(). Este y, finalmente,
método llamardeal método
se encarga
run() que hemos implementado.

Descargado de: http://technologycompartida.blogspot.com

Página 71
Descargado de: http://technologycompartida.blogspot.com

De este modo, todo ocurre como si los métodos run() de


cada objeto se ejecutaran
concurrentemente. La formaen paralelo,
de manejar esto
El método
depende deljoin() queoperativo.
sistema llamamos al final hace que el programa
principal espere
"muerto" hastasuque
(finalizada este thread
ejecución). esté
Este método puede disparar la
lo hemos tenido
excepción en cuenta en el por lo que
InterruptedException,
En nuestro ejemplo,
encabezamiento de lasimplemente
clase. a cada instancia de Amigo(...)
que creamos
puesto a andar.la hemos
Corren ligado
todas en a un thread hasta
paralelo y que mueren de
muerte
acab natural, y también el programa principal
Cuando usamos Thread.yield() (que en rigor debería ser
a.
Thread.currentThread().yield(),
uso muy común los desarrolladores perodesiendo algo
Java lo handesimplificado),
procesador
simplementededicarse
el threadaactual
otro (si
le es que hay
permite al alguno
La clase Amigo()
deseando es muy
utilizar sus simple y con lo que hemos visto hasta
servicios).
ahora no creo que tengamos que explicar
nada
más.
Y los
applets...?
También podemos usar estos conceptos en los applets. Veamos un
ejemploalpara
similar terminar
anterior, la clase
donde de hoy, muy
tres contadores cuentan (en un sistema
preemptivo)
crear en forma simultánea. Recuerden
una página
HTML con el tag
<applet code="Ejemplo20.class"
width=300
para height=100></applet>
poder verlo en acción con el appletviewer o su browser
;-)
favorito (que desde ya supongo que soporta Java!
El programa es extremandamente sencillo, y pueden verlo en
acción
págin si lo desean cargando via Internet la
http://www.amarillas.com/rock/ja
a:
va/Ejemplo20.htm
// Ejemplo de applet
import
que usa multithreading
java.awt.*;
import
java.applet.*;
public class Ejemplo20
extends Applet {
TextField
tfa,tfb,tfc;
public void
init() { setLayout(new
tfa = new
GridLayout(3,2));
tfb = new
TextField("0");
TextField("0");
tfc = new
add(new
TextField("0");
Label("Contador
add(tf
A"));
a);
add(new
add(tf
Label("Contador
add(new
b);
B"));
Label("Contador
add(tf
} B"));
c);

public void
start() { Thread A = new Thread
Thread B = new Thread
(new Counter(tfa));
(new Counter(tfb));
Thread C = new Thread
A.start
(new Counter(tfc));
();
B.start
();

Descargado de: http://technologycompartida.blogspot.com

Página 72
Descargado de: http://technologycompartida.blogspot.com

C.start
} ();

class Counter
implements Runnable
{ TextField
String
texto;
s;
public
texto =
Counter(TextField
}txtf) { txtf;

public void
run() { for (int i=0;
i<1000; i++)texto.setText(s.va
{
} lueOf(i));
}

Descargado de: http://technologycompartida.blogspot.com

Página 73
Descargado de: http://technologycompartida.blogspot.com

La liebre y la tortuga (y
el guepardo)
Java dispone de un mecanismo de prioridades para los threads, de
amodo
un thread que asignar
de poder a otro. Típicamente se CPU
más tiempo de asigna una prioridad de 1
asetPriority,
10 (10 es la mayor
como prioridad) mediante
en el
ejemplo que sigue:
public class
Ejemplo21 {
static
static
Animaltortuga;
static
Animalliebre;
Animalguepardo;
public static void
throws argv[])
main(String
InterruptedException
{ tortuga = new
liebre
Animal(2, = new
"T");
Animal(3,="L");
guepardo new
Animal(4, "G");
tortuga.st
liebre.sta
art();
rt();
guepardo.s
tortuga.jo
tart();
liebre.joi
in();
n();
guepardo.j
oin();
}

class Animal
String
extends Thread {
nombre;
public Animal(int prioridad,
this.nombre
String nombre) { =
nombre;
setPriority(pri
} oridad);

public void
run() { for (int x = 0; x <
30; x++) { System.out.print(
nombre );
yield(
} );
System.out.println("\nLle
} ga "+nombre );
}

La salida de este programa, ejecutado con


java Ejemplo21, es por ejemplo:
C:\java\curso>java
Ejemplo21
GGGGGGGGGGGGGGGGGG
GGGGGGGGGGGG
Llega
LTLLLLLLLLLLLLLLLLL
G
Llega
LLLLLLLLLLLL
L
TTTTTTTTTTTTTTTTTT
Llega
TTTTTTTTTTT
T
Descargado de: http://technologycompartida.blogspot.com

Página 74
Descargado de: http://technologycompartida.blogspot.com

Como se ve, a pesar de haber arrancado antes la tortuga, casi


Guepardo, luego
todo el tiempo delaCPU
Liebre (aunque
lo usa algoelqueda para la pobre
primero
tortuga, como
finalmente paraselaveTortuga.
en la T marcada),
No todas las y corridas ni todos los
de la carga
sistemas dandeligual
procesador y de
salida, ya quelaésta depende
implementación
Este de Java particular.
programa simplemente crea tres animales (clase Animal),
ejemplo
asigna unestá hecho
thread en base
a cada uno ayuno del libroEste
los ejecuta.
"Programación Java" de Macary y Nicolas.
Sincronicemos
losproblema
Un relojes
básico del multithreading es cuando varios
programas
los mismos(o, para¿cómo
datos: el caso,sabemos
varios threads)
si uno deacceden
ellos noa los
modificaun
Veamos mientras
ejemplo,losdonde
está usando otro?.que varios
suponemos
threads usan la variable valorImportante:
if
(valorImportante
..... algo se procesa
>0){ valorImportante
acá ........ =
valorImportante - 1;
.....
} sigue...............
......
¿Cómo nos aseguramos que valorImportante no cambió entre el if
y la líneamodificado
haberlo resaltada? mientras
Otros threadstanto.pueden
Asimismo, puede suceder
porción
que dos de código,
threads y se
estén pierda unolade
ejecutando los
misma
decrementos. Imaginen algo así:
(antes)
(thread 1) lee valo
rImportante
(thread 2) lee= 10= 10
valorImportante
(thread 1) 10
valorImportante = 10
-1 = 9 2) 10
(thread
-1 = 9 2) asigna 9 a
(thread
(thread 1) asigna 9 a
valorImportante
valorImportante
(después)
Como vemos, a pesar de haber
valorImportante = 9restado dos veces, hemos perdido
de
unaladeresta es lo mismo,
las restas. Aunque porque
usemos el código
-= en vez igualmente se
resuelve en varios pasos (varias operaciones
atómic
as).
Para evitar esto, Java nos brinda la palabra clave Synchronized,
los
quethreads
bloqueamenos el que
el acceso a una variable a todos
lo está usando.
Vamos a ver un caso específico; se trata de dos contadores que
una
usancantidad
el mismoa.sumador
Supuestamente
para sumar entredelosa dos
uno deben
llevar el sumador (a) hasta 20000.
// Archivo Ejemplo22.java, compilar con javac
Ejemplo22.java, ejecutar con java Ejemplo22
public class
Ejemplo22 {public static void
main(String Sumador
argv[]) { A = new
Contador
Sumador(); C1 = new Contador(A); //
dos threads
Contador C2que lo usan...
= new
//
Contador(A);
un
C1.star único sumador
C2.star
t();
// ...para sumar
t();
try
{ C1.join
C2.join
();
} ();
catch
(Exception e)
{
Descargado de: http://technologycompartida.blogspot.com

Página 75
Descargado de: http://technologycompartida.blogspot.com

System.out.pri
} ntln(e);
}
}

class Contador
extends Thread {
Sumado
r s;
Contador (Sumador
sumador) { s = sumador; // le
} asigno un sumador a usar

public void
run() { s.sumar(); //
} ejecuto la suma
}

class
Sumador int a =
{ 0;
public void
sumar() { for (int i=0;
i<10000; i++if )( {(i % 5000) == 0 ) { // "%"
da el resto de la división:
System.out.println(a); //
} imprimo cada 5000
a +=
} 1;
System.out.println(a);
}
} // imprimo el final

Ejecutando esto nos da más o menos así (cada corrida es


threads y la
diferente, carga
dependiendo de cómo se "chocan" los
de la CPU):
C:\java\curso>java
Ejemplo22
0
87
892
6104
141
34
59
178
55
Esto se debe justamente a lo que explicábamos al principio: a
veces los dos threads
simultáneamente, conintentan ejecutar a += 1
lo que algunos
Podemos solucionar esto
incrementos se pierden.
modificando el método run():
public void
run() { synchronize
d (s) { s.sumar
} ();
}

Descargado de: http://technologycompartida.blogspot.com

Página 76
Descargado de: http://technologycompartida.blogspot.com

Con esto, sólo a uno de los dos threads se les permite ejecutar
s.sumar() por
supuesto, vez,thread
el otro y se evita
queda elesperando,
problema. Por
por lo que más vale no
el programa
utilizar se puede
esto con métodosponer muy largos ya que
lento
La o aún bloquearse.
salida
ahora será:
C:\java\curso>java
Ejemplo22
0
5000
<
10000
< primer thread
10000
<
15000
20000
(
( segundo thread
(Lo mismo logramos (y en forma más correcta) declarando
como synchronized al método sumar():
public synchronized void
Esto es mejor porque{ la
sumar() clase que llama a sumar() no necesita
.............
saber
de que al
llamar tiene que sincronizar
método, el objeto
y si otros objetos (enantes
otros threads) lo
llaman, no necesitamos preocuparnos.
Más
sincronizaci
Otra manera de sincronizar el acceso de los threads a los
métodos, es lograr que
entre sí, esperando uno éstos
hasta se pongan
que de acuerdo
otro realizó alguna tarea
ón ParaCuando
notify().
dada. esto seun thread
usan llama a wait()
los métodos wait()en
y un método de un
objeto llame
thread dado, aqueda detenido
notify() hasta que otro
en algún
método
Por del mismo
ejemplo, vamosobjeto.
a suponer cuatro empleados que se
de que éste con
encuentran los su jefe y lo saludan, pero sólo luego
salude primero.
public class
Ejemplo23 {
public static void
main(String Saludo
argv[]) hola
{ = new
Personal pablo = new
Saludo();
Personal luis = "Pablo",
Personal(hola, new false);
Personal(hola,
Personal andrea"Luis",
= new false);
Personal(hola,
Personal pedro "Andrea",
= new false);
Personal jefe ="Pedro",
Personal(hola, new false);
Personal(hola, "JEFE", true);
pablo.sta
luis.star
rt();
andrea.sta
t();
rt();
pedro.sta
rt();
jefe.star
try
t();
{ pablo.joi
luis.join
n();
andrea.joi
();
n();
pedro.joi
n();
jefe.join
} ();
catch
(Exception e) System.out.pri
}{ ntln(e);
}
}

Descargado de: http://technologycompartida.blogspot.com

Página 77
Descargado de: http://technologycompartida.blogspot.com

class
Saludo { synchronized void
try
esperarJefe(String empleado) {
{ wait(
);
System.out.println(empleado+">
} Buenos dias jefe!");
catch
(InterruptedExceptio
System.out.println(e.
n e) { toString());
}
}

synchronized void
saludoJefe()System.out.println("JEFE>
{
notifyAl
Buenos dias!");
} l();
}

class Personal
String
extends Thread {
Saludo
nombre;
saludo;
boolean
esJefe;
Personal (Saludo s, String
n, boolean j)nombre
{
saludo
= n; =
esJefe
s;
} = j;

public void
run() { System.out.println("("+no
if
mbre+" llega)");
(esJefe) saludo.saludo
else Jefe();
saludo.esperarJefe
} (nombre);
}

Usé notifyAll() en lugar de notify(), porque en el segundo caso


sólo se notificaría
empleado al yprimer
en llegar) thread
no a los (el primer
demás,
que se se
Como quedarían
ve en la en el wait().
salida, a pesar de que los empleados están en
condiciones
no llega el de saludar, no lo hacen hasta que
jefe:
C:\java\curso>java
(Pablo
Ejemplo23
llega)
(Luis
llega)
(Andrea
(Pedro
llega)
llega)
(JEFE
JEFE>
llega)
Luis>
BuenosBuenos
dias!
dias jefe!

Descargado de: http://technologycompartida.blogspot.com

Página 78
Descargado de: http://technologycompartida.blogspot.com

Pedro> Buenos
dias jefe! Buenos
Andrea>
Pablo> Buenos
dias jefe!
dias jefe!
Aquí hice trampa: a veces, el jefe llega y saluda antes que alguno
se
de queda esperandopor
los empleados, indefinidamente. Prueben de modificar las
lo que ese empleado
clases para que
estén todos los el jefe no salude hasta que no
empleados presentes...

Descargado de: http://technologycompartida.blogspot.com

Página 79
Descargado de: http://technologycompartida.blogspot.com

Capítulo XV -
propu
Solución al problema
esto
En forma muy sencilla, modificando sólo la clase Personal,
llegue
podemosantes que un el problema de que el jefe
solucionar
empleado:
class Personal
...........
extends Thread {
static int
.....
llegaron = 0;
...........
.....
public void
run() { System.out.println("("+no
if
mbre+" llega)");
(esJefe) while (llegaron
{ < 4) { System.out.println("(Espe
} rando...)");
saludo.saludo
} Jefe();
else
{ synchronized(
this) { llegaron+
} +;
saludo.esperarJefe
} (nombre);
}
}

Preparamos una variable static (de clase) para contar todos


incrementamos
los empleados que justo antes de
pasaron porejecutar
aquí; lasaludo.esperarJefe
(sincronizando
que no pasen loselproblemas
thread en el incremento para
que
En el caso
vimos en eldel jefe, simplemente espera que el contador llegue
capítulo).
a 4. Podríamos
pasando modificar
la cantidad esto un poco,
de empleados como
parámetro podemos
Inclusive, para que seausarmás
dosflexible.
constructores distintos (uno para
último caso pasamos
los empleados la cantidad
y otro para el jefe,de empleados
y en este a esperar).
Les dejo el ejemplo para que lo estudien.
public class
Ejemplo23 {
public static void
main(String Saludo
argv[]) hola
{ = new
Saludo();
Personal jefe = new
Personal pablo "JEFE",
Personal(hola, = new 3);
Personal luis = "Pablo");
Personal(hola, new
Personal(hola,
Personal andrea"Luis");
= new
Personal(hola,
jefe.star "Andrea");
pablo.sta
t();
rt();
luis.star
andrea.sta
t();
try
rt();
{ pablo.joi
n();
luis.join
();

Descargado de: http://technologycompartida.blogspot.com

Página 80
Descargado de: http://technologycompartida.blogspot.com

andrea.joi
n();
jefe.join
} ();
catch
System.out.pri
(Exception e)
}{ ntln(e);
}
}

class
Saludo { synchronized void
esperarJefe(String
try empleado) {
{ wait(
System.out.println(empleado+">
);
} Buenos dias jefe!");
catch
System.out.println(e.
(InterruptedExceptio
n e) { toString());
}
}

synchronized void
saludoJefe()System.out.println("JEFE>
{
Buenos dias!");
notifyAl
} l();
}

class Personal
extends Thread {
String
nombre;
Saludo
boolean
saludo;
esJefe;
static int
int
llegaron = 0;
numEmp
;Personal (Saludo s,
String n) { esJefe =
nombre
false;
= n; =
saludo
} s;

Personal (Saludo s,
String n, int esJefe
x) { =
nombre
true;
= n; =
saludo
numEmp
s;
} = x;

public void
run() { System.out.println("("+no
mbre+" llega)");
if
(esJefe) while (llegaron < numEmp) {
{ saludo.saludo
System.out.println("(Esperando...)"); }
Jefe();

Descargado de: http://technologycompartida.blogspot.com

Página 81
Descargado de: http://technologycompartida.blogspot.com

}
else
{ synchronized(this) {
llegaron++; }
saludo.esperarJefe
} (nombre);
}
}

Descargado de: http://technologycompartida.blogspot.com

Página 82
Descargado de: http://technologycompartida.blogspot.com

Multim
edia!
Java permite cargar y visualizar archivos GIF o JPEG de imagen y
8000Hz de (solamente en mono, 8 bits,
AU de audio
muestreo).
Para el caso del sonido, un archivo de audio se carga mediante un
método
objeto degetAudioClip(URL,
la clase AudioClip,archivo),
medianteseelejecuta con los
métodos
Noten play()
esto! o loop()
Si bien y seque
dijimos detiene con stop().
un applet no puede acceder al
disco de la
archivos delmáquina cliente,
server desde SI puede
donde leer Por lo tanto, pasándole
se cargó.
el applet,
URL depodemosla máquina leerdesde
cualquier
donde tipo
se de
cargó
La
archivoformaa través
más segura
de la de
red.indicar dicho URL es mediante el método
getDocumentBase(),
adecua que nos da el URL
Por ejemplo, puedo cargar y reproducir
do.
audio con sólo dos líneas:
......
AudioClip sonido = getAudioClip(
..
sonido.pl
getDocumentBase(), "sonido.au" );
ay();
.......
..
Por otra parte, una foto puede cargarse mediante un
getImage(URL,
objeto de clase Image archivo). Luegoellamétodo
mediante mostramos en un objeto
dibujo)
Graphicsmediante drawImage(imagen,
correspondiente al applet (o alx, área
y, observador).
de
Observador
interface es un objeto que
ImageObserver; los implementa
applets, por ladescender de
Component
la implementan. (queTípicamente,
implementa dicha interface)
la imagen también
se visualiza
en el método paint(...) del applet:
.........
....
algunMetod
.......
o(...) {
Image imagen =
...
getImage(getDocumentBase(),
.......
}"imagen.gif");
...
........
... public void
paint(Graphics g.drawImage(imagen,
g) { xOffset, yOffset,
} this);
..........
..... // "this" representa al applet
El problema con las imágenes es asegurarse que fue cargada
antes de mostrarla.
MediaTracker Para debería
(también eso se utiliza
servir un
para los archivos de
implemen
audio, pero en esta versión aún no está
Mediante addImage( imagen, grupo) se agrega una imagen a la
tado).
lista del
para MediaTracker,
esperar y hay(como
que sea cargada métodos waitForAll() o
waitForID(grupo)),
correctamente (comopara verificar que se haya cargado
checkAll(),
checkID(grupo),
El siguiente applet isErrorAny()...), etcétera.para cargar una
utiliza estos conceptos
imagen y un archivo de audio y mostrarlos:
//
import Ejem
import
java.awt.*;
plo24.java
java.applet.*;
public class Ejemplo24
extends Applet {
MediaTrackersupervis
StringarchImagen, archAudio;
or;
Imageimagen;

Descargado de: http://technologycompartida.blogspot.com

Página 83
Descargado de: http://technologycompartida.blogspot.com

AudioClipa
udio;
Labeltitulo;
Panelcuadro;

public void
init() { supervisor = new
MediaTracker(this);
archImagen =
"javacero.gif";
archAudio =
"tada.au";
// carga
imagen =
supervisor.addImage
getImage(getDocumentBase(),
(imagen,0);
archImagen);
try
{ supervisor.waitForID(0);
se
cargue } // espero que
catch
System.out.println("Error
(InterruptedExceptio
}n e) { cargando imagen!");
showStatus("Imagen
cargada");
// carga
audio =
sonido
getAudioClip(getDocumentBase(),
// arma
archAudio);
layout
setLayout(new
titulo = new
BorderLayout());
Label(archImagen);
setFont(new Font("helvetica",
add("South",
Font.BOLD, 18));
} titulo);

public void
start() { repaint
();
audio.pla
} y();

public void
paint(Graphics
if g) {
g.setColor(Colo
(supervisor.isError
Any()) { r.black);
g.fillRect(0, 0,
return
size().width, size().height);
} ;
g.drawImage(imagen
} , 0, 0, this);
}

Para visualizarlo, como siempre,


creamos un HTML:
<HTM
L>
<HEA
<TITLE>Ejemplo 24 - Ejemplo
D>
Multimedia</TITLE>
</HEA
<BOD
D>
Y>

Descargado de: http://technologycompartida.blogspot.com

Página 84
Descargado de: http://technologycompartida.blogspot.com

<applet code="Ejemplo24.class"
width=150 height=200>
</appl
</BOD
et>
Y>
</HT
ML>

Parametrizando
un applet
Vamos a aprovechar este ejemplo, modificándolo un poco para
cargar,
indicarlemediante
desde elparámetros.
HTML qué Nuestro
archivos debe
HTML modificado será:
<HTM
L>
<HEA
<TITLE>Ejemplo 24 -
D>
</HEA
Multimedia</TITLE>
D>
<BOD
Y>
<applet code="Ejemplo24.class"
width=150
<param height=200>
name="imagen"
<param name="sonido"
value="javacero.gif">
</appl
value="tada.au">
et>
</BOD
Y>
</HT
ML>
Para leer estos parámetros desde el applet, usamos el método
getParameter(nombreParámetro),
podemos modificar nuestro appletasí que
simplemente
modificando un par de líneas:
archImagen =
getParameter("imagen");
archAudio =
getParameter("sonido");
Voilá! Pueden probar de cargar este applet en
De esta manera podemos pasar cualquier valor como parámetro
http://www.amarillas.com/rock/java/Ejemplo24.htm.
Y esto
para unesapplet,
todo haciéndolo más flexible.
por hoy!
Con esto hemos visto una gran parte de lo que es Java. No
hemos
pero profundizado
hemos demasiado
hecho ejemplos que en cada punto,
Sin embargo,
funcionan parahemos dejado
ilustrar cada un punto importante y muy fuerte de
cosa.
Java, que es el
aplicaciones y, de las comunicaciones
especialmente, entre
el uso de sockets y la
programación de aplicaciones cliente-servidor.

Descargado de: http://technologycompartida.blogspot.com

Página 85
Descargado de: http://technologycompartida.blogspot.com

Paseando por
la Red
Es muy sencillo acceder a archivos en la red utilizando Java. El
interfases
paquete a
java.net dispone de varias clases e
tal
En efecto.
primer lugar, la clase URL nos permite definir un recurso
en la red de varias maneras, por ejemplo:
URL url1 = new URL
URL url2 = new URL ("http",
("http://www.rockar.com.ar/index.html
"www.rockar.com.ar",
"); "sbits.htm");

Por otra parte, podemos establecer una conexión a un


URL dado mediante openConnection:
URLConnection conexion =
url.openConnection();
Una vez lograda la conexión, podemos leer y escribir datos
el caso de manejo
utilizando streams de archivos de
(corrientes comunes
datos), (ver
comocapítulo
en X). Un
llegan a través de nos
DataInputStream la red, y un DataOutputStream
permite leer datos que
nos permite enviar datos al host.
Por
ejemplo:
DataInputStream datos = new
DataInputStream( corrienteEntrada );

En nuestro caso, la corriente de entrada de datos


getInputStream() del objeto
proviene de la conexión al URL. El método
URLConnection nos provee tal corriente:
DataInputStream datos = new
DataInputStream(conex.getInputStream())

De este modo podemos escribir un pequeño programa para, por


ejemplo, leer
dirección una página
arbitraria HTMLEldesde
de internet. una luego de compilarse
programa,
con java Ejemplo25
mediante <url>; por ejemplo:
javac Ejemplo25.java, se ejecutajava Ejemplo25
http://www.rockar.com.ar/index.html.
import
import
java.io.*;
java.net.*;
public class
Ejemplo25 {
public static void
main(String argv[]) {
try
String
{s; URL url = new
URL (argv[0]); conex =
URLConnection
System.out.println("Carga
url.openConnection();
ndo "+argv[0]); datos = new
DataInputStream
do {
DataInputStream(conex.getInputStream());
s=
datos.readLin
if (s != null)
e();
} while (s !=System.out.println(s);
} null);
catch
System.out.println("Sintaxis: java
(ArrayIndexOutOfBoundsExc
} e) { Ejemplo25 <url>");
eption
catch
(UnknownHostExcepti
on e) {
Descargado de: http://technologycompartida.blogspot.com

Página 86
Descargado de: http://technologycompartida.blogspot.com

System.out.println("El host no
} existe o no responde");
catch
(Exception e)
e.printStack
{} Trace();
}
}

Este programa muestra el HTML como texto en la pantalla,


pero podríamos
guardarlo. grabarlo
Inclusive, a un archivo
podríamos para a medida que lo
procesarlo
guardarlos en un vector,
recibimos, identificar losytags
seguidamente conectarnos y bajar los
<A HREF=url>,
bajar un site
links que figuran en la página original hasta
completo.
Noten que esto no sólo sirve para establecer conexiones a
páginas HTML.
referirse tambiénEn realidad,
a otros un URLcomo
protocolos, puedegopher, ftp, etcétera;
puede
si bienhaber
segúnproblemas para conectarse
la implementación de Java
aPara
algunos tipos
ver los dede
tipos URL.
URL posibles les
recomiendo leer la página:
http://www.ncsa.uiuc.edu/demo
web/url-primer.html

Los
Sockets
Los sockets (zócalos, referido a los enchufes de conexión de
cables) sonamecanismos
programas través de una dered
comunicación
TCP/IP. De entre
hecho, al establecer
sockets: los sockets
una conexión realizan
via Internet la interfase
estamos entre la
utilizando
Dichos mecanismos
aplicación pueden
y el protocolo tener lugar dentro de la misma
TCP/IP.
máquina o a través
cliente-servidor: de unaunred.
cuando Se usan
cliente y unen forma establecen una
servidor
conexión, lo para
proporciona hacenesto
a través de un socket. Java
las clases
ServerSocket
Los y Socket.
sockets tienen asociado un port (puerto). En general, las
puerto particular
conexiones (por ejemplo,
via internet pueden en establecer un
se especifica porque ya hay definidos puertos
http://www.rockar.com.ar:80/index.html por defecto
el puerto para
es el 80). Esto
distintos
casi 79
ftp, nunca protocolos:
para 20Algunos
finger, etc. para ftp-data, 21pueden
servers para definir otros
disponibles para establecer
puertos, e inclusive pueden utilizarse puertos
conexiones especiales.
Justamente, una de las formas de crear un objeto de la clase
URL permite especificar también el puerto:
URL url3 = new URL ("http",
"www.rockar.com.ar", 80,"sbits.htm");

Para establecer una conexión a través de un socket, tenemos que


programar por un lado el servidor y por otro
los
En el servidor, creamos un objeto de la clase ServerSocket y
clientes.
Socket) mediantealgún
luego esperamos el cliente (de clase
método accept():
ServerSocket conexion = new
ServerSocket(5000);
Socket cliente =
conexion.accept();
// 5000elespunto
Desde el puerto en este
de vista del caso
cliente, necesitamos un Socket al que
número
// espero
le de
indiquemos
al cliente
la dirección del servidor y el
puerto a usar:
Socket conexion = new Socket
( direccion, 5000 );

Descargado de: http://technologycompartida.blogspot.com

Página 87
Descargado de: http://technologycompartida.blogspot.com

Una vez establecida la conexión, podemos intercambiar datos


Como
usandolastreams
clase URLConnection,
como en el ejemplola clase Socket dispone de
anterior.
métodos
que getInputStream
nos dan y getOutputStream
respectivamente un InputStream y un OutputStream a
través de los cuales transferir los datos.
Un servidor
atento
Vamos a crear un servidor Ejemplo26a.java (que podemos correr
en una
de ventana)
la misma que atenderá
máquina (lo vamosa un clienteen otra ventana). Para
a correr
hacerlo simple,
mensaje el servidor
al cliente sólo le enviará
y éste terminará un El servidor
la conexión.
quedará
Es entonces
importante disponible
notar que, parapara
queotro cliente.
el socket funcione, los servicios
programas
TCP/IP deben corran
estarenactivos
la misma máquina).
(aunque ambos Los usuarios de
TCP/IP
Windows activa, ya sea que
asegúrense a unahaya una conexión
redservidor
El local o acorrerá
Internet."para siempre", así que para
detenerlo presionen control-C.
//
servido
import
r
import
java.io.*;
java.net.*;
public class
Ejemplo26a {
public static void
main(String argv[]) {
ServerSocketservido
r;intnumCliente = 0;
Socketclient
e;try
{ servidor = new
ServerSocket(5000);
do {

cliente =
numClient
System.out.println("Llega el
servidor.accept();
e++;
cliente "+numCliente);
PrintStream ps = new
ps.println("Usted es mi
PrintStream(cliente.getOutputStream())
cliente
; "+numCliente);
}cliente.clos
while
} e();
(true);
catch
(Exception e)
e.printStack
{} Trace();
}
}

Utilizamos un PrintStream para enviar los datos al cliente, ya que


El método PrintStream.println
es sencillo maneja
de utilizar para mandar los datos como
Strings.
System.out.println,
stream simplemente
a través del cual hay
mandarlos al que indicarle
crearlo el caso, el
(en este
cliente.getOutputSt
OutputStream del cliente, que obtenemos con
ream()).
El cliente
satisfecho
Ahora vamos a crear la clase cliente, Ejemplo26b.java. El cliente
través de un DataInputStream
simplemente (mediante
establece la conexión, lee a el método readLine())
lo que el servidor le manda, lo muestra y
cort
a.
//
import
cliente
import
java.io.*;
:
java.net.*;

Descargado de: http://technologycompartida.blogspot.com

Página 88
Descargado de: http://technologycompartida.blogspot.com

Descargado de: http://technologycompartida.blogspot.com


Descargado de: http://technologycompartida.blogspot.com

public class
Ejemplo26b {
public static void
main(String argv[]) {
InetAddressdireccion
intnumCliente = 0;
;Socketservid
or;
try
{ direccion =
servidor = new
InetAddress.getLocalHost();
Socket(direccion, 5000);
DataInputStrea
// direccion
m new
datos = local
System.out.println(
DataInputStream(servidor.getIn
datos.readLine()
servidor.cl );
putStream());
} ose();
catch
(Exception e)
e.printStack
{} Trace();
}
}

Para probar esto, asegúrense que los servicios TCP/IP estén


yactivos,
corrancorran
varias java
vecesEjemplo26a
java Ejemplo26b
en unaen otra. Las
ventana
salidas serán más o menos así:
Ventana
servidor:
C:\java\curso>java
Llega el
Ejemplo26a
clienteel1
Llega
Llega
clienteel2
cliente 3 (----- cortar con
control-C -----)
Ventana
cliente:
C:\java\curso>java
Ejemplo26b
Usted es mi
cliente 1
C:\java\curso>java
Ejemplo26b
Usted es mi
cliente 2
C:\java\curso>java
Ejemplo26b
Usted es mi
cliente 3
(----- aquí cerramos el
servidor -----)
C:\java\curso>java
java.net.SocketExcep
Ejemplo26b
tion: at
connect
at
java.net.PlainSocketImpl.doConnect(PlainS
java.net.PlainSocketImpl.connectToAddress(Pla
ocketImpl.java:223)
at
inSocketImpl.java:128)
java.net.PlainSocketImpl.connect(PlainSo
at
cketImpl.java:115)
at
java.net.Socket.<init>(Socke
at
java.net.Socket.<init>(Socke
t.java:125)
Ejemplo26b.main(Ejemplo2
t.java:101)
6b.java:12)

Descargado de: http://technologycompartida.blogspot.com

Página 89
Descargado de: http://technologycompartida.blogspot.com

Esto es todo por ahora. El ejemplo fue lo más sencillo posible,


peroclientes
los mediante el mismo
pueden método el
intercambiar servidor
datos y
escribiendo en ambas
en una máquina
direcciones. y los clientes
Inclusive, en otras;
el servidor puedeademás,
correr si bien en este
caso utilizamos
pueden utilizar aplicaciones standalone, se
Por ejemplo, una aplicación servidora puede correr
applets.
buscar datos en una
constantemente en unbase de datos)
server y diferentes
de Internet clientespara
(por ejemplo, en
distintas máquinas,aposioblemente applets Java,
pueden conectarse
ella y consultarla.

Descargado de: http://technologycompartida.blogspot.com

Página 90