Java
Java
Java
1. INTRODUCCIÓN A JAVA
Los lenguajes al uso, como C o C++, deben ser compilados para un chip, y si se
cambia el chip, todo el software debe compilarse de nuevo. Esto encarece mucho
los desarrollos y el problema es especialmente acusado en el campo de la
electrónica de consumo. La aparición de un chip más barato y, generalmente,
más eficiente, conduce inmediatamente a los fabricantes a incluirlo en las nuevas
1
Tutorial de Java
series de sus cadenas de producción, por pequeña que sea la diferencia en precio
ya que,
multiplicada por la tirada masiva de los aparatos, supone un ahorro considerable.
Por tanto, Gosling decidió mejorar las características de Oak y utilizarlo.
Una vez que en Sun se dieron cuenta de que a corto plazo la televisión interactiva
no iba a ser un gran éxito, urgieron a FirstPerson a desarrollar con rapidez nuevas
estrategias que produjeran beneficios. No lo consiguieron y FirstPerson cerró en
la primavera de 1994.
Pese a lo que parecía ya un olvido definitivo, Bill Joy, cofundador de Sun y uno de
los desarrolladores principales del Unix de Berkeley, juzgó que Internet podría
llegar a ser el campo de juego adecuado para disputar a Microsoft su primacía
casi absoluta en el terreno del software, y vio en Oak el instrumento idóneo para
llevar a cabo estos planes. Tras un cambio de nombre y modificaciones de
diseño, el lenguaje Java fue presentado en sociedad en agosto de 1995.
Lo mejor será hacer caso omiso de las historias que pretenden dar carta de
naturaleza a la clarividencia industrial de sus protagonistas; porque la cuestión es
si independientemente de su origen y entorno comercial, Java ofrece soluciones a
nuestras expectativas. Porque tampoco vamos a desechar la penicilina aunque
haya sido su origen fruto de la casualidad.
Simple
Java ofrece toda la funcionalidad de un lenguaje potente, pero sin las
características menos usadas y más confusas de éstos. C++ es un lenguaje que
adolece de falta de seguridad, pero C y C++ son lenguajes más difundidos, por
2
Tutorial de Java
ello Java se diseñó para ser parecido a C++ y así facilitar un rápido y fácil
aprendizaje.
Java elimina muchas de las características de otros lenguajes como C++, para
mantener reducidas las especificaciones del lenguaje y añadir características muy
útiles como el garbage collector (reciclador de memoria dinámica). No es
necesario preocuparse de liberar memoria, el reciclador se encarga de ello y
como es un thread de baja prioridad, cuando entra en acción, permite liberar
bloques de memoria muy grandes, lo que reduce la fragmentación de la memoria.
Java reduce en un 50% los errores más comunes de programación con lenguajes
como C y C++ al eliminar muchas de las características de éstos, entre las que
destacan:
aritmética de punteros
no existen referencias
registros (struct)
definición de tipos (typedef)
macros (#define)
necesidad de liberar memoria (free)
Orientado a objetos
Java implementa la tecnología básica de C++ con algunas mejoras y elimina
algunas cosas para mantener el objetivo de la simplicidad del lenguaje. Java
trabaja con sus datos como objetos y con interfaces a esos objetos. Soporta las
tres características propias del paradigma de la orientación a objetos:
encapsulación, herencia y polimorfismo. Las plantillas de objetos son llamadas,
como en C++, clases y sus copias, instancias. Estas instancias, como en C++,
necesitan ser construidas y destruidas en espacios de memoria.
Distribuido
Java se ha construido con extensas capacidades de interconexión TCP/IP.
Existen librerías de rutinas para acceder e interactuar con protocolos como http y
3
Tutorial de Java
Robusto
Java realiza verificaciones en busca de problemas tanto en tiempo de compilación
como en tiempo de ejecución. La comprobación de tipos en Java ayuda a detectar
errores, lo antes posible, en el ciclo de desarrollo. Java obliga a la declaración
explícita de métodos, reduciendo así las posibilidades de error. Maneja la
memoria para eliminar las preocupaciones por parte del programador de la
liberación o corrupción de memoria.
Comprobación de punteros
Comprobación de límites de arrays
Excepciones
Verificación de byte-codes
Arquitectura neutral
Para establecer Java como parte integral de la red, el
compilador Java compila su código a un fichero objeto de formato independiente
de la arquitectura de la máquina en que se ejecutará. Cualquier máquina que
tenga el sistema de ejecución (run-time) puede ejecutar ese código objeto, sin
importar en modo alguno la máquina en que ha sido generado. Actualmente
existen sistemas run-time para Solaris 2.x, SunOs 4.1.x, Windows 95, Windows
NT, Linux, Irix, Aix, Mac, Apple y probablemente haya grupos de desarrollo
trabajando en el porting a otras plataformas.
4
Tutorial de Java
5
Tutorial de Java
Seguro
La seguridad en Java tiene dos facetas. En el lenguaje, características como los
punteros o el casting implícito que hacen los compiladores de C y C++ se eliminan
para prevenir el acceso ilegal a la memoria. Cuando se usa Java para crear un
navegador, se combinan las características del lenguaje con protecciones de
sentido común aplicadas al propio navegador.
El lenguaje C, por ejemplo, tiene lagunas de seguridad importantes, como son los
errores de alineación. Los programadores de C utilizan punteros en conjunción
con operaciones aritméticas. Esto le permite al programador que un puntero
referencie a un lugar conocido de la memoria y pueda sumar (o restar) algún
valor, para referirse a otro lugar de la memoria. Si otros programadores conocen
6
Tutorial de Java
El código Java pasa muchos tests antes de ejecutarse en una máquina. El código
se pasa a través de un verificador de byte-codes que comprueba el formato de los
fragmentos de código y aplica un probador de teoremas para detectar fragmentos
de código ilegal -código que falsea punteros, viola derechos de acceso sobre
objetos o intenta cambiar el tipo o clase de un objeto-.
7
Tutorial de Java
Portable
Más allá de la portabilidad básica por ser de arquitectura independiente, Java
implementa otros estándares de portabilidad para facilitar el desarrollo. Los
enteros son siempre enteros y además, enteros de 32 bits en complemento a 2.
Además, Java construye sus interfaces de usuario a través de un sistema
abstracto de ventanas de forma que las ventanas puedan ser implantadas en
entornos Unix, Pc o Mac.
Interpretado
8
Tutorial de Java
Se dice que Java es de 10 a 30 veces más lento que C, y que tampoco existen en
Java proyectos de gran envergadura como en otros lenguajes. La verdad es que
ya hay comparaciones ventajosas entre Java y el resto de los lenguajes de
programación, y una ingente cantidad de folletos electrónicos que supuran
fanatismo en favor y en contra de los distintos lenguajes contendientes con Java.
Lo que se suele dejar de lado en todo esto, es que primero habría que decidir
hasta que punto Java, un lenguaje en pleno desarrollo y todavía sin definición
definitiva, está maduro como lenguaje de programación para ser comparado con
otros; como por ejemplo con Smalltalk, que lleva más de 20 años en cancha.
La verdad es que Java para conseguir ser un lenguaje independiente del sistema
operativo y del procesador que incorpore la máquina utilizada, es tanto
interpretado como compilado. Y esto no es ningún contrasentido, me explico, el
código fuente escrito con cualquier editor se compila generando el byte-code.
Este código intermedio es de muy bajo nivel, pero sin alcanzar las instrucciones
máquina propias de cada plataforma y no tiene nada que ver con el p-code de
Visual Basic. El byte-code corresponde al 80% de las instrucciones de la
aplicación. Ese mismo código es el que se puede ejecutar sobre cualquier
plataforma. Para ello hace falta el run-time, que sí es completamente dependiente
de la máquina y del sistema operativo, que interpreta dinámicamente el byte-code
y añade el 20% de instrucciones que faltaban para su ejecución. Con este sistema
es fácil crear aplicaciones multiplataforma, pero para ejecutarlas es necesario que
exista el run-time correspondiente al sistema operativo utilizado.
Multithreaded
Al ser multithreaded (multihilvanado, en mala traducción),
Java permite muchas actividades simultáneas en un
programa. Los threads (a veces llamados, procesos ligeros), son básicamente
pequeños procesos o piezas independientes de un gran proceso. Al estar los
threads contruidos en el lenguaje, son más fáciles de usar y más robustos que
sus homólogos en C o C++.
9
Tutorial de Java
Dinamico
Java se beneficia todo lo posible de la tecnología orientada a objetos. Java no
intenta conectar todos los módulos que comprenden una aplicación hasta el
tiempo de ejecución. Las librería nuevas o actualizadas no paralizarán las
aplicaciones actuales (siempre que mantengan el API anterior).
10
Tutorial de Java
Java, para evitar que los módulos de byte-codes o los objetos o nuevas clases,
haya que estar trayéndolos de la red cada vez que se necesiten, implementa las
opciones de persistencia, para que no se eliminen cuando de limpie la caché de la
máquina.
Todo esto suena muy bonito pero tambien se tienen algunas limitantes:
⇒ La velocidad.
⇒ Los programas hechos en Java no tienden a ser muy rápidos, supuestamente
se está trabajando en mejorar esto.Como los programas de Java son
interpretados nunca alcanzan la velocidad de un verdadero ejecutable.
11
Tutorial de Java
⇒ Java es un lenguaje de programación. Esta es otra gran limitante, por más que
digan que es orientado a objetos y que es muy fácil de aprender sigue siendo
un lenguaje y por lo tanto aprenderlo no es cosa fácil. Especialmente para los
no programadores.
⇒ Java es nuevo. En pocas palabras todavía no se conocen bien todas sus
capacidades.
Pero en general Java posee muchas ventajas y se pueden hacer cosas muy
interesantes con esto. Hay que prestar especial atención a lo que está
sucediendo en el mundo de la computación, a pesar de que Java es relativamente
nuevo, posee mucha fuerza y es tema de moda en cualquier medio
computacional. Muchas personas apuestan a futuro y piensan en Java. La
pregunta es : ¿Estarán en lo correcto? La verdad es que no se, pero este manual
no es para filosofar sobre el futuro del lenguaje sino para aprender a programarlo.
1.3 HotJava
HotJava, en pocas palabras, es un navegador con soporte Java (Java-enabled),
desarrollado en Java. Como cualquier navegador de Web, HotJava puede
decodificar HTML estándar y URLs estándares, aunque no soporta
completamente el estándar HTML 3.0. La ventaja sobre el resto de navegadores,
sin soporte Java, es que puede ejecutar programas Java sobre la red. La
diferencia con Netscape, es que tiene implementado completamente los sistemas
de seguridad que propone Java, esto significa que puede escribir y leer en el
disco local, aunque esto hace disminuir la seguridad, ya que se pueden grabar en
nuestro disco programas que contengan código malicioso e introducirnos un virus,
por ejemplo. No obstante, el utilizar esta característica de HotJava es decisión del
usuario.
12
Tutorial de Java
¿Es Java la medicina? Está claro que cuando vemos un cepillo animado
limpiando los dientes, cubos moviéndose en 3-D, o una banda de gatos locos en
applets de Java, nos convencemos de que es el lenguaje idóneo para Internet.
Pero, qué pasa con las aplicaciones corporativas, ¿sería una buena tecnología allí
donde la red es el punto crítico? Vamos a intentar responder comparando las
capacidades de Java contra la lista de necesidades de la red corporativa.
13
Tutorial de Java
Con un entorno run-time de Java portado a cada una de las arquitecturas de las
plataformas presentes en la empresa y una buena librería de clases ("packages"
en Java), los programadores pueden entenderse y encontrar muy interesante
trabajar con Java. Esta posibilidad hará tender a los programadores hacia Java,
justo donde otros intentos anteriores con entornos universales (como Galaxy o
XVT) han fracasado. Estos APIs eran simplemente inadecuados, no orientados a
redes y, verdaderamente, pesados.
14
Tutorial de Java
Una vez que los programas estén escritos en Java, otro lado interesante del
asunto es que los programadores también son portables. El grupo de
programadores de la empresa puede ahora enfrentarse a un desarrollo para
cualquiera de las plataformas. La parte del cliente y del servidor de una aplicación
estarán ahora escritas en el mismo lenguaje. Ya no será necesario tener un grupo
que desarrolle en Solaris en del departamento de I+D, programadores trabajando
sobre Visual Basic en el departamento de documentación y programadores sobre
GNU en proyectos especiales; ahora todos ellos podrán estar juntos y formar el
grupo de software de la empresa.
Costes de desarrollo
En contraste con el alto coste de los desarrollos realizados sobre estaciones de
trabajo, el coste de creación de una aplicación Java es similar al de desarrollar
sobre un PC.
Mantenimiento y soporte
Un problema bien conocido que ocurre con el software corporativo es la demanda
de cuidados y realimentación. Java no es,
ciertamente, la cura para la enfermedad del
mantenimiento, pero tiene varias características
que harán la vida del enfermero más fácil.
15
Tutorial de Java
16
Tutorial de Java
En el libro Just Java de Peter van der Linden hay un capítulo excelente acerca del
compilador de Java, si tienes oportunidad, no dejes de leerlo.
Aprendizaje
Si la empresa está llena de programadores de C++ con alguna experiencia en el
manejo de librería gráficas, aprenderán rápidamente lo esencial de Java. Si el
equipo de ingenieros no conoce C++, pero maneja cualquier otro lenguaje de
programación orientada a objetos, les llevará pocas semanas dominar la base de
Java. Lo que sí que no es cierto es que haya que aprender C++ antes de
aprender Java.
17
Tutorial de Java
2.1 Windows
La versión del JDK para Windows es un archivo autoextraible. Se necesitan
alrededor de 6 Mb de espacio libre en disco. Ejecutar el fichero, que
desempaquetará el contenido del archivo. El directorio donde se instale no es
importante, pero supondremos que se instala en el raiz del disco C:, en cuyo caso
los archivos colgarán de c:\java. Es necesario añadir c:\java\bin a la variable de
entorno PATH.
18
Tutorial de Java
2.2 Solaris
La versión del JDK para Solaris es un fichero tar comprimido. Se necesitan
alrededor de 9 Mb de disco para descomprimir el JDK, aunque el doble de
espacio sería una cifra más cómoda. Ejecutar los siguientes comandos:
% uncompress JDK-beta-solaris2-sparc.tar.Z
% tar xvf JDK-beta-solaris2-sparc-tar
También puedes añadir esta línea al final del fichero .profile y .cshrc, y ya tienes el
sistema listo para ejecutar applets. Si quieres desembarazarte de la ventana que
aparece cada vez que lances el appletviewer con la licencia de Sun, crea un
directorio que se llame .hotjava en el directorio java/bin y ya no volverás a verla.
2.3 Linux
Necesitas un kernel que soporte binarios ELF, por lo tanto tu Linux debe ser la
versión 1.2.13 o superior, las anteriores tienen un bug que hacen que javac no
funcione. Necesitas también Netscape, versión 2.0b4 o posterior. Sobre la versión
1.2.13 del kernel de Linux, hay que seguir los pasos que indico para conseguir
que JDK funcione:
J_HOME=/usr/local/java
PRG=/usr/local/java/bin
19
Tutorial de Java
➫ Bajarse netscape-v202-export.i486-unknown-linux.tar.z a
usr/local/netscape, descomprimirlo y hacer 'tar xvf'
Esto debería ser suficiente para compilar cualquier cosa en Java/Linux. En caso
de tener problemas, es el momento de recurrir a las FAQ.
% cd /usr/local/java/demo/TicTacToe
% appletviewer example1.html
y a jugar a las tres en raya. Por cierto, que el algoritmo que usa el ordenador está
falseado por lo que es posible ganarle.
20
Tutorial de Java
Como necesito partir de algún punto para tomarlo como referencia, voy a suponer
que estamos sobre Linux y que vamos a prescindir del JDK de Randy Chapman.
Lo que habría que hacer sería lo siguiente.
setenv CLASSPATH
.:/usr/local/netscape/java/classes/moz2_0.zip :
/usr/local/netscape/java/classes/classes.zip
Para aprovechar el tiempo, se puede crear un script que recoja los pasos 3, 4 y 6.
Si estamos utilizando el csh, el contenido del script sería:
21
Tutorial de Java
Comentarios
En Java hay tres tipos de comentarios:
/* comentarios de una o
más líneas
*/
Los dos primeros tipos de comentarios son los que todo programador conoce y se
utilizan del mismo modo. Los comentarios de documentación, colocados
inmediatamente antes de una declaración (de variable o función), indican que ese
comentario ha de ser colocado en la documentación que se genera
automáticamente cuando se utiliza la herramienta de Java, javadoc. Dichos
comentarios sirven como descripción del elemento declarado permitiendo generar
una documentación de nuestras clases escrita al mismo tiempo que se genera el
código.
Identificadores
Los identificadores nombran variables, funciones, clases y objetos; cualquier cosa
que el programador necesite identificar o usar.
22
Tutorial de Java
Palabras clave
Las siguientes son las palabras clave que están definidas en Java y que no se
pueden utilizar como indentificadores:
Palabras Reservadas
Además, el lenguaje se reserva unas cuantas palabras más, pero que hasta ahora
no tienen un cometido específico. Son:
Literales
Un valor constante en Java se crea utilizando una representación literal de él.
Java utiliza cinco tipos de elementos: enteros, reales en coma flotante, booleanos,
caracteres y cadenas, que se pueden poner en cualquier lugar del código fuente
de Java. Cada uno de estos literales tiene un tipo correspondiente asociado con
él.
Enteros:
byte 8 bits complemento a dos
23
Tutorial de Java
Booleanos:
true
false
Caracteres:
Por ejemplo: a \t \u???? [????] es un número unicode
Cadenas:
Por ejemplo: "Esto es una cadena literal"
Arrays
Se pueden declarar en Java arrays de cualquier tipo:
char s[];
int iArray[];
Para crear un array en Java hay dos métodos básicos. Crear un array vacío:
String nombres[] = {
24
Tutorial de Java
"Juan","Pepe","Pedro","Maria"
};
String nombres[];
nombres = new String[4];
nombres[0] = new String( "Juan" );
nombres[1] = new String( "Pepe" );
nombres[2] = new String( "Pedro" );
nombres[3] = new String( "Maria" );
int lista[];
for( int i=0; i < 9; i++ )
lista[i] = i;
Es decir, todos los arrays en Java son estáticos. Para convertir un array en el
equivalente a un array dinámico en C/C++, se usa la clase vector, que permite
operaciones de inserción, borrado, etc. en el array.
Operadores
Los operadores de Java son muy parecidos en estilo y funcionamiento a los de C.
En la siguiente tabla aparecen los operadores que se utilizan en Java, por orden
de precedencia:
. [] ()
++ --
! ~ instanceof
* / %
+ -
<< >> >>>
< > <= >= == !=
& ^ |
&& ||
? :
= op= (*= /= %= += -= etc.)
,
25
Tutorial de Java
Separadores
Sólo hay un par de secuencias con otros caracteres que pueden aparecer en el
código Java; son los separadores simples, que van a definir la forma y función del
código. Los separadores admitidos en Java son:
Sentencias de Salto
if/else
if( Boolean ) {
sentencias;
}
else {
sentencias;
}
26
Tutorial de Java
switch
switch( expr1 ) {
case expr2:
sentencias;
break;
case expr3:
sentencias;
break;
default:
sentencias;
break;
}
Sentencias de Bucle
Bucles for
El siguiente trocito de código Java que dibuja varias líneas en pantalla alternando
sus colores entre rojo, azul y verde. Este fragmento sería parte de una función
Java (método):
int contador;
for( contador=1; contador <= 12; contador++ ) {
switch( contador % 3 ) {
case 0:
setColor( Color.red );
break;
case 1:
setColor( Color.blue );
break;
case 2:
setColor( Color.green );
break;
}
g.drawLine( 10,contador*10,80,contador*10 );
}
Bucles while
27
Tutorial de Java
while( Boolean ) {
sentencias;
}
Bucles do/while
do {
sentencias;
}while( Boolean );
Excepciones
try-catch-throw
try {
sentencias;
} catch( Exception ) {
sentencias;
}
uno: for( )
{
dos: for( )
{
continue; // seguiría en el bucle interno
continue uno; // seguiría en el bucle principal
break uno; // se saldría del bucle principal
}
}
En el código de una función siempre hay que ser consecuentes con la declaración
que se haya hecho de ella. Por ejemplo, si se declara una función para que
devuelva un entero, es imprescindible que se coloque un return final para salir de
28
Tutorial de Java
esa función, independientemente de que haya otros en medio del código que
también provoquen la salida de la función. En caso de no hacerlo se generará un
Warning, y el código Java no se puede compilar con Warnings.
int func()
{
if( a == 0 )
return 1;
return 0; // es imprescindible porque se retorna un entero
}
3.3 Clases
Las clases son lo más simple de Java. Todo en Java forma parte de una clase, es
una clase o describe como funciona una clase. El conocimiento de las clases es
fundamental para poder entender los programas Java.
Todas las acciones de los programas Java se colocan dentro del bloque de una
clase o un objeto. Todos los métodos se definen dentro del bloque de la clase,
Java no soporta funciones o variables globales. Esto puede despistar a los
programadores de C++, que pueden definir métodos fuera del bloque de la clase,
pero esta posibilidad es más un intento de no separarse mucho y ser compatible
con C, que un buen diseño orientado a objetos. Así pues, el esqueleto de
cualquier aplicación Java se basa en la definición de una clase.
Todos los datos básicos, como los enteros, se deben declarar en las clases antes
de hacer uso de ellos. En C la unidad fundamental son los ficheros con código
fuente, en Java son las clases. De hecho son pocas las sentencias que se pueden
colocar fuera del bloque de una clase. La palabra clave import (equivalente al
#include) puede colocarse al principio de un fichero, fuera del bloque de la clase.
Sin embargo, el compilador reemplazará esa sentencia con el contenido del
fichero que se indique, que consistirá, como es de suponer, en más clases.
Tipos de Clases
Hasta ahora sólo se ha utilizado la palabra clave public para calificar el nombre de
las clases que hemos visto, pero hay tres modificadores más. Los tipos de clases
que podemos definir son:
abstract
Una clase abstract tiene al menos un método abstracto. Una clase abstracta no se
instancia, sino que se utiliza como clase base para la herencia.
final
Una clase final se declara como la clase que termina una cadena de herencia. No
se puede heredar de una clase final. Por ejemplo, la clase Math es una clase final.
public
29
Tutorial de Java
Las clases public son accesibles desde otras clases, bien sea directamente o por
herencia. Son accesibles dentro del mismo paquete en el que se han declarado.
Para acceder desde otros paquetes, primero tienen que ser importadas.
synchronizable
Este modificador especifica que todos los métodos definidos en la clase son
sincronizados, es decir, que no se puede acceder al mismo tiempo a ellos desde
distintos threads; el sistema se encarga de colocar los flags necesarios para
evitarlo. Este mecanismo hace que desde threads diferentes se puedan modificar
las mismas variables sin que haya problemas de que se sobreescriban.
public MiClase {
int i;
public MiClase() {
i = 10;
}
public void Suma_a_i( int j ) {
i = i + j;
}
}
Class Ambito {
int i = 1; // ámbito exterior
{ // crea un nuevo ámbito
int i = 2; // error de compilación
}
30
Tutorial de Java
Métodos y Constructores
Los métodos son funciones que pueden ser llamadas dentro de la clase o por
otras clases. El constructor es un tipo específico de método que siempre tiene el
mismo nombre que la clase.
MiClase mc;
mc = new MiClase();
La palabra clave new se usa para crear una instancia de la clase. Antes de ser
instanciada con new no consume memoria, simplemente es una declaración de
tipo. Después de ser instanciado un nuevo objeto mc, el valor de i en el objeto mc
será igual a 10. Se puede referenciar la variable (de instancia) i con el nombre del
objeto:
mc.Suma_a_i( 10 );
Finalizadores
Java no utiliza destructores (al contrario que C++) ya que
tiene una forma de recoger automáticamente todos los objetos que se salen del
alcance. No obstante proporciona un método que, cuando se especifique en el
código de la clase, el reciclador de memoria (garbage collector) llamará:
31
Tutorial de Java
3.6 Herencia
La Herencia es el mecanismo por el que se crean nuevos objetos definidos en
términos de objetos ya existentes. Por ejemplo, si se tiene la clase Ave, se puede
crear la subclase Pato, que es una especialización de Ave.
class Pato extends Ave {
int numero_de_patas;
}
import MiClase;
public class MiNuevaClase extends MiClase {
public void Suma_a_i( int j ) {
i = i + ( j/2 );
}
32
Tutorial de Java
MiNuevaClase mnc;
mnc = new MiNuevaClase();
mnc.Suma_a_i( 10 );
public
public void CualquieraPuedeAcceder(){}
Cualquier clase desde cualquier lugar puede acceder a las variables y métodos
de instacia públicos.
protected
protected void SoloSubClases(){}
Sólo las subclases de la clase y nadie más puede acceder a las variables y
métodos de instancia protegidos.
private
private String NumeroDelCarnetDeIdentidad;
void MetodoDeMiPaquete(){}
33
Tutorial de Java
todos los objetos dentro del mismo paquete, pero no por los externos al paquete.
Es lo mismo que protected.
Los métodos protegidos (protected) pueden ser vistos por las clases derivadas,
como en C++, y también, en Java, por los paquetes (packages). Todas las clases
de un paquete pueden ver los métodos protegidos de ese paquete. Para evitarlo,
se deben declarar como private protected, lo que hace que ya funcione como en
C++ en donde sólo se puede acceder a las variables y métodos protegidos de las
clases derivadas.
34
Tutorial de Java
class UnaClase {
int var;
UnaClase()
{
var = 5;
}
UnaFuncion()
{
var += 5;
}
}
import MiClase;
public class MiNuevaClase extends MiClase {
public void Suma_a_i( int j ) {
35
Tutorial de Java
i = i + ( j/2 );
super.Suma_a_i( j );
}
}
MiNuevaClase mnc;
mnc = new MiNuevaClase();
mnc.Suma_a_i( 10 );
Cuando una clase contiene un método abstracto tiene que declararse abstracta.
No obstante, no todos los métodos de una clase abstracta tienen que ser
abstractos. Las clases abstractas no pueden tener métodos privados (no se
podrían implementar) ni tampoco estáticos. Una clase abstracta tiene que
derivarse obligatoriamente, no se puede hacer un new de una clase abstracta.
36
Tutorial de Java
Una clase abstracta en Java es lo mismo que en C++ virtual func() = 0; lo que
obliga a que al derivar de la clase haya que implementar forzosamente los
métodos de esa clase abstracta.
3.11 Interfaces
Los métodos abstractos son útiles cuando se quiere que cada implementación de
la clase parezca y funcione igual, pero necesita que se cree una nueva clase para
utilizar los métodos abstractos.
Por ejemplo:
37
Tutorial de Java
pegar del código del interface, con lo cual no se hereda nada, solamente se
pueden usar los métodos.
La ventaja principal del uso de interfaces es que una clase interface puede ser
implementada por cualquier número de clases, permitiendo a cada clase
compartir el interfaz de programación sin tener que ser consciente de la
implementación que hagan las otras clases que implementen el interface.
Una vez escrito el código Java, se necesitan ejecutar los pasos siguientes para
poder integrar el código C o C++:
38
Tutorial de Java
3.13 Paquetes
La palabra clave package permite agrupar clases e interfaces. Los nombres de los
paquetes son palabras separadas por puntos y se almacenan en directorios que
coinciden con esos nombres. Por ejemplo, los ficheros siguientes, que contienen
código fuente Java:
package java.applet;
java/applet
Import
Los paquetes de clases se cargan con la palabra clave import, especificando el
nombre del paquete como ruta y nombre de clase (es lo mismo que #include de
C/C++). Se pueden cargar varias clases utilizando un asterisco.
import java.Date;
import java.awt.*;
import MiClase;
Paquetes de Java
El lenguaje Java proporciona una serie de paquetes que incluyen ventanas,
utilidades, un sistema de entrada/salida general, herramientas y comunicaciones.
En la versión actual del JDK, los paquetes Java que se incluyen son:
java.applet
Este paquete contiene clases diseñadas para usar con applets. Hay una clase
Applet y tres interfaces: AppletContext, AppletStub y AudioClip.
39
Tutorial de Java
java.awt
El paquete Abstract Windowing Toolkit (awt) contiene clases para generar widgets
y componentes GUI (Interfaz Gráfico de Usuario). Incluye las clases Button,
Checkbox, Choice, Component, Graphics, Menu, Panel, TextArea y TextField.
java.io
El paquete de entrada/salida contiene las clases de acceso a ficheros:
FileInputStream y FileOutputStream.
java.lang
Este paquete incluye las clases del lenguaje Java propiamente dicho: Object,
Thread, Exception, System, Integer, Float, Math, String, etc.
java.net
Este paquete da soporte a las conexiones del protocolo TCP/IP y, además,
incluye las clases Socket, URL y URLConnection.
java.util
Este paquete es una miscelánea de clases útiles para muchas cosas en
programación. Se incluyen, entre otras, Date (fecha), Dictionary (diccionario),
Random (números aleatorios) y Stack (pila FIFO).
3.14 Referencias
Java se asemeja mucho a C y C++. Esta similitud, evidentemente intencionada,
es la mejor herramienta para los programadores, ya que facilita en gran manera
su transición a Java. Desafortunadamente, tantas similitudes hacen que no nos
paremos en algunas diferencias que son vitales. La terminología utilizada en estos
lenguajes, a veces es la misma, pero hay grandes diferencias subyacentes en su
significado.
C tiene tipos de datos básicos y punteros. C++ modifica un poco este panorama y
le añade los tipos referencia. Java también especifica sus tipos primitivos, elimina
cualquier tipo de punteros y tiene tipos referencia mucho más claros.
40
Tutorial de Java
//
// Aplicación HolaMundo de ejemplo
//
class HolaMundoApp {
public static void main( String args[] ) {
System.out.println( "Hola Mundo!" ) ;
}
}
HolaMundo
Vamos ver en detalle la aplicación anterior, línea a línea. Esas líneas de código
contienen los componenetes mínimos para imprimir Hola Mundo! en la pantalla.
//
// Aplicación HolaMundo de ejemplo
//
Estas tres primera líneas son comentarios. Hay tres tipos de comentarios en Java,
// es un comentario orientado a línea.
class HolaMundoApp {
Esta línea declara la clase HolaMundoApp. El nombre de la clase especificado en
el fichero fuente se utiliza para crear un fichero nombredeclase.class en el
directorio en el que se compila la aplicación. En nuestro caso, el compilador
creará un fichero llamado HolaMundoApp.class.
public static void main( String args[] ) {
Esta línea especifica un método que el intérprete Java busca para ejecutar en
primer lugar. Igual que en otros lenguajes, Java utiliza una palabra clave main
para especificar la primera función a ejecutar. En este ejemplo tan simple no se
pasan argumentos.
public significa que el método main puede ser llamado por cualquiera, incluyendo
el intérprete Java.
static es una palabra clave que le dice al compilador que main se refiere a la
propia clase HolaMundoApp y no a ninguna instancia de la clase. De esta forma,
si alguien intenta hacer otra instancia de la clase, el método main no se
instanciaría.
41
Tutorial de Java
void indica que main no devuelve nada. Esto es importante ya que Java realiza
una estricta comprobación de tipos, incluyendo los tipos que se ha declarado que
devuelven los métodos.
Compilación
El compilador javac se encuentra en el directorio bin por debajo del directorio java,
donde se haya instalado el JDK. Este directorio bin, si se han seguido las
instrucciones de instalación, debería formar parte de la variable de entorno PATH
del sistema. Si no es así, tendría que revisar la Instalación del JDK. El compilador
de Java traslada el código fuente Java a byte-codes, que son los componentes
que entiende la Máquina Virtual Java que está incluida en los navegadores con
soporte Java y en appletviewer.
42
Tutorial de Java
%javac HolaMundoApp.java
Ejecución
Para ejecutar la aplicación HolaMundoApp, hemos de recurrir al intérprete java,
que también se encuentra en el directorio bin, bajo el directorio java. Se ejecutará
la aplicación con la línea:
%java HolaMundoApp
y debería aparecer en pantalla la respuesta de
Java:
%Hola Mundo!
Problemas de compilación
A continuación presentamos una lista de los errores más frecuentes que se
presentan a la hora de compilar un fichero con código fuente Java, nos
basaremos en errores provocados sobre nuestra mínima aplicación Java de la
sección anterior, pero podría generalizarse sin demasiados problemas.
43
Tutorial de Java
System.out.printl( "HolaMundo!);
^
class HolaMundoapp {
Applet
La definición más extendida de applet, muy bien resumida por Patrick Naughton,
indica que un applet es "una pequeña aplicación accesible
en un servidor Internet, que se transporta por la red, se
instala automáticamente y se ejecuta in situ como parte de
un documento web". Claro que así la definición establece
el entorno (Internet, Web, etc.). En realidad, un applet es
una aplicación pretendidamente corta (nada impide que
ocupe más de un gigabyte, a no ser el pensamiento de
que se va a transportar por la red y una mente sensata)
basada en un formato gráfico sin representación
independiente: es decir, se trata de un elemento a
embeber en otras aplicaciones; es un componente en su
sentido estricto.
44
Tutorial de Java
Pues bien, así es un applet. Lo que ocurre es que, dado que no existe una base
adecuada para soportar aplicaciones industriales Java en las que insertar
nuestras miniaplicaciones (aunque todo se andará), los applets se han construido
mayoritariamente, y con gran acierto comercial (parece), como pequeñas
aplicaciones interactivas, con movimiento, luces y sonido... en Internet.
<HTML>
<APPLET CODE=HolaMundo.class WIDTH=300 HEIGHT=100>
</APPLET>
</HTML>
Arquitectura de appletviewer
El appletviewer representa el mínimo interfaz de navegación. En la figura se
muestran los pasos que seguiría appletviewer para presentarnos el resultado de
la ejecución del código de nuestra clase.
45
Tutorial de Java
Ciclo de vida de un
Applet
Cuando un applet se
carga en el
appletviewer, comienza su ciclo de vida, que pasaría por las siguientes fases:
46
Tutorial de Java
El applet se incializa.
El applet empieza a recibir llamadas. Primero recibe una llamada init (inicializar),
seguida de un mensaje start (empezar) y paint (pintar). Estas llamadas pueden
ser recibidas asíncronamente.
init ( )
Esta función miembro es llamada al crearse el applet. Es llamada sólo una vez. La
clase Applet no hace nada en init(). Las clases derivadas deben sobrecargar este
método para cambiar el tamaño durante su inicialización, y cualquier otra
inicialización de los datos que solamente deba realizarse una vez. Deberían
realizarse al menos las siguientes acciones:
Por ejemplo:
destroy ( )
Esta función miembro es llamada cuando el applet no se va a usar más. La clase
Applet no hace nada en este método. Las clases derivadas deberían
sobrecargarlo para hacer una limpieza final. Los applet multithread deberán usar
destroy() para "matar" cuanquier thread del applet que quedase activo.
47
Tutorial de Java
start ( )
Llamada para activar el applet. Esta función miembro es llamada cuando se visita
el applet. La clase Applet no hace nada en este método. Las clases derivadas
deberían sobrecargarlo para comenzar una animación, sonido, etc.
También se puede utilizar start() para eliminar cualquier thread que se necesite.
stop ( )
Llamada para detener el applet. Se llama cuando el applet desaparece de la
pantalla. La clase Applet no hace nada en este método. Las clases derivadas
deberían sobrecargarlo para detener la animación, el sonido, etc.
width
Variable entera, su valor es el ancho definido en el parámetro WIDTH de la marca
HTML del APPLET. Por defecto es el ancho del icono.
height
Variable entera, su valor es la altura definida en el parámetro HEIGHT de la
marca HTML del APPLET. Por defecto es la altura del icono. Tanto width como
height están siempre disponibles para que se puede chequear el tamaño del
applet.
48
Tutorial de Java
paint( Graphics g )
Se llama cada vez que se necesita refrescar el área de dibujo del applet. La clase
Applet simplemente dibuja una caja con sombreado de tres dimensiones en el
área. Obviamente, la clase derivada debería sobrecargar este método para
representar algo inteligente en la pantalla.
Para repintar toda la pantalla cuando llega un evento Paint, se pide el rectángulo
sobre el que se va a aplicar paint() y si es más pequeño que el tamaño real del
applet se invoca a repaint(), que como va a hacer un update(), se actualizará toda
la pantalla.
update( Graphics g )
Esta es la función que se llama realmente cuando se necesita actualizar la
pantalla. La clase Applet simplemente limpia el área y llama al método paint().
Esta funcionalidad es suficiente en la mayoría de los casos. De cualquier forma,
las clases derivadas pueden sustituir esta funcionalidad para sus propósitos.
Podemos, por ejemplo, utilizar update() para modificar selectivamente partes del
área gráfica sin tener que pintar el área completa:
repaint()
A esta función se la debería llamar cuando el applet necesite ser repintado. No
debería sobrecargarse, sino dejar que Java repinte completamente el contenido
del applet.
49
Tutorial de Java
Para usar getParameter(), se define una cadena genérica. Una vez que se ha
capturado el parámetro, se utilizan métodos de cadena o de números para
convertir el valor obtenido al tipo adecuado.
pv = getParameter( "velocidad" );
if( pv == null )
velocidad = 10;
else
velocidad = Integer.parseInt( pv );
}
getDocumentBase ( )
Indica la ruta http, o el directorio del disco, de donde se ha recogido la página
HTML que contiene el applet, es decir, el lugar donde está la hoja en todo Internet
o en el disco.
getCodeBase ( )
Indica la ruta http, o el directorio del disco, de donde se ha cargado el código
bytecode que forma el applet, es decir, el lugar donde está el fichero .class en
todo Internet o en el disco.
print ( Graphics g )
Para imprimir en impresora, al igual que paint() se puede utilizar print(), que
pintará en la impresora el mapa de bits del dibujo.
50
Tutorial de Java
Trataremos por encima los comandos que proporciona el jdb, pero sin entrar en
detalles de su funcionamiento, porque no merece la pena. Casi es mejor esperar
a disponer de herramientas visuales para poder depurar con cierta comodidad
nuestro código Java.
Para poder utilizar el depurador, las aplicaciones Java deben estar compiladas
con la opción de depuración activada, -g. Posteriormente se puede lanzar
appletviewer con la opción de depuración, debug, y habremos puesto en marcha
jdb.
%javac -g hm.java
El fichero hm.html contiene las líneas mínimas para poder activar el applet, estas
líneas son las que reproducimos:
<html>
<applet code=hm.class width=100 height=100>
</applet>
</html>
51
Tutorial de Java
>help
** command list **
threads [threadgroup] -- lista threads
thread <thread id> -- establece el thread por defecto
suspend [thread id(s)] -- suspende threads (por defecto, todos)
resume [thread id(s)] -- continúa threads (por defecto, todos)
where [thread id]|all -- muestra la pila de un thread
threadgroups -- lista los grupos de threads
threadgroup <name> -- establece el grupo de thread actual
print <id> [id(s)] -- imprime un objeto o campo
dump <id> [id(s)] -- imprime toda la información del objeto
locals -- imprime las variables locales de la pila actual
classes -- lista las clases conocidas
methods <class id> -- lista los métodos de una clase
stop in <class id>.<method> -- fija un punto de ruptura en un método
stop at <class id>:<line> -- establece un punto de ruptura en una línea
up [n frames] -- ascender en la pila de threads
down [n frames] -- descender en la pila de threads
clear <class id>:<line> -- eliminar un punto de ruptura
step -- ejecutar la línea actual
cont -- continuar la ejecución desde el punto de ruptura
catch <class id> -- parar por la excepción especificada
ignore <class id> -- ignorar la excepción especificada
list [line number] -- imprimir código fuente
use [source file path] -- ver o cambiar la ruta del fichero fuente
memory -- informe del uso de la memoria
load <classname> - carga la clase Java a ser depurada
run <args> - comienza la ejecución de la clase cargada
!! - repite el último comando
help (or ?) - lista los comandos
exit (or quit) - salir del depurador
>
52
Tutorial de Java
>threadgroups
1.(java.lang.ThreadGroup)0xee300068 system
2.(java.lang.ThreadGroup)0xee300a98 main
>
>threads
Group system:
1.(java.lang.Thread)0xee300098 clock handler cond
2.(java.lang.Thread)0xee300558 Idle thread run
3.(java.lang.Thread)0xee3005d0 sync Garbage Collector cond
4.(java.lang.Thread)0xee300620 Finalizer thread cond
5.(java.lang.Thread)0xee300a20 Debugger agent run
6.(java.tools.debug.BreakpointHandler)0xee300b58) Breakpoint handler cond
Group main:
7.(java.lang.Thread)0xee300048 main suspended
>
53
Tutorial de Java
Loading jdb...
0xee3009c8:class(sun.applet.AppletViewer)
>stop in hm.paint
Breakpoint set in hm.paint
>run
run sun.applet.AppletViewer hm.html
running...
Breakpoint hit: hm.paint(hm.java:9)
AWT-Motif[1]
5.6 Comando where
El comando where mostrará la pila de ejecución del applet.
AWT-Motif[1]where
[1]hm.paint(hm.java:9)
[2]sun.awt.motif.MComponentPeer.paint(MComponenetPeer.java:109)
[3]sun.awt.motif.MComponentPeer.handleExpose(MComponenetPeer.java:170)
AWT-Motif[1]
AWT-Motif[1]use
/usr/local/java/classes:
AWT-Motif[1]
AWT-Motif[1]list
9 public void paint( Graphics g ) {
10 => i = 10;
11 g.drawString( "Hola Mundo!",25,25 ) ;
12 }
13 }
AWT-Motif[1]
AWT-Motif[1]dump g
54
Tutorial de Java
g = (sun.awt.motif.X11Graphics)0xee303df8 {
int pData = 1342480
Color foreground = (java.awt.Color)0xee302378
Font font = (java.awt.Font)0xee302138
int originX = 0
int originY = 0
float scaleX = 1
float scaleY = 1
Image image = null
}
AWT-Motif[1]
AWT-Motif[1]step
Breakpoint hit: hm.paint(hm.java:11)
AWT-Motif[1]list
9 public void paint( Graphics g ) {
10 i = 10;
11 => g.drawString( "Hola Mundo!",25,25 );
12 }
13 }
AWT-Motif[1]
6. AWT
55
Tutorial de Java
JavaSoft, asegura que esto sólo era el principio y que AWT será multi-idioma,
tendrá herramientas visuales, etc. En fin, al igual que dicen los astrólogos, el
futuro nos deparará muchas sorpresas.
56
Tutorial de Java
punto fuerte del AWT, pero también tiene la desventaja de que una interface
gráfica diseñada para una plataforma, puede no visualizarse correctamente en
otra diferente.
Los Componentes deben circunscribirse dentro del Contenedor que los contiene.
Esto hace que el anidamiento de Componentes (incluyendo Contenedores) en
Contenedores crean árboles de elementos, comenzando con un Contenedor en la
raiz del árbol y expandiéndolo en sus ramas.
57
Tutorial de Java
7. GRAFICOS
Los dos métodos anteriores, paint() y update(), junto con el método repaint() son
los que están involucrados en la presentación de gráficos en pantalla. El AWT,
para reducir el tiempo que necesitan estos métodos para realizar el repintado en
pantalla de gráficos, tiene dos axiomas:
58
Tutorial de Java
59
Tutorial de Java
drawLine( x1,y1,x2,y2 )
drawRect( x,y,ancho,alto )
fillRect( x,y,ancho,alto )
clearRect( x,y,ancho.alto )
drawRoundRect( x,y,ancho,alto,anchoArco,altoArco )
fillRoundRect( x,y,ancho,alto,anchoArco,altoArco )
draw3DRect( x,y,ancho,alto,boolean elevado )
fill3DRect( x,y,ancho,alto,boolean elevado )
drawOval( x,y,ancho,alto )
fillOval( x,y,ancho,alto )
drawArc( x,y,ancho,alto,anguloInicio,anguloArco )
fillArc( x,y,ancho,alto,anguloInicio,anguloArco )
drawPolygon( int[] puntosX,int[] puntosY[],numPuntos )
fillPolygon( int[] puntosX,int[] puntosY[],numPuntos )
drawString( string s,x,y )
drawChars( char data[],offset,longitud,x,y )
drawBytes( byte data[],offset,longitud,x,y )
copyArea( xSrc,ySrc,ancho,alto,xDest,yDest )
Hay que tener en cuenta que el método drawImage() necesita un objeto Image y
un objeto ImageObserver. Podemos cargar una imagen desde un fichero de
dibujo (actualmente sólo se soportan formatos GIF y JPEG) con el método
getImage():
Image img = getImage( getDocumentBase(),"fichero.gif" );
60
Tutorial de Java
import java.awt.*;
import sun.awt.image.URLImageSource;
import java.applet.Applet;
Reproducción de sonido
La forma más fácil de reproducir sonido es a través del método play():
play( URL directorioSonido,String ficheroSonido );
o, simplemente:
Un URL común para el método play() es el directorio donde está el fichero HTML.
Se puede acceder a esa localización a través del método getDocumentBase() de
la clase Applet:
play( getDocumentBase(),"sonido.au" );
61
Tutorial de Java
para que esto funcione, el fichero de la clase y el fichero sonido.au deberían estar
en el mismo directorio.
Reproducción Repetitiva
Se puede manejar el sonido como si de imágenes se tratara. Se pueden cargar y
reproducir más tarde.
Para cargar un clip de sonido, se utiliza el método getAudioClip():
AudoClip sonido;
sonido = getAudioClip( getDocumentBase(),"risas.au" );
Una vez que se carga el clip de sonido, se pueden utilizar tres métodos:
sonido.play();
para reproducir el clip de sonido.
sonido.loop();
para iniciar la reproducción del clip de sonido y que entre en un blucle de
reproducción, es decir, en una repetición automática del clip.
sonido.stop();
para detener el clip de sonido que se encuentre en ese instante en reproducción.
8. EXCEPCIONES EN JAVA
import java.awt.*;
import java.applet.Applet;
62
Tutorial de Java
};
La palabra clave finally define un bloque de código que se quiere que sea
ejecutado siempre, de acuerdo a si se capturó la excepción o no. En el ejemplo
anterior, la salida en la consola, con i=4 sería:
Saludos desbordado
¡Esto se imprime siempre!
63
Tutorial de Java
Las excepciones, pues, pueden originarse de dos modos: el programa hace algo
ilegal (caso normal), o el programa explícitamente genera una excepción
ejecutando la sentencia throw (caso menos normal). La sentencia throw tiene la
siguiente forma:
throw ObtejoExcepction;
class melon {
public static void main( String[] a ) {
int i=0, j=0, k;
64
Tutorial de Java
Las siguientes son las excepciones predefinidas más frecuentes que se pueden
encontrar:
ArithmeticException
Las excepciones aritméticas son típicamente el resultado de una división por 0:
int i = 12 / 0;
NullPointerException
Se produce cuando se intenta acceder a una variable o método antes de ser
definido:
ClassCastException
El intento de convertir un objeto a otra clase que no es válida.
65
Tutorial de Java
y = (Prueba)x; // donde
x no es de tipo Prueba
NegativeArraySizeException
Puede ocurrir si hay un error aritmético al intentar cambiar el tamaño de un array.
OutOfMemoryException
¡No debería producirse nunca! El intento de crear un objeto con el operador new
ha fallado por falta de memoria. Y siempre tendría que haber memoria suficiente
porque el garbage collector se encarga de proporcionarla al ir liberando objetos
que no se usan y devolviendo memoria al sistema.
NoClassDefFoundException
Se referenció una clase que el sistema es incapaz de encontrar.
ArrayIndexOutOfBoundsException
Es la excepción que más frecuentemente se produce. Se genera al intentar
acceder a un elemento de un array más allá de los límites definidos inicialmente
para ese array.
UnsatisfiedLinkException
Se hizo el intento de acceder a un método nativo que no existe. Aquí no existe un
método a.kk
class A {
native void kk();
}
InternalException
Este error se reserva para eventos que no deberían ocurrir. Por definición, el
usuario nunca debería ver este error y esta excepción no debería lanzarse.
8.4 Crear Excepciones Propias
También podemos lanzar nuestras propias excepciones, extendiendo la clase
System.exception.
Por ejemplo, consideremos un programa cliente/servidor. El código cliente se
intenta conectar al servidor, y durante 5 segundos se espera a que conteste el
servidor. Si el servidor no responde, el servidor lanzaría la excepción de time-out:
Cualquier método que lance una excepción también debe capturarla, o declararla
como parte de la interface del método. Cabe preguntarse entonces, el porqué de
lanzar una excepción si hay que capturarla en el mismo método. La respuesta es
que las excepciones no simplifican el trabajo del control de errores. Tienen la
ventaja de que se puede tener muy localizado el control de errores y no tenemos
que controlar millones de valores de retorno, pero no van más allá.
66
Tutorial de Java
try
Es el bloque de código donde se prevé que se genere una excepción. Es como si
dijésemos "intenta estas sentencias y mira a ver si se produce una excepción". El
bloque try tiene que ir seguido, al menos, por una cláusula catch o una cláusula
finally
catch
Es el código que se ejecuta cuando se produce la excepción. Es como si
dijésemos "controlo cualquier excepción que coincida con mi argumento". En este
bloque tendremos que asegurarnos de colocar código que no genere
excepciones. Se pueden colocar sentencias catch sucesivas, cada una
controlando una excepción diferente. No debería intentarse capturar todas las
excepciones con una sola cláusula. Esto representaría
un uso demasiado general, podrían llegar muchas más
excepciones de las esperadas. En este caso es mejor
dejar que la excepción se propague hacia arriba y dar
un mensaje de error al usuario.
finally
Es el bloque de código que se ejecuta siempre, haya o no excepción. Hay una
cierta controversia entre su utilidad, pero, por ejemplo, podría servir para hacer un
log o un seguimiento de lo que está pasando, porque como se ejecuta siempre
puede dejarnos grabado si se producen excepciones y nos hemos recuperado de
ellas o no.
Este bloque finally puede ser útil cuando no hay ninguna excepción. Es un trozo
de código que se ejecuta independientemente de lo que se haga en el bloque try.
67
Tutorial de Java
Hemos dicho ya que un método debe capturar las excepciones que genera, o en
todo caso, declararlas como parte de su llamada, indicando a todo el mundo que
es capaz de generar excepciones. Esto debe ser así para que cualquiera que
escriba una llamada a ese método esté avisado de que le puede llegar una
excepción, en lugar del valor de retorno normal. Esto permite al programador que
llama a ese método, elegir entre controlar la excepción o propagarla hacia arriba
en la pila de llamadas.
9. Threads y Multithreading
68
Tutorial de Java
Mientras que los programas de flujo único pueden realizar su tarea ejecutando las
subtareas secuencialmente, un programa multithreaded permite que cada thread
comience y termine tan pronto como sea posible. Este comportamiento presenta
una mejor respuesta a la entrada en tiempo real.
69
Tutorial de Java
Creación de un Thread
Hay dos modos de conseguir threads en Java. Una es implementando la interface
Runnable, la otra es extender la clase Thread.
Hay una cuantas diferencias entre interface y clase. Primero, una interface
solamente puede contener métodos abstractos y/o variables estáticas y finales
(constantes). Las clases, por otro lado, pueden implementar métodos y contener
variables que no sean constantes. Segundo, una interface no puede implementar
cualquier método. Una clase que implemente una interface debe implementar
todos los métodos definidos en esa interface. Una interface tiene la posibilidad de
poder extenderse de otras interfaces y, al contrario que las clases, puede
extenderse de múltiples interfaces. Además, una interface no puede ser
instanciada con el operador new; por ejemplo, la siguiente sentencia no está
permitida:
El ejemplo anterior crea una nueva clase MiThread que extiende la clase Thread y
sobrecarga el método Thread.run() por su propia implementación. El método run()
es donde se realizará todo el trabajo de la clase. Extendiendo la clase Thread, se
pueden heredar los métodos y variables de la clase padre. En este caso,
solamente se puede extender o derivar una vez de la clase padre. Esta limitación
de Java puede ser superada a través de la implementación de Runnable:
70
Tutorial de Java
En este caso necesitamos crear una instancia de Thread antes de que el sistema
pueda ejecutar el proceso como un thread. Además, el método abstracto run()
está definido en la interface Runnable tiene que ser implementado. La única
diferencia entre los dos métodos es que este último es mucho más flexible. En el
ejemplo anterior, todavía tenemos oportunidad de extender la clase MiThread, si
fuese necesario. La mayoría de las clases creadas que necesiten ejecutarse
como un thread , implementarán la interface Runnable, ya que probablemente
extenderán alguna de su funcionalidad a otras clases.
No pensar que la interface Runnable está haciendo alguna cosa cuando la tarea
se está ejecutando. Solamente contiene métodos abstractos, con lo cual es una
clase para dar idea sobre el diseño de la clase Thread. De hecho, si vemos los
fuentes de Java, podremos comprobar que solamente contiene un método
abstracto:
package java.lang;
public interface Runnable {
public abstract void run() ;
}
Y esto es todo lo que hay sobre la interface Runnable. Como se ve, una interface
sólo proporciona un diseño para las clases que vayan a ser implementadas. En el
caso de Runnable, fuerza a la definición del método run(), por lo tanto, la mayor
parte del trabajo se hace en la clase Thread. Un vistazo un poco más profundo a
la definición de la clase Thread nos da idea de lo que realmente está pasando:
Arranque de un Thread
Las aplicaciones ejecutan main() tras arrancar. Esta es la razón de que main() sea
el lugar natural para crear y arrancar otros threads. La línea de código:
71
Tutorial de Java
crea un nuevo thread. Los dos argumentos pasados representan el nombre del
thread y el tiempo que queremos que espere antes de imprimir el mensaje.
Al tener control directo sobre los threads, tenemos que arrancarlos explícitamente.
En nuestro ejemplo con:
t1.start();
Manipulación de un Thread
Si todo fue bien en la creación del thread, t1 debería contener un thread válido,
que controlaremos en el método run().
Una vez dentro de run(), podemos comenzar las sentencias de ejecución como en
otros programas. run() sirve como rutina main() para los threads; cuando run()
termina, también lo hace el thread. Todo lo que queramos que haga el thread ha
de estar dentro de run(), por eso cuando decimos que un método es Runnable,
nos obliga a escribir un método run().
sleep( retardo );
Suspensión de un Thread
Puede resultar útil suspender la ejecución de un thread sin marcar un límite de
tiempo. Si, por ejemplo, está construyendo un applet con un thread de animación,
querrá permitir al usuario la opción de detener la animación hasta que quiera
continuar. No se trata de terminar la animación, sino desactivarla. Para este tipo
de control de thread se puede utilizar el método suspend().
t1.suspend();
t1.resume();
Parada de un Thread
72
Tutorial de Java
Este método devolverá true en caso de que el thread t1 esté vivo, es decir, ya se
haya llamado a su método run() y no haya sido parado con un stop() ni haya
terminado el método run() en su ejecución.
Nuevo Thread
Cuando un thread está en este estado, es simplemente un objeto Thread vacío. El
sistema no ha destinado ningún recurso para él. Desde este estado solamente
puede arrancarse llamando al método start(), o detenerse definitivamente,
llamando al método stop(); la llamada a cualquier otro método carece de sentido y
lo único que provocará será la generación de una excepción de tipo
IllegalThreadStateException.
73
Tutorial de Java
Ejecutable
La llamada al método start() creará los recursos del sistema necesarios para que
el thread puede ejecutarse, lo incorpora a la lista de procesos disponibles para
ejecución del sistema y llama al método run() del thread. En este momento nos
encontramos en el estado "Ejecutable" del diagrama. Y este estado es Ejecutable
y no En Ejecución, porque cuando el thread está aquí no esta corriendo. Muchos
ordenadores tienen solamente un procesador lo que hace imposible que todos los
threads estén corriendo al mismo tiempo. Java implementa un tipo de scheduling
o lista de procesos, que permite que el procesador sea compartido entre todos los
procesos o threads que se encuentran en la lista. Sin embargo, para nuestros
propósitos, y en la mayoría de los casos, se puede considerar que este estado es
realmente un estado "En Ejecución", porque la impresión que produce ante
nosotros es que todos los procesos se ejecutan al mismo tiempo.
Parado
El thread entra en estado "Parado" cuando alguien llama al método suspend(),
cuando se llama al método sleep(), cuando el thread está bloqueado en un
proceso de entrada/salida o cuando el thread utiliza su método wait() para esperar
a que se cumpla una determinada condición. Cuando ocurra cualquiera de las
cuatro cosas anteriores, el thread estará Parado.
Para cada una de los cuatro modos de entrada en estado Parado, hay una forma
específica de volver a estado Ejecutable. Cada
forma de recuperar ese estado es exclusiva; por
ejemplo, si el thread ha sido puesto a dormir, una
vez transcurridos los milisegundos que se
especifiquen, él solo se despierta y vuelve a estar en
estado Ejecutable. Llamar al método resume()
mientras esté el thread durmiendo no serviría para
nada.
Muerto
74
Tutorial de Java
Un thread se puede morir de dos formas: por causas naturales o porque lo maten
(con stop()). Un thread muere normalmente cuando concluye de forma habitual su
método run(). Por ejemplo, en el siguiente trozo de código, el bucle while es un
bucle finito -realiza la iteración 20 veces y termina-:
El método isAlive()
La interface de programación de la clase Thread incluye el método isAlive(), que
devuelve true si el thread ha sido arrancado (con start()) y no ha sido detenido
(con stop()). Por ello, si el método isAlive() devuelve false, sabemos que estamos
ante un "Nuevo Thread" o ante un thread "Muerto". Si nos devuelve true, sabemos
que el thread se encuentra en estado "Ejecutable" o "Parado". No se puede
diferenciar entre "Nuevo Thread" y "Muerto", ni entre un thread "Ejecutable" o
"Parado".
11.METODOS NATIVOS
75
Tutorial de Java
class HolaMundo {
public native void presentaSaludo();
static {
System.loadLibrary( "hola" );
}
}
Todo el código anterior forma parte del fichero HolaMundo.java, que contiene la
clase HolaMundo. En un fichero separado, Main.java, vamos a crear una
aplicación Java que instancie a la clase HolaMundo y llame al método nativo
presentaSaludo().
76
Tutorial de Java
class Main {
public static void main( String args[] ) {
new HolaMundo().presentaSaludo();
}
}
Como se puede observar, llamamos al método nativo del mismo modo que a
cualquier otro método Java; añadimos el nombre del método al final del nombre
del objeto con un punto ("."). El conjunto de paréntesis que sigue al nombre del
método encierra los argumentos que se le pasen. En este caso, el método
presentaSaludo() no recibe ningún tipo de argumento.
#ifndef _Included_HolaMundo
#define _Included_HolaMundo
77
Tutorial de Java
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) void HolaMundo_presentaSaludo(struct HHolaMundo *);
#ifdef __cplusplus
}
#endif
#endif
Del mismo modo que se generaba el fichero .h; el nombre del fichero de stubs
será el nombre de la clase con la extensión .c. En nuestro ejemplo, será
HolaMundo.c, y su contenido será el siguiente:
78
Tutorial de Java
#include <StubPreamble.h>
#include "HolaMundo.h>
#include <stdio.h>
Como se puede ver, la implementación no puede ser más sencilla: hace una
llamada a la función printf() para presentar el saludo y sale.
En el código se incluyen tres ficheros de cabecera:
StubsPreamble.h
79
Tutorial de Java
Unix
Teclearemos el siguiente comando:
Windows '95
El comando a utilizar en este caso es el siguiente:
Este comando funciona con Microsoft Visual C++ 2.x y posteriores. Si queremos
indicar al compilador donde se encuentran los ficheros de cabecera y las librerías,
tendremos que fijar dos variables de entorno:
c:\>SET INCLUDE=%JAVAHOME%\include;%INCLUDE%
c:\>SET LIB=%JAVAHOME%\lib;%LIB%
80
Tutorial de Java
Con ello, hemos visto como integrar código C en programas Java. Quedan
muchas cuestiones por medio, como la equivalencia de tipos entre Java y C, el
paso de parámetros, el manejo de cadenas, etc. Pero eso supondría entrar en
mucha más profundidad dentro de Java de la que aquí pretendemos (por ahora).
Stdin
System.in implementa stdin como una instancia de la clase InputStream. Con
System.in, se accede a los métodos read() y skip(). El método read() permite leer
un byte de la entrada. skip( long n ), salta n bytes de la entrada.
Stdout
System.out implementa stdout como una instancia de la clase PrintStream. Se
pueden utilizar los métodos print() y println() con cualquier tipo básico Java como
argumento.
81
Tutorial de Java
Stderr
System.err implementa stderr de la misma forma que stdout. Como con
System.out, se tiene acceso a los métodos de PrintStream.
import java.io.*;
class miType {
public static void main( String args[] ) throws IOException {
int c;
int contador = 0;
También existen otras clases para aplicaciones más específicas, que no vamos a
tratar, por ser de un uso muy concreto:
PipedInputStream
BufferedInputStream
PushBackInputStream
StreamTokenizer
PipedOutputStream
BufferedOutputStream
82
Tutorial de Java
Todos los lenguajes de programación tienen alguna forma de interactuar con los
sistemas de ficheros locales; Java no es una excepción.
Cuando se desarrollan applets para utilizar en red, hay que
tener en cuenta que la entrada/salida directa a fichero es
una violación de seguridad de acceso. Muchos usuarios
configurarán sus navegadores para permitir el acceso al
sistema de ficheros, pero otros no.
File miFichero;
miFichero = new File( "/etc/kk" );
o
miFichero = new File( "/etc","kk" );
o
File miDirectorio = new File( "/etc" );
miFichero = new File( miDirectorio,"kk" );
83
Tutorial de Java
RandomAccessFile miRAFile;
miRAFile = new RandomAccessFile( "/tmp/kk.dbf","rw" );
Acceso a la Información
Los objetos RandomAccessFile esperan información de lectura/escritura de la
misma manera que los objetos DataInput/DataOutput. Se tiene acceso a todas las
operaciones read() y write() de las clases DataInputStream y DataOutputStream.
Actualización de Información
Se pueden utilizar ficheros de acceso aleatorio para añadir información a ficheros
existentes:
Vamos a ver un pequeño ejemplo, Log.java, que añade una cadena a un fichero
existente:
import java.io.*;
84
Tutorial de Java
Hay una cuestión al respecto de los sockets, que viene impuesta por la
implementación del sistema de seguridad de Java. Actualmente, los applets sólo
85
Tutorial de Java
Socket
Es el objeto básico en toda comunicación a través de Internet, bajo el protocolo
TCP. Esta clase proporciona métodos para la entrada/salida a través de streams
que hacen la lectura y escritura a través de sockets muy sencilla.
ServerSocket
Es un objeto utilizado en las aplicaciones servidor para escuchar las peticiones
que realicen los clientes conectados a ese servidor. Este objeto no realiza el
servicio, sino que crea un objeto Socket en función del cliente para realizar toda la
comunicación a través de él.
DatagramSocket
La clase de sockets datagrama puede ser utilizada para implementar datagramas
o fiables (sockets UDP), no ordenados. Aunque la comunicación por estos sockets
es muy rápida porque no hay que perder tiempo estableciendo la conexión entre
cliente y servidor.
DatagramPacket
Clase que representa un paquete datagrama conteniendo información de
paquete, longitud de paquete, direcciones Internet y números de puerto.
MulticastSocket
Clase utilizada para crear una versión multicast de las clase socket datagrama.
Múltiples clientes/servidores pueden transmitir a un grupo multicast (un grupo de
direcciones IP compartiendo el mismo número de puerto).
NetworkServer
Una clase creada para implementar métodos y variables utilizadas en la creación
de un servidor TCP/IP.
NetworkClient
86
Tutorial de Java
87
Tutorial de Java
Hay un API muy bien definido; cualquiera que use el API, podrá reemplazar el
Modelo, la Vista o el Controlador, sin aparente dificultad.
La conexión entre el Modelo y sus Vistas es dinámica; se produce en tiempo de
ejecución, no en tiempo de compilación.
88
Tutorial de Java
La porción del programa que transforma los datos dentro del Modelo en una
presentación gráfica es la Vista. La Vista incorpora la visión del Modelo a la
escena; es la representación gráfica de la escena desde un punto de vista
determinado, bajo condiciones de iluminación determinadas.
Web de Manuales
http://members.xoom.com/manuales / http://www.come.to/manuales
http://members.xoom.com/jonysoft
JuanReyes@iname.com
ICQ: 13186894
País : CHILE
89