Taller VI - Módulo II

Anuncio
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Asignatura
Taller de Computación VI
Módulo II
Introducción a Java
Elaboración
Hugo Sanoguera, Fabián Gentile
Este material pertenece a la materia Taller de Computación VI, de la Carrera de Analista de Sistemas de
Computación del INSTITUTO DE TECNOLOGÍA ORT.
Todos los derechos reservados. No está permitida la reproducción total o parcial de este apunte, ni su
tratamiento informático, ni la transmisión de ninguna forma o por cualquier medio, ya sea electrónico,
mecánico, por fotocopia, por registro u otros métodos, sin el permiso previo de los titulares.
1ra edición Mayo de 2007.
1
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
UNIDAD DIDÁCTICA II
TABLA DE CONTENIDOS
UNIDAD DIDÁCTICA II_________________________________________________________ 1
TABLA DE CONTENIDOS ___________________________________________________________ 1
Introducción y orientaciones para el estudio______________________________________________ 3
Objetivos ___________________________________________________________________________ 3
Aclaraciones previas al estudio _________________________________________________________ 3
ORIGEN DE JAVA __________________________________________________________________ 4
Cómo funciona Java básicamente_______________________________________________________ 5
Características de Java _______________________________________________________________ 6
Simple ___________________________________________________________________________________ 6
Orientado a Objetos_________________________________________________________________________ 6
Distribuido _______________________________________________________________________________ 7
Robusto __________________________________________________________________________________ 7
Arquitectura Neutral ________________________________________________________________________ 8
Seguro __________________________________________________________________________________ 10
Portable _________________________________________________________________________________ 12
Interpretado ______________________________________________________________________________ 12
Multihilo ________________________________________________________________________________ 14
Dinámico________________________________________________________________________________ 15
Diferencias y Similitudes con C++ _____________________________________________________ 18
Instalación de un entorno de desarrollo integrado (IDE) Eclipse ________________________ 21
Tutorial de Eclipse _____________________________________________________________ 26
Material extraído de la pagina: ___________________________________________________ 26
www.eclipsetutorial.forge.os4os.org/in1.htm de Enrique Serrano Valle.___________________ 26
Parte 1: Entorno de Proyectos de Eclipse _______________________________________________ 26
Parte 2: Crear Elementos de Java _____________________________________________________ 30
Java Class _______________________________________________________________________________
File ____________________________________________________________________________________
Folder __________________________________________________________________________________
Interface ________________________________________________________________________________
Package _________________________________________________________________________________
Scrapbook Page___________________________________________________________________________
Source Folder ____________________________________________________________________________
30
31
31
32
33
33
33
Parte 3: Funciones Útiles de Programación______________________________________________ 34
Compilar y Detectar Errores _________________________________________________________________
Icono de Bombilla = Autocorregir ____________________________________________________________
CTRL + Espacio = Autocompletar ____________________________________________________________
Menú "Source" ___________________________________________________________________________
Menu Refactor____________________________________________________________________________
Consultar la Documentación _________________________________________________________________
Archivos JAR Importar _____________________________________________________________________
34
34
35
37
40
42
42
Parte 4: Vistas de Eclipse ____________________________________________________________ 43
Perspectivas-Restaurar Vistas ________________________________________________________________ 43
Tareas ____________________________________________________________________________ 44
Navigator________________________________________________________________________________ 44
1
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Package Explorer _________________________________________________________________________
Outline View _____________________________________________________________________________
Hierarchy View ___________________________________________________________________________
Fast Views_______________________________________________________________________________
Search View _____________________________________________________________________________
Navegar por las Vistas y los Editores __________________________________________________________
Maximizar una Vista o Editor ________________________________________________________________
Ir al Último Cambio _______________________________________________________________________
Acciones de Navegación de los Editores _______________________________________________________
Revisar Problemas_________________________________________________________________________
45
46
46
47
47
48
48
49
49
49
Parte 5: Ejecutar y Depurar __________________________________________________________ 51
Ejecutar _________________________________________________________________________________ 51
Depurar _________________________________________________________________________________ 52
Gestión de Cambios _______________________________________________________________________ 54
Primera aplicación en Java ___________________________________________________________ 55
Sintaxis De Java y Nomenclatura ______________________________________________________ 57
Estilo de codificación ______________________________________________________________________
Comentarios y documentación incrustada_______________________________________________________
Documentación en forma de comentarios _______________________________________________________
Sintaxis _________________________________________________________________________________
HTML empotrado _________________________________________________________________________
Etiquetas de documentación de variables _______________________________________________________
Etiquetas de documentación de métodos________________________________________________________
Ejemplo de documentación __________________________________________________________________
57
57
57
58
58
60
60
60
Tipos de Datos _____________________________________________________________________ 62
Recolector de Basura (garbage collector) _______________________________________________ 64
Ámbito de los objetos ______________________________________________________________________ 64
Limpieza: finalización y recolección de basura ___________________________________________ 64
La recolección de basura no es destrucción _____________________________________________________
¿Para qué sirve finalize( )? __________________________________________________________________
Hay que llevar a cabo la limpieza _____________________________________________________________
Cómo funciona un recolector de basura ________________________________________________________
64
65
66
66
LA CLASE String __________________________________________________________________ 69
Funciones Básicas _________________________________________________________________________
Funciones de Comparación de Strings _________________________________________________________
Funciones de Comparación de Subcadenas______________________________________________________
Funciones ValueOf ________________________________________________________________________
Funciones de Conversión ___________________________________________________________________
69
69
70
71
71
LA CLASE StringBuffer _____________________________________________________________ 72
Cambio de Tamaño ________________________________________________________________________
Modificación del Contenido _________________________________________________________________
Las funciones que cambian el tamaño son pues:__________________________________________________
Operadores de Concatenación ________________________________________________________________
72
73
73
74
Referencias ________________________________________________________________________ 75
Referencias y Arrays ________________________________________________________________ 77
2
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Introducción y orientaciones para el estudio
En el desarrollo de este módulo abordaremos:
ƒ
ƒ
ƒ
ƒ
ƒ
Un poco de historia del lenguaje Java.
Entorno de trabajo Eclipse.
Primera aproximación al lenguaje Java.
Manejo de Strings en Java.
Creación de un programa en Java.
Objetivos
Pretendemos que al finalizar de estudiar esta Unidad, el alumno logre:
ƒ
ƒ
ƒ
ƒ
ƒ
ƒ
Conocer un poco de historia del lenguaje Java con el cual trabajaremos a lo largo de esta
asignatura.
Conocer las distintas plataformas en las que corre Java.
Tener una primera aproximación a un entorno de trabajo (Eclipse).
Tener una aproximación al Lenguaje Java.
Conocer el manejo de Strings en Java.
Poder realizar el primer programa desde su escritura hasta su ejecución, conociendo las
etapas intermedias.
Aclaraciones previas al estudio
En este módulo, usted encontrará:
Contenidos
Conceptualizaciones centrales
Bibliografía
Referencia de material bibliográfico recomendado
Usted debe tener presente que los contenidos presentados en el módulo
no ahondan profundamente en el tema, sino que pretenden ser un recurso
motivador, para que a través de la lectura del material, la bibliografía
sugerida, y el desarrollo de las actividades propuestas alcance los
objetivos planteados en el presente módulo.
3
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
ORIGEN DE JAVA
Material extraído de la pagina:
Tutorial de Java de Agustin Froufe www.sunsite.dcc.uchile.cl/java/docs/JavaTut
Sun Microsystems, líder en servidores para Internet, uno de cuyos lemas desde hace mucho
tiempo es "the networkis the computer" (lo que quiere dar a entender que el verdadero ordenador
es la red en su conjunto y no cada máquina individual), es quien ha desarrollado el lenguaje Java,
en un intento de resolver simultáneamente todos los problemas que se le plantean a los
desarrolladores de software por la proliferación de arquitecturas incompatibles, tanto entre las
diferentes máquinas como entre los diversos sistemas operativos y sistemas de ventanas que
funcionaban sobre una misma máquina, añadiendo la dificultad de crear aplicaciones distribuidas
en una red como Internet.
He podido leer más de cinco versiones distintas sobre el origen, concepción y desarrollo de Java,
desde la que dice que este fue un proyecto que rebotó durante mucho tiempo por distintos
departamentos de Sun sin que nadie le prestara ninguna atención, hasta que finalmente encontró
su nicho de mercado en la aldea global que es Internet; hasta la más difundida, que justifica a
Java como lenguaje de pequeños electrodomésticos.
Hace algunos años, Sun Microsystems decidió intentar introducirse en el mercado de la
electrónica de consumo y desarrollar programas para pequeños dispositivos electrónicos. Tras
unos comienzos dudosos, Sun decidió crear una filial, denominada FirstPerson Inc., para dar
margen de maniobra al equipo responsable del proyecto.
El mercado inicialmente previsto para los programas de FirstPerson eran los equipos domésticos:
microondas, tostadoras y, fundamentalmente, televisión interactiva. Este mercado, dada la falta de
pericia de los usuarios para el manejo de estos dispositivos, requería unas interfaces mucho más
cómodas e intuitivas que los sistemas de ventanas que proliferaban en el momento.
Otros requisitos importantes a tener en cuenta eran la fiabilidad del código y la facilidad de
desarrollo. James Gosling, el miembro del equipo con más experiencia en lenguajes de
programación, decidió que las ventajas aportadas por la eficiencia de C++ no compensaban el
gran coste de pruebas y depuración. Gosling había estado trabajando en su tiempo libre en un
lenguaje de programación que él había llamado Oak, el cual, aún partiendo de la sintaxis de C++,
intentaba remediar las deficiencias que iba observando.
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 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.
El primer proyecto en que se aplicó este lenguaje recibió el nombre de proyecto Green y consistía
en un sistema de control completo de los aparatos electrónicos y el entorno de un hogar. Para ello
se construyó un ordenador experimental denominado *7 (Star Seven). El sistema presentaba una
interfaz basada en la representación de la casa de forma animada y el control se llevaba a cabo
mediante una pantalla sensible al tacto. En el sistema aparecía Duke, la actual mascota de Java.
Posteriormente se aplicó a otro proyecto denominado VOD (Video On Demand) en el que se
empleaba como interfaz para la televisión interactiva. Ninguno de estos proyectos se convirtió
nunca en un sistema comercial, pero fueron desarrollados enteramente en un Java primitivo y
fueron como su bautismo de fuego.
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.
4
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
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.
Cómo funciona Java básicamente
Java es el primer lenguaje que tiene la virtud de ser compilado e interpretado de forma simultánea.
Cuando un programador realiza una aplicación o un applet en Java y lo compila, en realidad, el
compilador no trabaja como un compilador de un lenguaje al uso. El compilador Java únicamente
genera el denominado ByteCode. Este código es un código intermedio entre el lenguaje máquina
del procesador y Java. Evidentemente este código no es ejecutable por sí mismo en ninguna
plataforma hardware, pues no se corresponde con el lenguaje de ninguno de los procesadores
que actualmente se conocen (habrá que esperar a ver qué ocurre con los procesadores Java). Por
lo tanto, para ejecutar una aplicación Java es necesario disponer de un mecanismo que permita
ejecutar el ByteCode. Este mecanismo es la denominada Máquina Virtual Java. En cada
plataforma (Unix, Linux, Windows 95/NT, Macintosh, Mainframes, AS400, etc.) existe una máquina
virtual específica. Así que cuando el ByteCode llega a la máquina virtual, ésta lo interpreta
pasándolo a código máquina del procesador donde se esté trabajando, y ejecutando las
instrucciones en lenguaje máquina que se deriven de la aplicación Java. De este modo, cuando el
mismo ByteCode llega a diferentes plataformas, éste se ejecutará de forma correcta, pues en
cada una de esas plataformas existirá la máquina virtual adecuada. Con este mecanismo se
consigue la famosa multiplataforma de Java, que con sólo codificar una vez, podemos ejecutar en
varias plataformas.
En realidad la máquina virtual desempeña otras funciones, como la de aislar los programas Java
al entorno de la máquina virtual, consiguiendo una gran seguridad.
Sin embargo, como podrá estar deduciendo el lector, esto tiene algunas desventajas, y la más
clara es la velocidad de ejecución. Puesto que la máquina virtual debe estar interpretando
constantemente el ByteCode, se consume demasiado tiempo de procesador en realizar esta
interpretación, que por otra parte no aporta nada a la aplicación, obteniendo así un bajo
rendimiento. Para solucionarlo se han adoptado soluciones intermedias. Una de las más
novedosas y útiles son los compiladores JIT (Just-In-Time). Estos compiladores están situados a
la entrada de la máquina virtual, de forma que según llega el ByteCode lo van compilando al
lenguaje máquina del procesador. A diferencia de la interpretación, el compilador no ejecuta el
ByteCode, únicamente lo traduce y lo almacena en código nativo dentro de la máquina virtual. Así,
una vez que la aplicación está dentro de la máquina virtual, ya se encuentra en lenguaje máquina
y, por lo tanto, será directamente ejecutable, sin necesidad de interpretaciones, consiguiendo
dotar de mayores rendimientos a la aplicación.
Que Java es lento, resultará pues evidente, pero vamos, hasta los más pesimistas respecto a
Java, como Microsoft, reconocen que Java obtendrá gracias a los compiladores JIT un
rendimiento cercano al 80% del de C++, lo cual es más que suficiente para la mayoría de las
aplicaciones; y más aún si se tiene en cuenta el sector al cual va dirigido Java, porque, al fin y al
cabo, tampoco se trata de escribir el Doom III en Java. No obstante, el uso de ByteCode no es la
única causa de que Java sea más lento que C++. Porque este último lenguaje no tiene un
recolector de basura, ni que cargar clases dinámicamente, ni realizar comprobaciones en tiempo
de ejecución como la de los límites de los arrays, las condiciones de seguridad o que el ByteCode
no esté manipulado para acceder ilegalmente a campos marcados como privados o protegidos.
Estas características suponen una sobrecarga importante, sólo el recolector de basura puede
superar el 15%, y son la causa última de que Java no pueda alcanzar el cien por cien del
rendimiento de C++. A pesar de todo, hay grandes expectativas en la compilación dinámica y en la
5
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
propia mejora de los elementos que integran la máquina virtual como el recolector de basura,
porque afortunadamente, a diferencia de otras ocasiones, muchas empresas e investigadores no
se han quedado en una queja estéril y se han puesto a trabajar para solucionar estas cuestiones.
A cambio de este incremento de la carga se obtiene mayor fiabilidad, lo que reduce
ostensiblemente el coste de mantenimiento y un sinfín de nuevas posibilidades.
Características de Java
Las características principales que nos ofrece Java respecto a cualquier otro lenguaje de
programación, serían:
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 con pocas posibilidades para la seguridad),
pero C y C++ son los lenguajes más difundidos, por 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 de baja prioridad, cuando entra en acción, permite liberar
bloques de memoria muy grandes, lo que limita en mucho 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)
Aunque, en realidad, lo que hace es eliminar las palabras reservadas (struct, typedef), ya que las
clases son algo parecido.
Además, el intérprete completo de Java que hay en este momento muy pequeño.
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.
Java incorpora funcionalidades inexistentes en C++ como por ejemplo, la resolución dinámica de
métodos. Esta característica deriva del lenguaje Objective C, propietario del sistema operativo
Next. En C++ se suele trabajar con librerías dinámicas (DLLs) que obligan a recompilar la
aplicación cuando se retocan las funciones de su interior. Mientras que en java solo se recompila
la clase modificada(.class )
6
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Este inconveniente es resuelto por Java mediante una interfaz específica llamada RTTI (RunTime
Type Identification) que define la interacción entre objetos excluyendo variables de instancias o
implementación de métodos. Las clases en Java tienen una representación en el runtime que
permite a los programadores interrogar por el tipo de clase y enlazar dinámicamente la clase con
el resultado de la búsqueda.
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 ftp. Esto permite a los
programadores acceder a la información a través de la red con tanta facilidad como a los ficheros
locales.
Java en sí no es distribuido, sino que proporciona las librerías y herramientas para que los
programas puedan ser distribuidos, es decir, que se corran en varias máquinas, interactuando.
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.
También implementa los arrays auténticos, en vez de listas enlazadas de punteros, con
comprobación de límites, para evitar la posibilidad de sobreescribir o corromper memoria resultado
de punteros que señalan a zonas equivocadas. Estas características reducen drásticamente el
tiempo empleado en el desarrollo de aplicaciones Java.
Además, para asegurar el funcionamiento de la aplicación, realiza una verificación de los
ByteCodes, que son el resultado de la compilación de un programa Java. Es un código de
máquina virtual que es interpretado por el intérprete Java. No es el código máquina directamente
entendible por el hardware, pero ya ha pasado todas las fases del compilador: análisis de
instrucciones, orden de operadores, etc., y ya tiene generada la pila de ejecución de órdenes.
Java proporciona, pues:
•
•
•
•
Comprobación de punteros
Comprobación de límites de arrays
Excepciones
Verificación de ByteCodes
7
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
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 , SunOs , Windows Servers, Windows XP, Linux, Irix, Aix, Mac, Apple ,
Mainframes, As400 y probablemente haya grupos de desarrollo trabajando en el porting a otras
plataformas.
El código fuente Java se "compila" a un código de bytes de alto nivel independiente de la
máquina. Este código (ByteCode) está diseñado para ejecutarse en una máquina hipotética que
es implementada por un sistema run-time, que sí es dependiente de la máquina. En una
representación en que tuviésemos que indicar todos los elementos que forman parte de la
arquitectura de Java sobre una plataforma genérica, obtendríamos una imagen como la siguiente:
8
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
En ella podemos ver que lo verdaderamente dependiente del sistema es la Máquina Virtual Java
(JVM) y las librerías fundamentales, que también permitirían acceder directamente al hardware de
la máquina. Además, siempre habrá APIs de Java que también entren en contacto directo con el
hardware y serán dependientes de la máquina, como ejemplo de este tipo de APIs podemos citar:
•
•
•
•
•
•
•
Swing : Mejora de las herramientas para la implementación de interfaces de usuario
Java 2D : gráficos 2D y manipulación de imágenes
Java Media Framework : Elementos críticos en el tiempo: audio, video...
Java Animation : Animación de objetos en 2D
Java Telephony : Integración con telefonía
Java Share : Interacción entre aplicaciones multiusuario
Java 3D : Gráficos 3D y su manipulación
La siguiente figura ilustra la situación en que se encuentra Java cuando se ejecuta sobre un
sistema operativo convencional. En la imagen se observa que si se exceptúa la parte
correspondiente al Sistema Operativo que ataca directamente al hardware de la plataforma, el
resto está totalmente programado por Javasoft o por los programadores Java, teniendo en cuenta
que HotJava es una aplicación en toda regla, al tratarse de un navegador y estar desarrollado en
su totalidad en Java. Cualquier programador podría utilizar las mismas herramientas para levantar
un nuevo desarrollo en Java, bien fuesen applets para su implantación en Internet o aplicaciones
para su uso individual.
9
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Y la imagen que aparece a continuación muestra la arquitectura de Java sin un Sistema Operativo
que lo ampare, de tal forma que el kernel tendría que proporcionar suficientes posibilidades como
para implementar una Máquina Virtual Java y los drivers de dispositivos imprescindibles como
pantalla, red, ratón, teclado y la base para poder desarrollar en Java librerías como AWT, ficheros,
red, etc. Con todo ello estaría asegurado el soporte completo del API de Java, quedando en mano
de los desarrolladores la implementación de aplicaciones o applets o cualquier otra librería.
Seguro
La seguridad en Java tiene dos facetas. En el lenguaje, características como los punteros o el
casting implícito que hace el compilador 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 nuestras estructuras de datos pueden extraer información confidencial de
nuestro sistema. Con un lenguaje como C, se pueden tomar números enteros aleatorios y
convertirlos en punteros para luego acceder a la memoria:
printf( "Escribe un valor entero: " );
scanf( "%u",&puntero );
printf( "Cadena de memoria: %s\n",puntero );
Otra laguna de seguridad u otro tipo de ataque, es el Caballo de Troya. Se presenta un programa
como una utilidad, resultando tener una funcionalidad destructiva. Por ejemplo, en UNIX se
visualiza el contenido de un directorio con el comando ls. Si un programador deja un comando
destructivo bajo esta referencia, se puede correr el riesgo de ejecutar código malicioso, aunque el
comando siga haciendo la funcionalidad que se le supone, después de lanzar su carga
destructiva. Por ejemplo, después de que el caballo de Troya haya enviado por correo el
/etc/shadow a su creador, ejecuta la funcionalidad de ls presentando el contenido del directorio.
Se notará un retardo, pero nada inusual.
10
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
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 ByteCode 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-.
Si los ByteCodes pasan la verificación sin generar ningún mensaje de error, entonces sabemos
que:
•
•
•
•
•
El código no produce desbordamiento de operandos en la pila
El tipo de los parámetros de todos los códigos de operación son conocidos y correctos
No ha ocurrido ninguna conversión ilegal de datos, tal como convertir enteros en punteros
El acceso a los campos de un objeto se sabe que es legal: public, private, protected
No hay ningún intento de violar las reglas de acceso y seguridad establecidas
El Cargador de Clases también ayuda a Java a mantener su seguridad, separando el espacio de
nombres del sistema de ficheros local del de los recursos procedentes de la red. Esto limita
cualquier aplicación del tipo Caballo de Troya, ya que las clases se buscan primero entre las
locales y luego entre las procedentes del exterior.
Las clases importadas de la red se almacenan en un espacio de nombres privado, asociado con el
origen. Cuando una clase del espacio de nombres privado accede a otra clase, primero se busca
en las clases predefinidas (del sistema local) y luego en el espacio de nombres de la clase que
hace la referencia. Esto imposibilita que una clase suplante a una predefinida.
En resumen, las aplicaciones de Java resultan extremadamente seguras, ya que no acceden a
zonas delicadas de memoria o de sistema, con lo cual evitan la interacción de ciertos virus. Java
no posee una semántica específica para modificar la pila de programa o la memoria libre o utilizar
objetos y métodos de un programa sin los privilegios del kernel del sistema operativo. Además,
para evitar modificaciones por parte de los crackers de la red, implementa un método ultraseguro
de autentificación por clave pública. El Cargador de Clases puede verificar una firma digital antes
de realizar una instancia de un objeto. Por tanto ningún objeto se crea y almacena en memoria,
sin que se validen los privilegios de acceso. Es decir, la seguridad se integra en el momento en
que se interpreta, con el nivel de detalle y de privilegio que sea necesario. Con código compilado
no sería posible establecer estos niveles de seguridad entre dos objetos pertenecientes al mismo
proceso, porque al compartir un único espacio de direcciones, el código de uno podría acceder
tranquilamente a cualquier dirección del otro.
Dada, pues la concepción del lenguaje y si todos los elementos se mantienen dentro del estándar
marcado por Sun, no hay peligro. Java imposibilita, también, abrir ningún fichero de la máquina
local (siempre que se realizan operaciones con archivos, éstas trabajan sobre el disco duro de la
máquina de donde partió el applet), no permite ejecutar ninguna aplicación nativa de una
plataforma e impide que se utilicen otros ordenadores como puente, es decir, nadie puede utilizar
nuestra máquina para hacer peticiones o realizar operaciones con otra. Además, los intérpretes
que incorporan los navegadores de la Web son aún más restrictivos. Bajo estas condiciones (y
dentro de la filosofía de que el único ordenador seguro es el que está apagado, desenchufado,
dentro de una cámara acorazada en un bunker y rodeado por mil soldados de los cuerpos
especiales del ejército), se puede considerar que Java es un lenguaje seguro y que los applets
están libres de virus.
Respecto a la seguridad del código fuente, no ya del lenguaje, el propio JDK proporciona un
desemsamblador de ByteCode, lo cual hace que cualquier programa pueda ser convertido a
código fuente, lo que para el programador significa una vulnerabilidad total a su código. Utilizando
javap no se obtiene el código fuente original, pero sí desmonta el programa mostrando el
algoritmo que se utiliza, que es lo realmente interesante. La protección de los programadores ante
esto es utilizar llamadas a programas nativos, externos (incluso en C o C++) de forma que no sea
11
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
descompilable todo el código; aunque así se pierda portabilidad. Es otra de las cuestiones que
Java tiene pendientes.
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
El intérprete Java (sistema run-time) puede ejecutar directamente el código objeto. Enlazar
(linkear) un programa normalmente consume menos recursos que compilarlo, por lo que los
desarrolladores con Java pasarán más tiempo desarrollando y menos esperando por el ordenador.
No obstante, el compilador actual del JDK es bastante lento. Por ahora, que todavía no hay
compiladores específicos de Java para las diversas plataformas, Java es más lento que otros
lenguajes de programación, como C++, ya que debe ser interpretado y no ejecutado como sucede
en cualquier programa tradicional.
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 ByteCode. 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 ByteCode 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 runtime, que sí es
completamente dependiente de la máquina y del sistema operativo que interpreta dinámicamente
el ByteCode 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 runtime
correspondiente al sistema operativo utilizado.
No obstante, este panorama está cambiando y aunque Java sigue siendo
básicamente un lenguaje interpretado, la situación se acerca mucho a la
de los programas compilados, sobre todo en lo que a la rapidez en la
ejecución del código se refiere.Para comprender el funcionamiento de
HotSpot, que es el último lanzamiento que hace Sun y que promete
interpretar los ByteCodes más rápido que un programa compilado, las
siguientes imágenes muestran cómo actúa el sistema runtime en los
diversos casos que hasta ahora pueden darse.
La imagen de la izquierda muestra las acciones correspondientes a un
compilador tradicional. El compilador traslada las sentencias escritas en
lenguaje de alto-nivel a múltiples instrucciones, que luego son enlazadas
junto con el resultado de múltiples compilaciones previas que han dado
origen a librerías, y juntando todo ello, es cuando genera un programa
ejecutable.
12
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
La imagen de la derecha muestra la forma de actuación de un intérprete.
Básicamente es un enorme bucle, en el cual se va leyendo o recogiendo cada
una de las instrucciones del programa fuente que se desea ejecutar, se analiza,
se parte en trozos y se ejecuta. Luego se va a recoger la siguiente instrucción
que se debe interpretar y se continúa con este proceso hasta que se terminan las
instrucciones o hasta que entre las instrucciones hay alguna que contiene la
orden de detener la ejecución de las instrucciones que componen el programa
fuente.
La imagen siguiente, situada a la izquierda, muestra un tipo de intérprete más
eficiente que el anterior, el intérprete de ByteCodes, que fue popularizado
hace más de veinte años por la Universidad de California al crear el UCSD
Pascal. En este caso, el intérprete trabaja sobre instrucciones que ya han sido
trasladadas a un código intermedio en un paso anterior. Así, aunque se
ejecute en un bucle , se elimina la necesidad de analizar cada una de las
instrucciones que componen el programa fuente, porque ya lo han sido en el
paso previo. Este es el sistema que Java utiliza, y la Máquina Virtual Java es
un ejemplo de este tipo de intérprete. No obstante, sigue siendo lento, aunque
se obtenga un código independiente de plataforma muy compacto, que puede
ser ejecutado en cualquier ordenador que disponga de una máquina virtual
capaz de interpretar los ByteCodes trasladados.
Un paso adelante en el rendimiento del código Java lo han representado los
compiladores Just-In-Time, que compilan el código convirtiéndolo a código máquina
antes de ejecutarlo. Es decir, un compilador JIT va trasladando los ByteCodes al
código máquina de la plataforma según los va leyendo, realizando un cierto grado de
optimización. El resultado es que cuando el programa se ejecute, habrá partes que no
se ejecuten y que no serán compiladas, y el compilador JIT no perderá el tiempo en
optimizar código que nunca se va a ejecutar. No obstante, los compiladores JIT no
pueden realizar demasiadas optimizaciones, ya que hay código que ellos no ven, así
que aunque siempre son capaces de optimizar la parte de código de inicialización de
un programa, hay otras partes que deben ser optimizadas, según se van cargando,
con lo cual, hay una cierta cantidad de tiempo que inevitablemente ha de perderse.
13
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Y, finalmente, se presenta la última tendencia en lo que a
compilación e intérpretes se refiere. Lo último en que
trabaja Sun es HotSpot, una herramienta que incluye un
compilador dinámico y una máquina virtual para
interpretar los ByteCodes, tal como se muestra en la
figura siguiente, situada a la izquierda de la página.
Cuando se cargan los ByteCodes producidos por el
compilador por primera vez, éstos son interpretados en la
máquina virtual. Cuando ya están en ejecución, el profiler
mantiene información sobre el rendimiento y selecciona
el método sobre el que se va a realizar la compilación.
Los métodos ya compilados se almacenan en un caché
en código máquina nativo. Cuando un método es
invocado, esta versión en código máquina nativo es la
que se utiliza, en caso de que exista; en caso contrario,
los ByteCodes son reinterpretados. La función control
que muestra el diagrama es como un salto indirecto a
través de la memoria que apunta tanto al código máquina como al interpretado, aunque Sun no ha
proporcionado muchos detalles sobre este extremo.
Multihilo
Al ser MultiHilo ( o multihilvanado, mala traducción de multithreaded), Java permite muchas
actividades simultáneas en un programa. Los hilos -a veces llamados, procesos ligeros, o hilos de
ejecución- son básicamente pequeños procesos de un gran proceso. Al estar estos hilos
construidos en el mismo lenguaje, son más fáciles de usar y más robustos que sus homólogos en
C o C++.
El beneficio de ser multihilo consiste en un mejor rendimiento interactivo y mejor comportamiento
en tiempo real. Aunque el comportamiento en tiempo real está limitado a las capacidades del
sistema operativo subyacente (Unix, Windows, etc.) de la plataforma, aún supera a los entornos
de flujo único de programa (single-threaded) tanto en facilidad de desarrollo como en rendimiento.
Cualquiera que haya utilizado la tecnología de navegación concurrente, sabe lo frustrante que
puede ser esperar por una gran imagen que se está trayendo de un sitio interesante desde la red.
En Java, las imágenes se pueden ir trayendo en un hilo de ejecución independiente, permitiendo
que el usuario pueda acceder a la información de la página sin tener que esperar por el
navegador.
14
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Dinámico
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 mismo tiempo de ejecución. Las
librería nuevas o actualizadas no paralizarán la ejecución de las aplicaciones actuales -siempre
que mantengan el API anterior.
Java también simplifica el uso de protocolos nuevos o actualizados. Si su sistema ejecuta una
aplicación Java sobre la red y encuentra una pieza de la aplicación que no sabe manejar, tal como
se ha explicado en párrafos anteriores, Java es capaz de traer automáticamente cualquier pieza
que el sistema necesite para funcionar.
Java, para evitar que los módulos de ByteCode o los objetos o nuevas clases, no haya que estar
trayéndolas 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.
15
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
A continuación vemos la descripción de los APIs que componen la plataforma Java, aunque no
todas las que aquí se citan están disponibles para su uso, ya que algunas se encuentran en fase
de desarrollo, otras en fase de discusión pública para aporte de ideas y otras en fase beta.
Java Enterprise
Conjunto de especificaciones para entornos corporativos
JDBC API
Java Database Connectivity, para permitir a aplicaciones o applets acceder a bases de datos de
forma homogénea vía consultas SQL
Java RMI
Remote Method Invocation, invocación remota de métodos para aplicaciones distribuidas
Java IDL
Puente de compatibilidad con el modelo estándar de objetos CORBA
JNDI
Java Naming and Directory Interface, proporciona servicios de directorio y localización de recursos
en un entorno corporativo
JavaBeans
Especificación de componentes basados en Java
JAF
JavaBeans Activation Framework, entorno para determinar el tipo de datos, encapsular el acceso
a ellos, descubrir las acciones que se les pueden aplicar e instanciar el componente JavaBean
adecuado
Java Security API
API para componentes que necesitan encriptación, certificación, firmas digitales y autentificación
JFC
Java Foundation Classes, jerarquía de clases para el desarrollo de aplicaciones gráficas e
interfaces de usuario
Swing Set
Conjunto de pequeños componentes gráficos para aplicaciones: botones, pestañas, etc.
Java 2D
Extensión del AWT para el tratamiento de información gráfica bidimensional
Java Servlet API
Especificación que permite crear applets que se ejecutan en el servidor
Java Server API
API para el intercambio de información entre un servidor Web y aplicaciones que se ejecutan en
su entorno
Java Commerce API
API para transacciones comerciales en Internet
Java Media API
Conjunto de especificaciones para el acceso y utilización de información interactiva
JMF
Java Media Framework, conjunto de especificaciones para la arquitectura, protocolos e interfaces
de programación para reproductores multimedia, captura y videoconferencia
Java Collaboration
Especificación para la comunicación interactiva bidireccional
Java Telephony
Especificación para aplicaciones de telefonía
Java Speech
Especificación para el reconocimiento y síntesis de voz
Java Animation
Especificación para la manipulación y movimiento de objetos bidimensionales
Java 3D
Especificación para la manipulación de objetos tridimensionales
Java Management API
Especificación para la gestión remota de redes
JavaMail API
16
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Especificación para proporcionar un conjunto de clases abstractas que modelice un sistema de
correo
Personal Java
Espeficaciones para aparatos electrónicos de consumo conectables a redes, incluyendo
televisores, teléfonos inteligentes, videoconsolas, etc.
Java Smart Card
Especificaciones para tarjetas inteligentes, tipo tarjeta de crédito
Embedded Java
Especificaciones para dispositivos electrónicos industriales con software embebido ejecutándose
sobre sistemas operativos de tiempo real, incluyendo dispositivos de instrumentación, electrónica
de control de procesos, etc.
17
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Diferencias y Similitudes con C++
Si conocemos C++, esta sección servirá para tener como referencia respecto a los cambios que
representa Java sobre C++, y donde debes cambiar el concepto de las cosas. Fundamentalmente,
porque hay características que siguen utilizándose en Java heredadas de C++, pero el sentido con
que se aplican es ligeramente diferente, lo que muchas veces lleva a los programadores C++ que
atacan Java, a confusiones innecesarias. Por ello, aunque un poco extenso, es una sección de
lectura obligada para tener en cuenta las cosas que debes alterar en la forma de concebir la
programación cuando encares proyectos en Java.
•
•
•
•
•
•
•
•
•
•
•
Java no soporta typedefs, defines o comandos de preprocesador. Al no existir un
preprocesador, no está prevista la inclusión de ficheros de cabecera, tampoco tiene cabida
el concepto de macro o constante. Sin embargo, sí se permite cierto uso de constantes
enumeradas a través de la utilización de la palabra clave final. Java tampoco soporta
enums, aunque soporte constantes enumeradas, como acabo de decir.
Java soporta clases, pero no soporta estructuras o uniones.
Todas las aplicaciones C++ necesitan una función de entrada llamada main() y puede
haber multitud de otras funciones, tanto funciones miembros de una clase como funciones
independientes. En Java no hay funciones independientes, absolutamente todas las
funciones han de ser miembros de alguna clase (métodos). Funciones globales y datos
globales en Java no están permitidos.
En C++ se pueden crear árboles de herencia de clases independientes unos de otros. En
Java esto no es posible, en última instancia hay una clase Object, de la que hereda todo
lo que el programador cree.
Todas las funciones o definiciones de métodos en Java deben estar contenidos dentro de
la definición de la clase. Para un programador C++ puede parecerle que esto es semejante
a las funciones inline, pero no es así. Java no permite, al menos directamente, que el
programador pueda declarar funciones inline.
Tanto Java como C++ soportan funciones o métodos (estáticos) de clases, que pueden ser
invocados sin necesidad de tener que instanciar ningún objeto de la clase.
En Java se introduce el concepto de interface, que no existe en alguna versiones de C++.
Una interface se utiliza para crear una clase base abstracta que contenga solamente las
constantes y las declaraciones de los métodos de la clase. No se permite que haya
variables miembro ni definiciones de métodos. Además, en Java también se pueden crear
verdaderas clases abstractas.
Java no soporta herencia múltiple, aunque se pueden utilizar las posibilidades que
ofrece el uso de interfaces para emplear las ventajas que ofrece la herencia múltiple,
evitando los inconvenientes que se derivan de su uso. La herencia simple es similar en
Java y en C++, aunque la forma en que se implementa es bastante diferente,
especialmente en lo que respecta a la utilización de los constructores en la cadena de
herencia.
Java no soporta la sentencia goto, aunque sea una palabra reservada. Sin embargo,
soporta las sentencias break y continue con etiquetas, que no están soportadas por
C++. Bajo ciertas circunstancias, estas sentencias etiquetadas se pueden utilizar como un
goto encubierto.
Java no soporta la sobrecarga de operadores, aunque la utilice internamente, pero no
está disponible para el programador. Tampoco soporta la conversión automática de
tipos, excepto en las conversiones seguras.
Al contrario que C++, Java dispone de un tipo String y los objetos de este tipo no pueden
modificarse. La cadenas que se encuentren definidas entre comillas dobles son
convertidas automáticamente a objetos String. Java también dispone del tipo
StringBuffer, cuyos objetos sí se pueden modificar, y además se proporcionan una serie
de métodos para permitir la manipulación de cadenas de este tipo.
18
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
•
•
•
•
•
•
•
•
•
Analista de Sistemas de Computación
Taller de Computación VI
Al contrario que C++, Java trata a los arrays como objetos reales. Disponen de un
miembro, length, que indica la longitud del array. Se genera una excepción cuando se
intenta sobrepasar el límite indicado por esta longitud. Todos los arrays son instanciados
en memoria dinámica y se permite la asignación de un array a otro; sin embargo, cuando
se realiza una asignación, simplemente tenemos dos referencias a un mismo array, no hay
dos copias del array, por lo que si se altera un elemento de un array, también se alterará
en el otro. A diferencia de C++, el tener dos "punteros" o referencias a un mismo objeto en
memoria dinámica no representa necesariamente un problema (aunque sí puede provocar
resultados imprevistos). En Java, la memoria dinámica es liberada automáticamente, pero
esta liberación no se lleva a cabo hasta que todas las referencias a esa memoria son
NULL o dejan de existir. Por tanto, a diferencia de C++, una zona de memoria dinámica
nunca puede ser inválida mientras esté siendo referenciada por alguna variable.
Java no soporta punteros, al menos en el sentido que atribuye C++, es decir, no permite
modificar el contenido de una zona de memoria apuntada por un puntero, o realizar
operaciones aritméticas con punteros. La mayor necesidad de uso de punteros deriva de la
utilización de cadenas y arrays, y esto se evita al ser objetos de primera clase en Java. Por
ejemplo, la declaración imprescindible en C++, char *puntero, para referenciar al primer
elemento de una cadena no se necesita en Java, al ser la cadena un objeto String.
La definición de clase es semejante en Java y C++, aunque en Java no es necesario el
punto y coma (;) final. El operador de ámbito (::) necesario en C++ no se usa en Java,
sino que se utiliza el punto (.) para construir referencias. Y, como no hay soporte de
punteros, el operador flecha (->) tampoco está soportado en Java. En C++, las funciones y
datos miembros se invocan utilizando el nombre de la clase y el nombre del miembro
estático conectados por el operador de ámbito. En Java, se utiliza el punto (.) para
conseguir el mismo propósito.
Al igual que C++, Java dispone de tipos primitivos como int, float, etc. Pero, al contrario
de C++, los tamaños de estos tipos son iguales independientemente de la plataforma en
que se estén utilizando. No hay tipos sin signo en Java, y la comprobación de tipos es
mucho más restrictiva en Java que en C++. Java dispone de un tipo boolean verdadero.
Las expresiones condicionales en Java se evalúan a booleano en vez de a entero como en
el caso de C++. Es decir, en Java no se permiten sentencias del tipo if( x+y ), porque la
expresión que va dentro del paréntesis no se evalúa a booleano.
El tipo char en C++ es un tipo de 8 bits que mapea el conjunto completo de caracteres
ASCII. En Java, el tipo char es de 16 bits y utiliza el set de caracteres Unicode (los
caracteres del 0 al 127 del set Unicode, coinciden con el set ASCII).
Al contrario que en C++, el operador desplazamiento (>>) es un operador con signo,
insertando el bit de signo en la posición vacía. Por ello, Java incorpora el operador >>>,
que inserta ceros en las posiciones que van quedando vacías tras el desplazamiento.
C++ permite la instanciación de variables u objetos de cualquier tipo en tiempo de
compilación sobre memoria estática o, en tiempo de ejecución, sobre memoria dinámica.
Sin embargo, Java requiere que todas las variables de tipos primitivos sean instanciadas
en tiempo de compilación, y todos los objetos sean instanciados en memoria dinámica en
tiempo de ejecución. Java proporciona clases de envoltura para todos los tipos primitivos,
excepto para byte y short, que permiten que estos tipos primitivos puedan ser
instanciados en memoria dinámica como objetos en tiempo de ejecución, si fuese
necesario.
C++ requiere que las clases y funciones estén declaradas antes de utilizarlas por primera
vez. Esto no es necesario en Java. C++ también requiere que los miembros estáticos de
una clase se redeclaren fuera de la clase. Esto tampoco es necesario en Java.
19
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
•
•
•
•
•
•
•
•
•
•
•
Analista de Sistemas de Computación
Taller de Computación VI
En C++, si no se indican valores de inicialización para las variables de tipos primitivos,
pueden contener basura. Aunque las variables locales de tipos primitivos se pueden
inicializar en la declaración, los datos miembros de tipo primitivo de una clase no se
pueden inicializar en la definición de la clase. En Java, se pueden inicializar estos datos
miembros de tipo primitivo en la declaración de la clase. También se pueden inicializar en
el constructor. Si la inicialización no se realiza explícitamente, o falla por lo que sea, los
datos son inicializados a cero (o su equivalente) automáticamente.
Al igual que ocurre en C++, Java también soporta constructores que pueden ser
sobrecargados. Y, del mismo modo que sucede en C++, si no se proporciona un
constructor explícitamente, el sistema proporciona un constructor por defecto.
En Java todos los objetos se pasar por referencia, eliminando la necesidad del constructor
copia utilizado en C++.
No hay destructores en Java. La memoria que no se utiliza es devuelta al Sistema a través
del reciclador de memoria, que se ejecuta en un thread diferente al del programa principal.
Esta es una de las diferencias extremadamente importantes entre C++ y Java.
Como C++, Java también soporta la sobrecarga de funciones. Sin embargo, el uso de
argumentos por defecto no está soportado en Java. Al contrario que C++, Java no soporta
templates, por lo que no existen funciones o clases genéricas(soportada en la versión
Java 6 ).
El multithreading, o multihilo, es algo característico de Java, que se proporciona por
defecto.
Aunque Java utiliza las mismas palabras clave que C++ para indicar el control de acceso:
private, public y protected, la interpretación es significativamente diferente entre C++ y
Java.
La implementación del manejo de excepciones en Java es más completa y bastante
diferente al empleado en C++.
Al contrario que C++, Java no soporta la sobrecarga de operadores. No obstante, los
operadores + y += son sobrecargados automáticamente para concatenar cadenas, o para
convertir otros tipos a cadenas.
Como en C++, las aplicaciones Java pueden hacer llamadas a funciones escritas en otros
lenguajes, llamadas métodos nativos. No obstante, los applets no pueden hacer llamadas
a métodos nativos.
A diferencia de C++, Java dispone de un sistema interno de generación de documentación.
Si se utilizan comentarios escritos de determinada forma, se puede utilizar la herramienta
javadoc para generar la documentación de la aplicación Java, e incluso se pueden
programar doclets para generar tipos específicos de documentación.
20
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Instalación de un entorno de desarrollo integrado (IDE) Eclipse
Material extraído de la pagina www.desarrolloweb.com/articulos/1692.php
La instalación y configuración de Eclipse, un entorno de desarrollo integrado (IDE) que
sirve para muchos lenguajes. Eclipse tiene interesantes utilidades para Java y además es
gratuito.
Como hemos dicho, un IDE puede hacernos el trabajo mucho más sencillo, sobretodo si nuestro
desarrollo ya va manejando un buen número de Clases. Además estos entornos nos permiten
mucha más versatilidad para depurar nuestros programas puesto que tienen debbugers mucho
más avanzados, cosa que nos viene de perlas para ir empezando en este mundillo.
Eclipse es un IDE de código abierto. Hay más herramientas similares de código abierto
disponibles pero esta es la que creo que tiene mejor relación calidad-facilidad de las que he
encontrado.
Su instalación es muy sencilla, podemos descargárnoslo de http://www.eclipse.org/ en forma de
archivo ZIP y solo tenemos que descomprimirlo en la carpeta donde queramos tenerlo instalado.
Para ejecutarlo solo hay que arrancar el fichero Eclipse.exe. Una vez arrancado lo único que nos
pedirá es que le demos la ruta por defecto donde queramos que eclipse nos vaya guardando los
proyectos que creemos:
Después de esto nos aparecerá la ventana principal de Eclipse:
21
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Si presionamos arriba a la derecha sobre el icono en forma de flecha curva, nos aparece el
mensaje ir al Workbench.
Ahora nos vamos a disponer a hacer un ejercicio pero con la ayuda de Eclipse. Como es evidente
para un ejercicio tan trivial nos va a suponer casi mas un gasto que un ahorro pero lo importante
es conseguir para empezar un manejo básico de Eclipse.
Eclipse puede usar varias perspectivas en su ventana principal
dependiendo del tipo de desarrollo que vayamos a realizar. Ahora
abriremos la perspectiva "Java":
Y nos aparece la siguiente pantalla:
22
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Es conveniente que todos los desarrollos que hagamos los hagamos dentro de un proyecto y por
mucho que nuestro ejercicio sea tan simple como útil a estas alturas, vamos a hacerlo como tal.
Por lo tanto vamos a crear un proyecto para nuestro desarrollo:
Para esto le damos a "File New Project". Como podemos ver hay muchos tipos de proyectos para
poder crear para nuestro desarrollo. Elegimos "Java project" y le damos a next. En la ventana en
la que estamos ahora podemos darle un nombre a nuestro proyecto y nos aparecen dos opciones
relativas a la organización de nuestro proyecto. Las dejamos tal y como está para que
simplemente nos coloque nuestros archivos .java y .class (fuentes y ejecutables java) en la
carpeta que hemos escogido para el entorno de trabajo al arrancar eclipse, y le damos a "Finish".
El siguiente paso es ir añadiendo nuestras clases al proyecto.
Continuamos pinchando con el botón derecho en la carpeta del proyecto que se nos ha creado en
la parte izquierda de la ventana principal podemos darle a "New Class".
Esta ventana tiene varias opciones que iremos entendiendo poco a poco. Por ahora simplemente
pondremos los nombres de la clase, del paquete donde queramos incluirla (podemos dejar el
paquete por defecto dejando este campo en blanco) y marcaremos las opciones que vemos en la
ilustración.
23
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Como hemos podido comprobar al escribir los nombres de la clase y del paquete nos avisa de
ciertas reglas para la nomenclatura de estos. Podemos avanzar que los nombres de las clases
siempre empiezan en mayúscula y que los de los paquetes en minúscula, ya comentaremos esto
más adelante y con más detenimiento.
Al darle a finalizar nos crea una plantilla que podemos ver en el centro de la pantalla. Esta área es
la que corresponde al editor y aquí es donde escribiremos nuestros programas en Java. La
plantilla creada nos añade las líneas básicas en el tipo de clase Java que hemos creado con todos
los pasos anteriores.
Escribimos lo que queda para que se nos quede tal y como en la figura. Es decir, introducimos
System.out.println ("Hola Mundo"); dentro del método "main" de la clase.
Ya solo nos queda ejecutar el programa para ver que funciona. Para hacerlo
funcionar podemos utilizar el menú "run" o directamente mediante los iconos de
la barra de herramientas.
Al ejecutar el "run" un asistente nos dará a elegir el tipo de ejecución que
queremos para nuestro código en Java. Simplemente escogemos "Java Application" en el menú
con un doble "clic" y nos creará un "apéndice" de configuración de ejecución para nuestro código
en concreto, como podemos ver:
En principio y sin más detalles le damos a "Run" y vemos los resultados:
Como podemos comprobar, abajo hay una pestaña que pone "console". Esa pestaña nos muestra
una consola que hace las veces de la línea de comandos desde la que ejecutamos nuestro
programa de Java en el primer ejemplo. Por tanto es en ese espacio en el que podemos ver la
salida del programa: "Hola Mundo".
24
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Ya tenemos un entorno completo para hacer nuestros pequeños desarrollos en Java y ya lo
hemos probado. A partir de aquí hay varias opciones para continuar:
Si estamos en windows tenemos que descomprimir el .zip de eclipse (Te crea la carpeta eclipse)
pero antes debemos tener instalado el SDK que esta en la pagina eclipse.org (sirve para compilar,
etc. indispensable)
Para descargar la última versión del entorno de desarrollo Eclipse y para consultar otros
tutoriales y documentos, visite el sitio web de eclipse: http://www.eclipse.org
Para descargar la máquina virtual Java J2SE JRE visite: http://www.java.sun.com
25
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Tutorial de Eclipse
Material extraído de la pagina:
www.eclipsetutorial.forge.os4os.org/in1.htm de Enrique Serrano Valle.
Parte 1: Entorno de Proyectos de Eclipse
En el entorno de desarrollo Eclipse todo archivo se almacena dentro de un proyecto. Esto quiere
decir que todo documento, carpeta, archivo de código fuente (.java) y código compilado (.class)
tiene que estar contenido dentro de un proyecto. Así pues, el primer paso antes de usar Eclipse
para programar en Java es comprender la estructura de proyectos de Eclipse.
Es necesario crear un nuevo proyecto no sólo para desarrollar un nuevo programa de Java, sino
para editar también archivos ya existentes (como por ejemplo, un programa ".java" almacenado en
un diskette). Para crear un nuevo proyecto, seleccione en la línea de menús principal "File > New
> Project...". También es posible seleccionar "New > Project..." haciendo clic derecho en cualquier
parte una vista de Eclipse (como por ejemplo, el Package Explorer o el Resource Navigator).
Hay varios tipos de proyectos de Eclipse que pueden ser creados:
•
Para crear o editar programas Java, un "Java Project" debería ser creado. Nótese que
dentro de un proyecto de Java también puede almacenarse toda la información
relacionada con el proyecto (la cual no tiene por qué reducirse estrictamente a código
fuente, sino que también puede contener documentación y otros archivos relacionados).
•
Los "Simple Project" sólo deberían crearse para almacenar documentos y otros archivos,
pero no código Java que se desee compilar. Por ello, siempre que se creen archivos
".java" sería recomendable crear un "Java Project".
•
Los "Plug-in Development Project" se usan para añadir nuevos módulos y funciones al
entorno Eclipse. Estos proyectos sólo son necesarios si se es un desarrollador de Eclipse.
•
Los proyectos de "EMF" se utilizan para crear modelos de análisis y diseño.
26
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Puesto que este tutorial se centra en utilizar Eclipse para programar en Java, escogeremos crear
un nuevo "Java Project" seleccionando "Java > Java Project" y haciendo clic en el botón "Next >"
del asistente de creación.
Tras esto, debe especificarse un nuevo nombre para el proyecto. Los proyectos profesionales se
nombran utilizando nombres de dominio dados la vuelta para evitar posibles conflictos de
nombrado. Sin embargo, para un proyecto de uso interno cualquier nombre descriptivo será
suficiente. En este ejemplo, se ha llamado al nuevo proyecto "Eclipse Tutorial".
Si se usa el directorio por defecto, los archivos del proyecto se almacenarán en el directorio
"[DirectorioDeInstalación]\workspace\[NombreProyecto]". También es posible especificar un
directorio diferente en el que guardar dichos contenidos.
27
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Pese a que en este punto es ya posible terminar la creación del nuevo proyecto haciendo clic en el
botón "Finish", es recomendable pulsar de nuevo el botón "Next >" para definir explícitamente de
esta manera una carpeta fuente para los archivos ".java" desde el principio. Las carpetas fuente
("Source Folders") almacenan los archivos de código fuente de Java (.java), de manera que
Eclipse sepa donde encontrarlos y pueda realizar la compilación automática de los mismos cada
vez que un archivo sea guardado.
Para crear dicha carpeta fuente seleccione la pestaña de "Source" y pulse el botón "Add
Folder...". Seleccione el proyecto recientemente creado y pulse el botón "Create New Folder". Un
buen nombre para esta carpeta fuente podría ser sencillamente "src". Tras especificar dicho
nombre, pulse "Ok". A la pregunta de si desea actualizar la carpeta de salida de archivos
compilados, debería responder afirmativamente. De este modo, los archivos ".class" que resulten
de la compilación de los ".java" almacenados en la carpeta fuente irán a parar a la carpeta "\bin".
Pulse el botón "Finish" para terminar el proceso de creación del nuevo proyecto. Si se nos
pregunta si deseamos pasar a la perspectiva de Java, deberíamos responder afirmativamente.
El proyecto recién creado debería parecerse a este, tal y como lo
muestra la vista "Navigator".
En Eclipse 3.0 la creación de proyectos es un tanto diferente a
Eclipse 2.x. Aún puede definirse una carpeta cualquiera para
almacenar los proyectos. Pero ahora los pasos anteriormente
expuestos acerca de la
creación de una estructura adecuada de carpetas fuente y
destino pueden omitirse, ya que en la nueva versión de Eclipse basta con marcar la opción
"Create separate source and output folders" para construir de forma automática la estructura de
archivos deseada.
28
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Como ya se mencionó anteriormente, para editar un elemento existente debería ser primero
importado dentro de un proyecto de Eclipse. Esto puede hacerse desde el menú "File > Import..."
o bien pulsando con el botón derecho en cualquier punto de la vista del "Package Explorer" o del
"Resource Navigator". Para seleccionar un archivo o directorio hay que seleccionar "File system"
en el sub menú de importación. Entonces sólo habrá que recorrer los directorios marcando los
archivos que se deseen importar así como el proyecto y la carpeta destino.
Es importante tener en cuenta que todo elemento que se importa en Eclipse se duplica. Esto
significa que borrar la copia que Eclipse esté manejando no borrará el archivo original, de manera
que se seguirá teniendo una copia de reserva. Sin embargo, si se usa la opción de importar un
proyecto de Eclipse ya existente, los contenidos de dicho proyecto serán duplicados. Así que hay
que ser especialmente cuidadoso al borrar proyectos importados del entorno de trabajo de
Eclipse, ya que es posible que otras copias de backup de dicho proyecto no existan.
Todo archivo creado mediante la utilización de Eclipse puede ser exportado como un archivo
normal (seleccionando Export... > File System), como un archivo ".jar" e incluso como archivos
comprimidos en ".zip". El proceso que hay que seguir es similar al proceso recientemente
explicado para importar archivos, sólo que seleccionando ahora la opción "Export".
También es posible copiar, cortar y pegar archivos y carpetas desde Eclipse hasta los directorios
del sistema operativo (por ejemplo, del explorador de Windows) y viceversa (seleccionando un
archivo, pulsando CTRL+C, seleccionando la carpeta destino dentro de Eclipse y pulsando
CTRL+V).
29
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Parte 2: Crear Elementos de Java
Una vez que se ha creado un nuevo proyecto, es hora de aprender cómo crear los diversos
elementos de Java. Para seguir los pasos que se exponen a continuación es necesario cambiar a
la "Perspectiva Java" (si no se ha hecho ya) seleccionando "Window > Perspectives > Java". La
perspectiva de Java contiene las vistas y editores más útiles a la hora de
crear nuevos programas en Java.
Haciendo clic derecho en la carpeta fuente recientemente creada (por
ejemplo, "src") dentro de la vista del Package Explorer, aparecerá un menú
contextual. Seleccionando "New >" en dicho menú se mostrará una lista
con los diversos elementos de Java que pueden ser creados.
Algunos de dichos elementos pueden ser creados también realizando clic
sobre los iconos del menú de la parte superior de la pantalla.
Java Class
Las clases de Java son los archivos ".java" que contienen el código fuente y que serán
posteriormente compilados en archivos ".class". Estos archivos Java tienen que ser almacenados
dentro de la carpeta fuente recientemente creada (por ejemplo, "src"). Pulse "New > Class" para
abrir la ventana de creación de clases.
La carpeta fuente especificada debería ser la carpeta recientemente definida (src). Si no se
especifica ningún paquete para contener las clases Java, se guardarán dentro de un paquete por
defecto. El último campo obligatorio que debería ser rellenado antes de proceder a la creación de
la clase Java es el propio nombre de la clase. Las convenciones de Java sugieren que el nombre
30
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
de una clase debería comenzar con mayúscula. En este tutorial se ha usado el nombre
"ExampleClass".
También existen otros modificadores que pueden ser fácilmente añadidos a una clase desde el
mismo momento de su creación. Sin embargo, estos elementos también podrían ser añadidos
manualmente en otras fases más avanzadas del proceso de desarrollo. Si se pretende que la
nueva clase extienda (herede de) otra clase existente, se debería especificar la clase "padre"
dentro del campo "Superclass". El botón "Browse..." es de gran utilidad a la hora de encontrar
clases que sean posibles candidatas para ser extendidas. Aunque Java sólo soporta herencia
única (sólo puede extenderse de una única clase) sí que es posible que una clase implemente
más de una interfaz. Una vez más, el botón "Browse..." simplifica la tarea de seleccionar interfaces
implementadas.
Si se desea que la nueva clase contenga un método "main" (es decir, el punto inicial de ejecución
del programa), puede añadirse dicho método automáticamente sólo con marcar la casilla con la
opción apropiada. También pueden implementarse de esta manera los constructores de la
superclase y todos los métodos abstractos heredados. Esta última opción es muy útil si se desea
instanciar la clase puesto que para esto todo método abstracto debería estar implementado.
Es interesante destacar que los archivos compilados ".class" sólo son visibles en la ventana
"Navigator", abierta por defecto dentro de la perspectiva "Resource". Puesto que la perspectiva de
Java no abre esa ventana por defecto, los ficheros .class no serán visibles en la vista del Package
Explorer. Sin embargo, basta con escribir y guardar un archivo ".java" para que se cree un archivo
".class" resultante de compilar el archivo fuente anterior.
File
Los archivos que se crean a través de este menú suelen almacenar notas e información general.
Otros archivos tales como archivos de configuración, archivos "build" de ant y similares también
pueden crearse de esta manera. Crear un nuevo archivo es tan sencillo como pulsar "New > File",
seleccionar el proyecto y carpeta adecuados en que se desea crear el archivo, dar nombre al
nuevo archivo y pulsar el botón "Finish". Por defecto, archivos los archivos genéricos se abren en
el editor de texto.
Folder
Las carpetas se utilizan para almacenar y organizar archivos. Como ya se ha mencionado
anteriormente, una carpeta normal no es exactamente lo mismo que una carpeta fuente. Una
práctica recomendada de programación es crear explícitamente una carpeta fuente donde
31
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
almacenar los archivos .java con el código fuente (src), una carpeta de salida donde guardar el
código compilado (bin) y una carpeta para guardar toda la documentación relacionada (docs).
Para crear una nueva carpeta basta con especificar el nombre de la nueva carpeta y la carpeta
que la contiene.
Interface
Las interfaces son casos particulares de las clases de Java, que carecen de implementación y que
se espera que otras clases implementen. Usualmente funcionan como una especie de contrato,
indicando lo que la clase implementada debería hacer, mientras que los detalles de más bajo nivel
corresponderían al implementador. El procedimiento de creación de interfaces es muy similar al
procedimiento de creación de nuevas clases ya detallado. Aunque una interfaz no puede
implementar ninguna interfaz, sí que puede extender otra interfaz mediante una relación de
herencia.
32
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Package
Los paquetes se declaran para almacenar y organizar los archivos de Java. El nombre de un
paquete consta usualmente de varias partes separadas por puntos. Cada una de estas partes
será un directorio nuevo dentro del sistema de archivos. Las clases que se creen dentro de un
paquete determinado en Eclipse llevarán añadida automáticamente la declaración "package" en
su código fuente.
Scrapbook Page
Estas "hojas de sucio" son una forma sencilla de probar fragmentos de código antes de añadirlos
al programa final. Sólo hay que crear una "Scrapbook Page" dentro de la carpeta deseada y
escribir el código dentro de ella. No hace falta meter el código dentro de un método main para
ejecutarlo.
En Eclipse 3.0 las "scrapbook pages" no se muestran directamente en el menú
contextual. Para crear una nueva hoja de sucio seleccione "New > Other > Java > Java
Run/Debug > Scrapbook Page". Otra diferencia respecto de las versiones 2.x es que en
Eclipse 3.0 sí que están habilitadas las funciones de auto completar dentro de las
scrapbook pages.
Antes de intentar ejecutar el código añadido es necesario importar las
clases usadas. Para ello basta con realizar clic derecho sobre cualquier
parte de la hoja y seleccionar "Set Imports" del menú contextual. Ahí es
donde hay que especificar los tipos y paquetes que es necesario añadir.
Para ejecutar el código recién creado es necesario seleccionarlo
pinchando con el botón izquierdo del ratón y arrastrando hasta tener todo
el código seleccionado. Luego hay que pulsar el botón derecho del ratón
sobre este código seleccionado y ejecutar la opción "Execute" del menú
contextual. La salida estándar de dicho proceso se mostrará dentro de la
vista "Console", y otros mensajes de error se mostrarán dentro de la
misma hoja de sucio.
Una vez que se ha completado la prueba habría que pulsar el botón "Stop
Evaluation" del menú contextual.
Puesto que el editor de estas hojas de prueba no proporciona tantas
funciones de ayuda a la programación como el editor de código Java, una
práctica recomendada es escribir el código original en el editor de Java y
luego pegarlo en esta hoja de pruebas.
Source Folder
Como ya se vio, las carpetas fuente son un tipo especial de carpetas destinadas a almacenar los
archivos fuentes de Java (es decir, los de extensión ".java"). Estos archivos de código serán
automáticamente compilados en archivos ".class". Puesto que todo proyecto de Java debería
tener una carpeta fuente, es una práctica recomendada organizar esto desde el primer momento,
como se explicó en la primera parte de este tutorial.
33
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Parte 3: Funciones Útiles de Programación
Hasta ahora se han expuesto conceptos básicos del funcionamiento general de Eclipse. Es hora
de presentar las funciones de ayuda a la programación de Eclipse. Es en esta parte donde se dará
cuenta de cómo usar Eclipse para programar en Java ahorra gran cantidad de tiempo y esfuerzo.
Mientras que las partes anteriores de este tutorial eran necesarias, esta será la más interesante.
Compilar y Detectar Errores
Es importante tener en cuenta que en Eclipse los errores de compilación se muestran en tiempo
real subrayando el fragmento de código adecuado con una línea roja. Y además el entorno
automáticamente compila los archivos salvados. Así pues, no será necesario pasar por el tedioso
y lento proceso de compilar - observar los errores - corregir los errores.
Los errores pueden encontrarse fácilmente porque se muestran además como marcas rojas en el
margen derecho del editor de código Java. También los errores y advertencias presentes en
archivos ya guardados se muestran dentro de la vista de tareas (Tasks View), como se detallará
posteriormente. Haciendo click en cualquiera de los dos tipos de marcadores de error llevará
automáticamente hasta la línea en que el error está presente. Las advertencias (warnings) se
muestran de la misma manera, pero con marcas amarillas.
Icono de Bombilla = Autocorregir
Hemos visto como Eclipse detecta y marca todo error y advertencia de compilación. Eclipse
habitualmente permite autocorregir los posibles errores haciendo clic en el icono de bombilla
presente en el margen izquierdo del editor de código. Así pues, aparecerá una ventana mostrando
todas las opciones. Seleccionar una opción mediante los cursores del teclado o dejar el punto del
ratón sobre dicha opción abrirá una nueva ventana mostrando detalladamente las modificaciones
de código que la autocorrección efectuaría. Basta con pulsar la opción seleccionada (o pulsar
ENTER) para hacer que Eclipse lleve a cabo la corrección automatizada.
34
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
CTRL + Espacio = Autocompletar
Una vez que conozca la útil función de autocompletar la usará continuamente. A través de los
siguientes ejemplos prácticos aprenderá cuales son las situaciones más comunes en que esta
función de ayuda a la programación resultará muy útil.
•
Nombres de Clases
Crear referencias a otras clases dentro de la clase actual es una tarea de programación habitual.
Sin embargo, algunas clases de Java tienen nombres muy largos que son difíciles de recordar.
Además, es necesario añadir declaraciones de importación para poder resolver dichas referencias
a clases a la hora de compilar.
Usar "CTRL + Espacio" tras escribir los primeros caracteres del nombre de una clase Java
mostrará las posibles alternativas. Puede seleccionar cualquiera de ellas simplemente realizando
clic izquierdo del ratón. Nótese que la sentencia de importación correspondiente se añadirá de
forma automática. Las clases se marcan con una "C" verde mientras que las interfaces se marcan
con una "I" morada. El paquete al que pertenece la clase se muestra también, permitiendo de este
modo evitar posibles confusiones.
•
Atributos y Variables Locales
Cuando se define una clase es normal dar nombres inventados a sus atributos y a las variables
internas de los métodos. Pero en ocasiones resulta difícil recordar el nombre exacto. Tras escribir
los primeros caracteres del atributo o de la variable local, pulsar "CTRL + Espacio" mostrará las
posibles alternativas. Este proceso es muy similar al de autocompletar el nombre de las clases
recientemente expuesto. Las variables locales se marcan con el icono de una "L" gris, mientras
que los atributos se marcan con un icono que puede variar según la visibilidad del atributo.
•
Métodos y Constructores
Una vez que se ha creado un objeto Java pueden invocarse los métodos correspondientes a su
clase. Sin embargo, es bastante habitual olvidar el nombre de un método en concreto, o incluso
35
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
los tipos de sus parámetros y su orden. Este problema puede solucionarse fácilmente pulsando
"CTRL + Espacio" tras escribir el nombre del objeto seguido de un punto, lo cual mostrará una
ventana con las posibles alternativas. Pulsar sobre la alternativa escogida añadirá la signatura del
método al objeto.
También es posible autocompletar la signatura de los constructores pulsando "CTRL + Espacio"
tras escribir (o autocompletar) el nombre de la clase seguido de un signo de apertura de
paréntesis, "(".
Escribir las primeras letras del modificador de un método tal como "public" o "private" y pulsar
"CTRL + Espacio" le permitirá crear automáticamente una plantilla del método. Pulsar el tabulador
permite saltar de un campo de la plantilla a otro, de manera que se pueda completar el tipo de
retorno, el nombre del método y sus parámetros.
•
Bucles
Los bucles suelen estar presentes en todos los programas. Aunque crear un nuevo bucle puede
no ser una tarea muy compleja, Eclipse proporciona algunas funciones de auto completado que
pueden acelerar considerablemente el proceso. Basta con escribir "do", "while" o "for" y pulsar
"CTRL + Espacio" para mostrar las posibles opciones. Si el bucle ha sido creado con el propósito
de iterar sobre un array de elementos, seleccionar esta opción intentará autocompletar incluso el
nombre del array.
36
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
•
Analista de Sistemas de Computación
Taller de Computación VI
Etiquetas de Javadoc
Mientras que los comentarios internos del programador se indican con una "//", los comentarios de
Javadoc se inician con un "/**". Tras crear un método, añadir "/** + ENTER" sobre la signatura del
método autocompletará información de Javadoc tal como "@param [nombreParámetro]
[comentario]", "@return [descripciónDatosDevueltos]" y "@throws [tipoExcepción] [comentario]".
Pulsar "CTRL + Espacio" dentro de un bloque "/** ... */" mostrará toda la lista de etiquetas Javadoc
posibles.
Menú "Source"
Mediante un clic derecho en el editor de código se mostrará un menú contextual. Las funciones
más importantes de su submenú "Source >" son las siguientes:
•
Comment and Uncomment
Seleccionando esta opción se puede comentar o quitar la marca de comentario del código. Esto
es especialmente útil usado con bloques de código, puesto que permite no ejecutar
temporalmente partes del código sin llegar a eliminarlas. Las teclas rápidas asociadas son "CTRL
+ /" para añadir comentarios y "CTRL + \" para eliminar dichas marcas de comentario del bloque
de código seleccionado.
En Eclipse 3.0 estos comandos han sido sustituidos por "Toggle Comment".
Seleccionando este nuevo comando del menú "Source" es posible cambiar el estado del
código seleccionado, pasándolo de comentario a código o viceversa. También la nueva
opción "Add Block Comment" marcará el código como comentario rodeándolo con los
símbolos "/*" y "*/". Mientras que seleccionar un bloque de código comprendido entre esos
símbolos de comentario hará que en aparezca la opción "Remove Block Comment", la cual
eliminaría los símbolos de comentario.
•
Format
La función de formateado automático de código automáticamente indenta el código de la forma
adecuada, además de llevar a cabo otras funciones de representación. Es una forma rápida de
conseguir tener un código ordenado y comprensible.
37
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Las opciones del formateador de código pueden adaptarse a las preferencias personales usando
"Window > Preferences > Java > Code Formatter". Las teclas rápidas asociadas son "CTRL +
Mayúsculas + F".
Nótese que las funciones de identación de código permiten identificar rápidamente qué
fragmentos de código son afectados por una condición o bucle determinados, por ejemplo. Pero
también es útil situar el cursor tras un paréntesis o llave, porque de esta forma se marcará el
paréntesis asociado que abre o cierra el bloque con un cuadrado gris. Así pues, se verá de un
vistazo qué código se encuentra realmente comprendido entre los dos paréntesis.
Eclipse 3.0 permite especificar opciones avanzadas de formateo de código. La página de
preferencias que permite configurar el formateo de código se ha trasladado a "Window >
Preferences > Java > Code Style > Code Formatter". Pese a que las opciones se pueden
configurar de acuerdo a las preferencias personales, ya vienen configuradas por defecto para
cumplir las convenciones de Java.
•
Organise and Add Imports
Aunque las sentencias de importación adecuadas se muestran siempre cuando se usan las
funciones de autocompletar código para completar el nombre de una clase Java, nuevas
sentencias de importación pueden añadirse en cualquier momento usando la función "Add Import".
Pulsar "Organise Imports" eliminará automáticamente todas las declaraciones de importación no
utilizadas, incrementando la eficiencia del código. El método abreviado del teclado es "CTRL +
Mayúsculas + O".
•
Override and Implement Methods
Seleccionando esta opción de sombrear o
implementar métodos abrirá una ventana de menú en
la cual se podrán marcar los métodos de la
superclase cuya signatura se desea que se añada.
La opción "Add Constructors from Superclass"
permitirá especializar todos los constructores usados.
38
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
•
Analista de Sistemas de Computación
Taller de Computación VI
Generate Getter and Setter
El lenguaje Java permite especificar diferentes niveles de visibilidad de atributos. Sin embargo, en
programación orientada a objetos, los atributos internos de una clase deberían ser siempre
privados. Esto quiere decir que no debería poder realizarse ningún tipo de modificación directa del
atributo de una clase desde otra clase externa. A causa de esto, la única manera de acceder a un
atributo privado para leer su valor o bien para darle un nuevo valor sería utilizando un método
accesor o modificador que sea público. Seleccionando "Generate Getter and Setter" una ventana
mostrando los posibles métodos que podrían crearse de acuerdo con los atributos definidos
aparecerá. Entonces los métodos necesarios podrían crearse simplemente seleccionándolos y
pulsando "Ok".
•
Surround with try/catch block
Para utilizar esta opción es necesario tener seleccionado de antemano un fragmento de código
pinchando con el botón izquierdo del ratón (o pulsando Mayúsculas) y arrastrando. Activar esta
opción creará un bloque "try" alrededor del código seleccionado. Tras este bloque se añadirán
automáticamente los bloques "catch" adecuados, los cuales atraparán toda posible excepción que
el código rodeado pueda lanzar. Por defecto se añade una sentencia de traza dentro de esos
bloques "catch" de manera que sea posible identificar inmediatamente dónde se lanzó la
excepción.
39
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Nótese también que, cuando una excepción no es atrapada, aparecerá como texto en rojo (de la
salida de error estándar) en la vista "Console". Pulsar la línea de código en que se muestra en qué
línea tuvo lugar la excepción llevará directamente a ese punto del programa en el editor de código.
Menu Refactor
Haciendo clic derecho en el editor de código mostrará el menú contextual. A continuación se
muestran las funciones más interesantes del sub menú "Refactor >".
•
Rename
Para invocar la función de renombrado hay que tener previamente seleccionado un elemento.
Marcar la opción de "update references" actualizará toda referencia al nuevo elemento
renombrado. Usando esta opción de "Refactor > Rename..." es como deberían renombrarse todos
los elementos incluyendo los archivos ".java". Puesto que así se actualizan todas las referencias
no aparecerán problemas a la hora de compilar. Al renombrar determinados elementos será
posible actualizar también referencias en comentario de Javadoc, comentarios normales y
cadenas de caracteres entrecomilladas, lo cual también puede resultar bastante útil. La opción de
"Preview" permite asegurarse de que no habrá ningún tipo de error durante la operación de
renombrado.
40
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
•
Analista de Sistemas de Computación
Taller de Computación VI
Move
Antes de seleccionar "Refactor > Move...", el archivo fuente o elemento que se desea mover
deberá haber sido seleccionado. Entonces será sólo necesario seleccionar el destino de manera
que se lleve a cabo la operación de mover. Esta es la forma correcta de mover archivos ya que
evita problemas futuros con referencias y rutas de compilación.
•
Change Method Signature
Para modificar la signatura de un método es posible usar esta opción en lugar de hacerlo
manualmente. Sólo hay que colocar el cursor dentro del método cuya signatura se desea cambiar.
Esta es una forma rápida de cambiar la visibilidad, el tipo de retorno, los parámetros y su orden.
Los nuevos parámetros se añaden pulsando el botón "Add" y se modifican pulsando en botón
"Edit".
•
Pull Up and Push Down
Si la clase actual extiende o es extendida por otra clase, puede ser interesante mover algunos
elementos a la superclase (pull up) o a la subclase (push down) respectivamente. Seleccionar el
elemento y la opción adecuada llevará a cabo esta operación de forma automatizada.
41
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Consultar la Documentación
La documentación Javadoc del código que se esté actualmente programando puede ser
consultada en tiempo real simplemente colocando el cursor o el puntero del ratón sobre el
elemento elegido. Para expandir la ventana con esta documentación basta con pulsar la tecla de
función F2.
Ladocumentación Javadoc externa (como por ejemplo, la documentación oficial de las clases de
Java) puede consultarse modificando dentro de las preferencias del JRE instalado ("Window >
Preferences > Installed JRE") con "Edit" la ubicación del Javadoc. De esta manera, dejando el
cursor sobre el nombre de la clase y pulsando "Mayúsculas + F2" se abrirá la documentación por
el punto adecuado.
Eclipse 3.0 dispone de una nueva vista de Javadoc ("Window > Show View... > Java > Javadoc").
Dicha vista muestra la documentación Javadoc asociada al elemento sobre el que está situado el
cursor.
Archivos JAR Importar
En ocasiones puede ser necesario importar algunos archivos Jar no incluidos por defecto en el
JRE estándar para que el proyecto pueda compilar. Basta con pulsar el botón derecho del ratón
sobre la carpeta adecuada, elegir "Properties > Java Build Path", seleccionar la pestaña
"Libraries", pulsar el botón "Add External Jars" y seleccionar el archivo ".jar" o ".zip". El nuevo Jar
añadido será visible en la ventana Package Explorer como un pequeño frasco.
42
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Parte 4: Vistas de Eclipse
La interfaz de usuario de Eclipse consta de dos tipos de elementos: vistas y editores. Mientras que
los editores normalmente permiten realizar una tarea completa, las vistas proporcionan funciones
de apoyo. En este punto del tutorial ya debería tener bastante práctica usando el editor de código
cuyas funciones principales se detallaron en la parte 3. Ahora, las vistas más interesantes de
Eclipse se explicarán con detalle, junto a algunos consejos de cómo navegar a través de los
editores.
Perspectivas-Restaurar Vistas
Una perspectiva de Eclipse es una agrupación de vistas y editores de manera que den apoyo a
una actividad completa del proceso de desarrollo software. Sin embargo, es posible crear
perspectivas propias añadiendo nuevas vistas y cambiando su distribución en la pantalla. Las
perspectivas pueden seleccionarse haciendo clic en los iconos de perspectiva del lateral izquierdo
o eligiendo "Window > Open Perspective" del menú. Las perspectivas son:
Resource: esta perspectiva está estrechamente relacionada con el sistema de archivos
puesto que representa la localización física de los recursos almacenados dentro de los
proyectos
Java: esta perspectiva se centra en tareas de programación, mostrando paquetes, clases,
métodos y atributos en sus vistas asociadas.
Plug-in development: la perspectiva de desarrollo de plug-in permite a los
desarrolladores añadir nuevos módulos de Eclipse.
Install/Update: permite gestión de la configuración. Muestra los componentes instalados
así como sus versiones y conflictos.
Debug: relacionada con la tarea de depuración. Se centra en los procesos ejecutados,
puntos de ruptura, variables, salida, etc.
Java Browsing: esta perspectiva permite ojear rápidamente código, proyectos, paquetes
y jerarquías.
En Eclipse 3.0 los iconos de perspectiva se han trasladado a la esquina superior derecha.
También hay ahora un botón etiquetado como "Open a Perspective" que permite acceder
rápidamente a otras perspectivas. Otro cambio es que la perspectiva "Install/Update" ha sido
eliminada, y puede accederse a sus funciones seleccionando "Help > Software Updates".
43
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Tareas
La vista de tareas ("Tasks View") permite una rápida gestión de tareas pendientes. Seleccionando
"Window > Show View > Tasks" se muestra esta vista. Pueden añadirse nuevas tareas haciendo
clic en el botón "Add task". Nótese que la prioridad de la tarea y su estado también pueden
modificarse sin más que hacer clic en dichos campos. También los errores y las advertencias de
los archivos con código guardados se muestran en esta vista. Haciendo clic en la descripción de
un error llevará hasta el punto exacto del código en que se encuentra dicho error.
Añadir "TODO [descripción]" a un archivo Java añadirá una nueva tarea "por hacer" a la vista de
tareas. Una vez más, hacer clic sobre su descripción conducirá hasta el punto exacto en que la
etiqueta "TODO" se añadió. Dentro del editor de código Java las etiquetas de "TODO" pueden
encontrarse rápidamente ya que se muestran como pequeñas marcas azules en el margen
derecho. Hacer clic sobre estas marcas llevará directamente a la línea etiquetada. Nótese que
varios procesos automatizados insertan estas etiquetas "TODO" para asegurarse de que el código
autogenerado es revisado y comentado.
Haciendo clic derecho en cualquier punto de la vista de tareas se mostrará un menú contextual
que permitirá realizar de forma rápida cualquier actividad relacionada con la gestión de las tareas
definidas.
Navigator
La ventana del navegador de recursos permite echar un vistazo a la estructura de archivos de los
proyectos definidos. Nótese que esta vista es la única que muestra la carpeta de salida ("bin") así
como los archivos Java compilados (".class").
44
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Package Explorer
La vista del explorador de paquetes muestra la estructura lógica de paquetes y clases Java
almacenados en los distintos proyectos. las carpetas fuente (que deben almacenar los archivos
fuente ".java") se muestran aquí decoradas con el icono de un paquete contenido. Los archivos
Java también pueden ser expandidos de modo que muestren sus métodos y atributos internos al
pulsar el botón "+".
• Working Set
Un conjunto de trabajo es un grupo de elementos que se muestran en las distintas vistas de
eclipse. Estos conjuntos de trabajo se usan como filtros que permiten separar claramente los
diferentes proyectos en que se está trabajando. Esto puede resultar muy útil cuando se está
trabajando simultáneamente en varios proyectos no directamente relacionados entre sí. Organizar
los distintos proyectos en grupos de trabajo acelerará el proceso de buscar los elementos
deseados y reducirá la confusión visual.
Para definir un conjunto de trabajo, basta con pulsar en el icono de menú del Package Explorer (el
icono de un triángulo invertido) y seleccionar "Select Working Set". Aquí se permitirá nombrar un
nuevo conjunto de trabajo, así como seleccionar sus recursos relacionados y editar o quitar otros
conjuntos de trabajo existentes. Todos los conjuntos de trabajo disponibles se muestran
directamente la próxima vez que se pulse el icono triangular de menú.
Es importante tener en cuenta que crear un nuevo proyecto cuando un conjunto de trabajo está
siendo usado hará que el nuevo proyecto no se muestre dentro de las vistas de Eclipse. Para
poder ver el proyecto recién creado, será necesario editar el conjunto de trabajo actual ("Menú de
la vista > Select Working Set > Edit" o directamente "Edit Current Working Set") y seleccionar el
nuevo proyecto para que se muestre.
45
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Outline View
La vista de resumen es una forma rápida de ver qué métodos i atributos se encuentran definidos
dentro de una clase de Java. Los iconos asociados proporcionan información adicional de acuerdo
con la visibilidad del atributo o método en cuestión. Y sólo con hacer clic en cualquiera de estos
iconos conducirá a la línea de código exacta en que dicho atributo o método está definido. La vista
de resumen es una herramienta esencial para entender y navegar archivos Java voluminosos.
Hierarchy View
La vista de jerarquía muestra las relaciones de herencia presentes entre distintos elementos de
Java. Haciendo clic derecho en el nombre de una clase Java en el editor de código y
seleccionando "Open Type Hierarchy" abrirá esta vista de jerarquía. La tecla rápida asociada es
"F4"
En Eclipse 3.0 se ha añadido la opción "Open Call Hierarchy" al menú contextual del editor de
código. Tras seleccionar un método, al hacer clic en esta opción se abrirá una vista que mostrará
dónde es usado dicho método. Las teclas rápidas asociadas son "CTRL + ALT + H".
46
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Fast Views
Arrastrar una vista hasta el margen izquierdo (hasta que aparezca un icono de carpetas apiladas)
convierte esta vista en una "vista rápida". Pulsar el icono de la vista rápida hará que dicha vista se
muestre, mientras que volver a pulsarlo (o pulsar en cualquier otro punto de la pantalla) hará que
se oculte. Mediante un clic derecho en el icono de la vista rápida y seleccionando "Fast View"
restaurará la vista a su posición original.
El área por defecto en que se apilan las vistas rápidas ha sido cambiada en Eclipse 3.0. Ahora es
un pequeño rectángulo situado en la esquina inferior izquierda de la pantalla. Así pues, las vistas
rápidas se crean ahora arrastrando la vista dentro del rectángulo hasta que aparece un icono de
una flecha dentro de un cuadrado. No obstante, la zona en que almacenar las vistas rápidas
puede cambiarse de sitio colocando el cursor sobre ella hasta que se transforma en un cursor con
cuatro flechas, arrastrando y depositando la zona en el lugar deseado.
Search View
Para realizar una búsqueda dentro de Eclipse, el menú "Search" de la barra superior de menús
debería ser seleccionado. También se pueden lanzar búsquedas
pulsando el icono de linterna.
Hay varios tipos de búsquedas dentro de Eclipse.
La búsqueda de archivos "File Search" es una búsqueda textual
que puede ser ejecutada sobre archivos de todo tipo. Es
equivalente a una búsqueda tradicional.
La búsqueda de ayuda "Help Search" efectúa búsquedas dentro
de la ayuda de Eclipse.
La búsqueda de Java "Java Search" es similar a la búsqueda de archivos pero proporciona
funciones adicionales para buscar en archivos Java. Así pues, permite buscar explícitamente por
tipos, métodos, paquetes, constructores y campos, usando restricciones de búsqueda adicionales
(como por ejemplo, buscar sólo el punto del código en que se declararon los elementos
coincidentes).
47
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Es importante comprobar que la búsqueda se efectúa sobre los ficheros apropiados. Esto puede
definirse usando el campo "scope". "Workspace" hace referencia al entorno de trabajo completo.
"Selected Resources" son sólo los archivos seleccionados (es posible seleccionar más de un
archivo haciendo clic izquierdo en ellos mientras se mantiene pulsada la tecla CTRL). "Working
Set" es un conjunto de trabajo previamente definido.
Los resultados de la búsqueda aparecen en la vista "Search". También se subrayan en gris dentro
del editor de código, con una flecha amarilla en el margen izquierdo y con una marca gris en el
margen derecho. Haciendo clic en cualquiera de estos elementos seremos conducidos al punto en
que la cadena buscada se encontró.
Los resultados de búsqueda se muestran como un árbol jerárquico en Eclipse 3.0
Navegar por las Vistas y los Editores
Hasta ahora hemos visto una introducción de cómo utilizar las vistas de Eclipse y cómo dichas
vistas ayudan a manejar la información. Es hora de explicar algunas funciones de navegación
adicionales que serán útiles para encontrar rápidamente la información deseada y que permitirán
presentarla adecuadamente en los diversos editores y vistas.
Maximizar una Vista o Editor
Basta con hacer doble clic en el título de una ventana para maximizarla. Doble clic en el título de
nuevo hará que las dimensiones y posición de la ventana sean restauradas a las que tenía
originalmente. En Eclipse 3.0 se ha añadido "CTRL + M" como tecla rápida asociada a maximizar
o restaurar la ventana del editor actual.
48
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Ir al Último Cambio
El icono del menú representado como "una flecha con un asterisco" sirve para colocar el cursor en
el último punto del código que fue modificado dentro del editor activo. Es habitual que tras cambiar
algo de código (por ejemplo, tras escribir algunas instrucciones nuevas) movamos el cursor a otra
línea para revisar otra parte del programa. Si deseáramos volver al punto en que añadimos el
último cambio (que suele ser el lugar por el que "íbamos programando") tendríamos el problema
solucionado con sólo pulsar este icono de "ir al último lugar editado". Las teclas rápidas asociadas
son "CTRL + Q".
Acciones de Navegación de los Editores
Pero, ¿qué haríamos si quisiéramos volver a un punto del programa en el que no
introdujimos ningún cambio (es decir, en el que situamos el cursor pero en que no
escribimos o borramos ningún carácter)? O, ¿y si quisiéramos regresar al lugar en que
estuvimos justo antes de editar algo en otro lugar? Las flechas de navegación del menú
resolverán estos problemas. Basta con pulsar la flecha de "navegar hacia atrás" para
regresar a puntos previamente visitados del programa.
Y pulsando la flecha de "navegar hacia delante" recorreremos el historial de lugares visitados
hacia los puntos más recientes.
De hecho, estas útiles acciones funcionan de forma muy similar a como lo hacen los botones de
"atrás" y "adelante" de un navegador web. La opción de "atrás" sólo se activa si existen puntos de
programas que se visitaron previamente. Y la opción de "adelante" se activa tras haber pulsado el
botón de "atrás". También hay que tener en cuenta que pulsando en el pequeño triángulo negro
que se encuentra junto a las flechas de navegación desplegaremos un menú que muestra otros
archivos (distintos del abierto en la ventana activa del editor) en los que se encuentran otros
puntos visitados accesibles. Por cierto, para cambiar la ventana activa del editor a otras ventanas
abiertas existe un método abreviado: "ALT + F6" (comando de "siguiente editor").
Las útiles teclas rápidas asociadas a estas acciones de navegación son "ALT + IZQUIERDA" para
navegar hacia atrás y "ALT + DERECHA" para navegar hacia delante.
Revisar Problemas
Los botones de "Ir al siguiente/anterior problema" permiten recorrer uno tras otro los problemas
pendientes que aparecen en el editor actual.
49
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Aunque esta es una forma sistemática de revisar los problemas, es interesante recordar que
también puede accederse directamente a los problemas, advertencias, resultados de búsqueda y
tareas pendientes sin más que hacer clic en sus marcas asociadas que aparecen en el margen
derecho del editor.
En Eclipse 3.0 estos botones de "ir a problema" se han sustituido por botones de "ir a anotación".
Haciendo clic en el pequeño triángulo negro cercano a estas flechas de navegación por
anotaciones se abrirá una lista editable con los tipos de anotaciones que serán recorridas. Así
pues, el uso de estos botones no está ya limitado sólo a la comprobación de problemas ya que
ahora se pueden realizar también otras tareas útiles tales como, por ejemplo, comprobar
sistemáticamente todas las "tareas pendientes" ("TODO") sin más que seleccionar "Tasks" en
dicha lista.
50
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Parte 5: Ejecutar y Depurar
Cuando el programa de Java esté completado será hora de ejecutarlo y probarlo. Quizás
aparezcan algunos "bugs" a la hora de ejecutarlo. Entonces será hora de depurar el programa.
Afortunadamente, Eclipse proporciona ayuda a las tareas de ejecutar y depurar código.
Ejecutar
Para ejecutar un programa dentro de Eclipse hay que seleccionar "Run > Run..." del menú
principal. Dentro de "Configurations" se almacenan diferentes configuraciones de ejecución. Hay
cuatro tipos de configuraciones de ejecución: Java Applet (para applets web), Java Application
(para programas normales de Java), JUnit (casos de prueba) y Run-Time Workbench (otras
instancias de Eclipse que permiten probar nuevos módulos de Eclipse).
Así pues, para ejecutar un programa de Java normal debería seleccionarse "Java Application" y
pulsar el botón "New" para crear una nueva configuración. Dentro de la pestaña "Main" hay que
dar nombre a la nueva configuración seleccionar el proyecto que contiene la clase con el método
main y seleccionar dicha clase. El método "main" es el punto de ejecución de un programa Java, y
se representa como un pequeño icono de un hombre corriendo al lado del icono de la clase.
Si se desea pasar argumentos al método main (en la forma de "String[] args"), no hay más que
hacer clic en la solapa de "Arguments" y escribir esos argumentos separados por espacio dentro
de la zona en blanco de "Program Arguments".
51
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Finalmente, hacer clic en el botón "Run" lanzará la ejecución del programa seleccionado. Una
forma más rápida de arrancar la ejecución del programa recientemente ejecutado es pulsar en el
icono de un hombre corriendo que aparece en el menú principal. Pulsar la flecha próxima a este
icono mostrará otras configuraciones de ejecución recientemente utilizadas.
En Eclipse 3.0 el icono anterior ha sido reemplazado por una flecha blanca dentro de un
círculo verde.
Depurar
Aunque Java no es tan difícil de depurar como otros lenguajes de programación, también es
perfectamente posible que surjan complejos problemas de ejecución. Eclipse da apoyo completo a
la tare de depuración a través de su perspectiva "Debug" ("Window > Open Perspective > Debug"
o seleccionando el icono del "bicho" en el margen izquierdo). Dentro de esta perspectiva de
depuración, haciendo clic en el margen izquierdo del editor de código aparecerá un menú
contextual. Seleccionando "Add/Remove Breakpoint" añadirá o quitará un punto de ruptura,
mientras que "Toggle Breakpoint" cambiará el estado de activación del punto de ruptura. Los
puntos de ruptura marcan líneas en que la ejecución del programa se detendrá de manera que
sea posible comprobar el valor de las variables en ese instante, identificando así posibles errores.
Haciendo clic derecho en un punto de ruptura
y seleccionando "Breakpoint Properties..."
permitirá especificar opciones avanzadas del
punto de ruptura. "Hit Count" especifica que la
ejecución del programa se detendrá cuando se
pase por el punto de ruptura el número
especificado de veces. Las condiciones de
activación detendrán la ejecución cuando la
condición sea cierta o bien cuando el valor de
la condición cambie. Especificar una variable
como una condición de activación y
seleccionar "suspend when value of condition
changes" es una forma de "detener la
ejecución en el punto de ruptura cuando dicha
variable sea modificada".
52
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Las excepciones son uno de los síntomas más evidentes de errores de ejecución. Los "Java
Exception Breakpoints" detienen la ejecución cuando salta una excepción del tipo seleccionado.
Estos puntos de ruptura se activan haciendo clic en el icono "J!" de la vista de "Breakpoints" o
desde el menú principal "Run". La ejecución puede detenerse cuando la excepción sea capturada,
no capturada o ambas. Añadir siempre los puntos de ruptura de excepciones Java de
"ArrayIndexOutOfBoundsException" (lanzada cuando el índice de una matriz se sale de sus
dimensiones) y "NullPointerException" (lanzada cuando se intenta acceder a una referencia que
apunta a null) es una práctica de depuración recomendada.
Si se desea que el programa se detenga en los puntos de ruptura definidos deberá ser ejecutado
en modo depuración ("Run > Debug..."). Tras detenerse en un punto de ruptura la ejecución del
programa puede continuar de diversas maneras. Haciendo clic derecho en el editor de código
dentro de la perspectiva de depuración aparecerá un menú contextual con estas opciones. "Run to
line" reanuda la ejecución del programa hasta que se alcanza la línea en que está el cursor. "Step
into selection" continuará la ejecución dentro del método seleccionado siempre y cuando el código
fuente del método esté disponible. La ejecución también puede reanudarse mediante un clic
derecho en la ventana de "Debug" y seleccionando las opciones adecuadas, o directamente
pulsando los iconos de dicha ventana. "Step over" parará en la línea siguiente a la invocación de
un método. "Resume" reanudará la ejecución normal del programa y sólo se interrumpirá en los
puntos de ruptura si sus condiciones de activación se satisfacen.
53
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
La vista "Variables" proporciona información verdaderamente útil ya que muestra los valores que
tienen actualmente las variables cuando la ejecución se detienen en un punto de ruptura.
La vista de "Debug" también es útil para observar diferentes procesos que están siendo
ejecutados simultáneamente, como por ejemplo, hebras. Cuando el proceso de depuración ha
terminado, los procesos mostrados en la ventana de depuración se muestran como "Finished"
(pueden acabarse manualmente con "Clic derecho > Terminate"). La información de ejecuciones
previas puede eliminarse realizando clic derecho sobre ella y seleccionando "Terminate and
Remove" o "Terminate All" más "Remove All Terminated".
Gestión de Cambios
No es extraño cambiar código del programa y darse cuenta después de que la nueva versión
funciona incluso aún peor que la primera versión. Ese es el motivo de que los programadores
tengamos que guardar diferentes versiones del programa cada vez que introducimos un nuevo
cambio. Sin embargo, esta práctica inevitable es normalmente tediosa y consume mucho tiempo.
Afortunadamente, Eclipse proporciona un potente sistema de gestión de cambios y de control de
versiones. Haciendo clic derecho en un archivo Java dentro del Package Explorer y selecionando
"Replace With > Local History" permitirá reemplazar la versión actual por una versión previamente
guardada. La hora y fecha de modificación se muestran junto con dos ventanas que destacan las
diferencias existentes entre ambas versiones.
54
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Seleccionando "Window > Preferences > Workbench > Local History" permitirá seleccionar
cuantas versiones, megas y días almacenar. Así pues, se puede obtener un buen equilibrio
personalizado entre seguridad y eficiencia.
Primera aplicación en Java
La aplicación más pequeña posible es la que simplemente imprime un mensaje en la pantalla.
Tradicionalmente, el mensaje suele ser "Hola Mundo!". Esto es justamente lo que hace el
siguiente fragmento de código:
// Aplicación HolaMundo de ejemplo
class HolaMundoApp {
public static void main( String args[] ) {
System.out.println( "Hola Mundo!" );
}
}
Hay que ver en detalle la aplicación anterior, línea a línea. Esas líneas de código contienen los
componentes mínimos para imprimir Hola Mundo! en la pantalla. Es un ejemplo muy simple, que
no instancia objetos de ninguna otra clase; sin embargo, accede a otra clase incluida en el JDK.
// Aplicación HolaMundo de ejemplo
//
Estas dos primeras 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 este 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.
55
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
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.
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.
args[ ] es la declaración de un array de Strings. Estos son los argumentos escritos tras el nombre
de la clase en la línea de comandos:
C:\>java HolaMundoApp arg1 arg2 ...
System.out.println( "Hola Mundo!" );
Esta es la funcionalidad de la aplicación. Esta línea muestra el uso de un nombre de clase y
método. Se usa el método println( ) de la clase out que está en el paquete Sistema.
A una variable de tipo class se puede acceder sin necesidad de instanciar ningún objeto de esa
clase. Por ello ha de ser un tipo básico o primitivo, o bien puede ser una referencia que apunta a
otro objeto. En este caso, la variable out es una referencia que apunta a un objeto de otro tipo,
aquí una instancia de la clase PrintStream (un objeto PrintStream), que es automáticamente
instanciado cuando la clase System es cargada en la aplicación. Esto es algo semejante al hecho
de que los objetos stream de entrada/salida, cin y cout son automáticamente instanciados y
enlazados a los dispositivos estándar de entrada y salida cuando un programa C++ comienza su
ejecución.
El método println( ) toma una cadena como argumento y la escribe en el stream de salida
estándar; en este caso, la ventana donde se lanza la aplicación. La clase PrintStream tiene un
método instanciable llamado println( ), que lo hace representar en la salida estándar del Sistema el
argumento que se le pase. En este caso, se utiliza la variable o instancia de out para acceder al
método.
}
}
Finalmente, se cierran las llaves que limitan el método main() y la clase HolaMundoApp. En C++,
la función main() en un programa puede tener cualquiera de los siguientes prototipos:
tipo_retorno main()
tipo_retorno main( int argc, char argv[] )
El tipo_retorno puede ser cualquier tipo válido, o void, para indicar que la función no tiene que
devolver valor alguno. La lista de argumentos puede estar vacía, o contener los argumentos de
soporte para pasar parámetros en la línea de comandos. Esta forma de implementación la función
difiere de la que acaba de presentar para Java, que siempre habrá de ser la misma,
independientemente de los valores de retorno o la lista de parámetros que se pasen en la lista de
argumentos a la aplicación.
56
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Sintaxis De Java y Nomenclatura
Material extraído del libro: Tinking in Java de Bruce Eckel
Estilo de codificación
El estándar no oficial de java dice que se ponga en mayúsculas la primera letra del nombre de una
clase. Si el nombre de la clase consta de varias palabras, se ponen todas juntas (es decir, no se
usan guiones bajos para separar los nombres) y se pone en mayúscula la primera letra de cada
palabra, como por ejemplo:
En casi todo lo demás: métodos, campos (variables miembro), y nombres de referencias a objeto,
el estilo aceptado es el mismo que para las clases, con la excepción de que la primera letra del
identificador debe ser minúscula. Por ejemplo:
class TodosLosColoresDelArcoiris {
int unEnteroQueRepresentaUnColor;
void cambiarElTonoDelColor (int nuevoTono) {
// . . .
}
}
Por supuesto, hay que recordar que un usuario tendría que teclear después todos estos nombres
largos, por lo que se ruega a los programadores que lo tengan en cuenta.
El código Java de las bibliotecas de Sun también sigue la forma de apertura y cierre de las llaves
que se utilizan en este libro.
Comentarios y documentación incrustada
Hay dos tipos de comentarios en Java. El primero es el estilo de comentarios tradicional de C, que
fue heredado por C++. Estos comentarios comienzan por /* y pueden extenderse incluso a lo largo
de varias líneas hasta encontrar */. Téngase en cuenta que muchos programadores comienzan
cada línea de un comentario continuo por el signo *, por lo que a menudo se vera
/ * Esto es un comentario
* que se extiende
* a lo largo de varias líneas
*/
Hay que recordar, sin embargo, que todo lo que esté entre /* y */ se ignora, por lo que no hay
ninguna diferencia con decir:
/ * Éste es un comentario que
se extiende a lo largo de varias líneas */
La segunda forma de hacer comentarios viene de C++. Se trata del comentario en una sola línea
que comienza por // y continúa hasta el final de la línea. Este tipo de comentario es muy
conveniente y se utiliza muy frecuentemente debido a su facilidad de uso. Uno no tiene que
buscar por el teclado donde está el / y el * (basta con pulsar dos veces la misma tecla), y no es
necesario cerrar el comentario, por lo que a menudo se verá:
/ / esto es un comentario en una sola línea
Documentación en forma de comentarios
Una de las partes más interesantes del lenguaje Java es que los diseñadores no sólo tuvieron en
cuenta que la escritura de código era la única actividad importante -sino que también pensaron en
la documentación del código. Probablemente el mayor problema a la hora de documentar el
código es el mantenimiento de esa documentación. Si la documentación y el código están
separados, cambiar la documentación cada vez que se cambia el código se convierte en un
problema. La solución parece bastante simple: unir el código a la documentación. La forma más
fácil de hacer esto es poner todo en el mismo archivo. Para completar la estampa, sin embargo,
57
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
es necesaria alguna sintaxis especial de comentarios para marcarlos como documentación
especial, y una herramienta para extraer esos comentarios y ponerlos en la forma adecuada.
La herramienta para extraer los comentarios se denomina javadoc. Utiliza parte de la tecnología
del compilador de Java para buscar etiquetas de comentario especiales que uno incluye en sus
programas.
No sólo extrae la información marcada por esas etiquetas, sino que también extrae el nombre de
la clase o del método al que se adjunta el comentario. De esta manera es posible invertir la
mínima cantidad de trabajo para generar una decente documentación para los programas.
La salida de javadoc es un archivo HTML que puede visualizarse a través del navegador Web.
Esta herramienta permite la creación y mantenimiento de un único archivo fuente y genera
automáticamente documentación útil. Gracias a javadoc se tiene incluso un estándar para la
creación de documentación, tan sencillo que se puede incluso esperar o solicitar documentación
con todas las bibliotecas Java.
Sintaxis
Todos los comandos de javadoc se dan únicamente en comentarios /**. Estos comentarios
acaban, como siempre, con */. Hay dos formas principales de usar javadoc: empotrar HTML, o
utilizar "etiquetas doc". Las etiquetas doc son comandos que comienzan por '@' y se sitúan al
principio de una línea de comentarios (en la que se ignora un posible primer '*').
Hay tres "tipos" de documentación en forma de comentarios, que se corresponden con el
elemento al que precede el comentario: una clase, una variable o un método. Es decir, el
comentario relativo a una clase aparece justo antes de la definición de la misma; el comentario
relativo a una variable precede siempre a la definición de la variable, y un comentario de un
método aparece inmediatamente antes de la definición de un método. Un simple ejemplo:
/** Un comentario de clase */
public class PruebaDoc {
/** Un comentario de una variable * /
public int i;
/** Un comentario de un método */
public void f ( ) { }
Nótese que javadoc procesará la documentación en forma de comentarios sólo de miembros
public y protected. Los comentarios para miembros private y "friendly" (véase Capítulo 5) se
ignoran, no mostrándose ninguna salida (sin embargo es posible usar el modificador -private para
incluir los miembros privados). Esto tiene sentido, dado que sólo los miembros públicos y
protegidos son visibles fuera del objeto, que será lo que constituya la perspectiva del programador
cliente. Sin embargo, la salida incluirá todos los comentarios de la clase.
La salida del código anterior es un archivo HTML que tiene el mismo formato estándar que toda la
documentación Java, de forma que los usuarios se sientan cómodos con el formato y puedan
navegar de manera sencilla a través de sus clases. Merece la pena introducir estos códigos,
pasarlos a través de javadoc y observar el fichero HTML resultante para ver los resultados.
HTML empotrado
Javadoc pasa comandos HTML al documento HTML generado. Esto permite un uso total de
HTML; sin embargo, el motivo principal es permitir dar formato al código, como:
/**
* <pre>
* System.out .println (new Date ( ) ) ;
* </pre>
*/
58
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
También puede usarse HTML como se haría en cualquier otro documento web
para dar formato al
propio texto de las descripciones:
/**
* Uno puede <em>incluso</em> insertar una lista:
* <01>
* <li> Elemento uno
* <li> Elemento dos
* <li> Elemento tres
* </ol>
Nótese que dentro de los comentarios de documentación, los asteriscos que aparezcan al
principio de las líneas serán desechados por javadoc, junto con los espacios adicionales a éstos.
Javadoc vuelve a dar formato a todo adaptándolo a la apariencia estándar de la documentación.
No deben utilizarse encabezados como <hl> o <hn como HTML empotrado porque javadoc inserta
sus propios encabezados y éstos interferirían con ellos.
Todos los tipos de documentación en comentarios -de clases, variables y métodos- soportan
HTML empotrado.
@see: referencias a otras clases
Los tres tipos de comentarios de documentación (de clase, variable y métodos) pueden contener
etiquetas
asee, que permiten hacer referencia a la documentación de otras clases. Javadoc generará HTML
con las etiquetas @see en forma de vínculos a la otra documentación. Las formas son:
@see nombredeclase
@see nombredeclase-totalmente-cualificada
@see nombredeclase-totalmente-cualificada#nombre-metodo
Cada una añade un hipervínculo "Ver también" a la documentación generada. Javadoc no
comprobará los hipervínculos que se le proporcionen para asegurarse de que sean válidos.
Etiquetas de documentación de clases
Junto con el HTML empotrado y las referencias asee, la documentación de clases puede incluir
etiquetas de información de la versión y del nombre del autor. La documentación de clases
también puede usarse para las interfaces (véase Capítulo 8).
Es de la forma:
@versión información-de-versión
en el que información-de-versión es cualquier información significativa que se desee incluir.
Cuando se especifica el indicador -versión en la línea de comandos javadoc, se invocará
especialmente a la información de versión en la documentación HTML generada.
Es de la forma:
Fautor información-del-autor
donde la información-del-autor suele ser el nombre, pero podría incluir también la dirección de
correo electrónico u otra información apropiada. Al activar el parámetro -author en la línea de
comandos javadoc, se invocará a la información relativa al autor en la documentación HTML
generada. Se pueden tener varias etiquetas de autor, en el caso de tratarse de una lista de
autores, pero éstas deben ponerse consecutivamente. Toda la información del autor se agrupará
en un único párrafo en el HTML generado.
Esta etiqueta permite indicar la versión del código que comenzó a utilizar una característica
concreta. Se verá que aparece en la documentación para ver la versión de JDK que se está
utilizando.
59
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Etiquetas de documentación de variables
La documentación de variables solamente puede incluir HTML empotrado y referencias @see.
Etiquetas de documentación de métodos
Además de documentación empotrada y referencias @see, los métodos permiten etiquetas de
documentación para los parámetros, los valores de retorno y las excepciones.
@param
Es de la forma:
@paran nombre-parametro descripción
donde nombre-parámetro es el identificador de la lista de parámetros, y descripción es el texto que
vendrá en las siguientes líneas. Se considera que la descripción ha acabado cuando se encuentra
una nueva etiqueta de documentación. Se puede tener cualquier número de estas etiquetas,
generalmente una por cada parámetro.
Es de la forma:
@return descripción
donde descripción da el significado del valor de retorno. Puede ocupar varias líneas.
Las excepciones se verán en el Capítulo 10, pero sirva como adelanto que son objetos que
pueden "lanzarse" fuera del método si éste falla. Aunque al invocar a un método sólo puede
lanzarse una excepción, podría ocurrir que un método particular fuera capaz de producir distintos
tipos de excepciones, necesitando cada una de ellas su propia descripción. Por ello, la etiqueta de
excepciones es de la forma:
@throws nombre-de-clase-totalmente-cualificada descripción
donde nombre-de-clase-totalmente-cualificada proporciona un nombre sin ambigüedades de una
clase de excepción definida en algún lugar, y descripción (que puede extenderse a lo largo de
varias líneas) indica por qué podría levantarse este tipo particular de excepción al invocar al
método. Se utiliza para etiquetar aspectos que fueron mejorados. Esta etiqueta es una sugerencia
para que no se utilice esa característica en particular nunca más, puesto que en algún momento
del futuro puede que se elimine. Un método marcado como @deprecated hace que el compilador
presente una advertencia cuando se use.
Ejemplo de documentación
He aquí el primer programa Java de nuevo, al que en esta ocasión se ha añadido documentación
en forma de comentarios:
/ / : c02:HolaFecha.java
import java.uti1. *;
/ * * El primer ejemplo de Piensa en Java.
* Muestra una cadena de caracteres y la fecha de hoy.
* @author Bruce Eckel
* @author www.BruceEckel.com
* @version 2.0
*/
public class HolaFecha {
/ * * Único punto de entrada para la clase y la aplicación
* @param args array de cadenas de texto pasadas como parámetros
* @return No hay valor de retorno
* Fexception exceptions No se generarán excepciones
*/
public static void main (String[] args) {
System.out .println (“hola, hoy es: " ) ;
System.out .println (new Date() ) ;
60
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
La primera línea del archivo utiliza mi propia técnica de poner ":" como marcador especial de la
línea de comentarios que contiene el nombre del archivo fuente. Esa línea contiene la información
de la trayectoria al fichero (en este caso, c02 indica el Capítulo 2) seguido del nombre del
archivo". La última línea también acaba con un comentario, esta vez indicando la finalización del
listado de código fuente, que permite que sea extraído automáticamente del texto de este libro y
comprobado por un compilador.
61
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Tipos de Datos
Los tipos primitivos
Hay un grupo de tipos que tiene un tratamiento especial: se trata de los tipos "primitivos", que se
usarán frecuentemente en los programas. La razón para el tratamiento especial es que crear un
objeto con new -especialmente variables pequeñas y simples- no es eficiente porque new coloca
el objeto en el montículo. Para estos tipos, Java vuelve al enfoque de C y C++. Es decir, en vez de
crear la variable utilizando new, se crea una variable "automática" que no es una referencia. La
variable guarda el valor, y se coloca en la pila para que sea más eficiente.
Java determina el tamaño de cada tipo primitivo. Estos tamaños no varían de una plataforma a
otra como ocurre en la mayoría de los lenguajes. La invariabilidad de tamaño es una de las
razones por las que Java es tan llevadero.
Todos los tipos numéricos tienen signo, de forma que es inútil tratar de utilizar tipos sin signo.
El tamaño del tipo boolean no está explícitamente definido; sólo se especifica que debe ser capaz
de tomar los valores true o false.
Los tipos de datos primitivos también tienen clases "envoltura". Esto quiere decir que si se desea
hacer un objeto no primitivo en el montículo(heap) para representar ese tipo primitivo, se hace uso
del casting(envoltorio) asociado. Por ejemplo:
char c = ' x ' ;
Character C = new Character (c) ;
O también se podría utilizar:
Character C = new character( 'x' ) ;
Números de alta precisión
Java incluye dos clases para llevar a cabo aritmética de alta precisión: BigInteger y BigDecimal.
Aunque estos tipos vienen a encajar en la misma categoría que las clases "envoltorio", ninguna de
ellas tiene un tipo primitivo. Ambas clases tienen métodos que proporcionan operaciones análogas
que se lleven a cabo con tipos primitivos. Es decir, uno puede hacer con BigInteger y BigDecimal
cualquier cosa que pueda hacer con un int o un float, simplemente utilizando llamadas a métodos
en vez de operadores. Además, las operaciones serán más lentas dado que hay más elementos
involucrados. Se sacrifica la velocidad en favor de la exactitud. BigInteger soporta enteros de
precisión arbitraria. Esto significa que uno puede representar valores enteros exactos de cualquier
tamaño y sin perder información en las distintas operaciones. BigDecimal es para números de
coma flotante de precisión arbitraria; pueden usarse, por ejemplo, para cálculos monetarios
62
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
exactos. Para conocer los detalles de los constructores y métodos que pueden invocarse para
estas dos clases, puede recurrirse a la documentación existente en línea
Valores por defecto para los miembros primitivos
Cuando un tipo de datos primitivo es un miembro de una clase, se garantiza que tenga un valor
por defecto siempre que no se inicialice:
Debe destacarse que los valores por defecto son los que Java garantiza cuando se usa la variable
como miembro de una clase. Esto asegura que las variables miembro de tipos primitivos siempre
serán inicializadas (algo que no ocurre en C++), reduciendo una fuente de errores. Sin embargo,
este valor inicial puede no ser correcto o incluso legal dentro del programa concreto en el que se
esté trabajando. Es mejor inicializar siempre todas las variables explícitamente.
Esta garantía no se aplica a las variables "locales" -aquellas que no sean campos de clases. Por
consiguiente, si dentro de una definición de función se tiene:
int x;
Entonces x tomará algún valor arbitrario (como en C y C++); no se inicializará automáticamente a
cero. Cada uno es responsable de asignar un valor apropiado a la variable x antes de usarla. Si
uno se olvida, Java seguro que será mejor que C++: se recibirá un error en tiempo de compilación
indicando que la variable debería haber sido inicializada. (Muchos compiladores de C++ advertirán
sobre variables sin inicializar, pero en Java éstos se presentarán como errores.)
63
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Recolector de Basura (garbage collector)
Ámbito de los objetos
Los objetos en Java no tienen la misma vida que los tipos primitivos. Cuando se crea un objeto
Java haciendo uso de new, éste perdura hasta el final del ámbito. Por consiguiente, si se escribe:
{
String s = new String ("un string" ) ;
} /* Fin del ámbito */
la referencia S desaparece al final del ámbito. Sin embargo, el objeto String al que apunta S sigue
ocupando memoria. En este fragmento de código, no hay forma de acceder al objeto, pues la
única referencia al mismo se encuentra fuera del ámbito. En capítulos posteriores se verá cómo
puede pasarse la referencia al objeto, y duplicarla durante el curso de un programa.
Resulta que, dado que los objetos creados con new se mantienen durante tanto tiempo como se
desee, en Java desaparecen un montón de posibles problemas propios de C++. Los problemas
mayores parecen darse en C++ puesto que uno no recibe ningún tipo de ayuda del lenguaje para
asegurarse de que los objetos estén disponibles cuando sean necesarios. Y lo que es aún más
importante, en C++ uno debe asegurarse de destruir los objetos cuando se ha acabado con ellos.
Esto nos conduce a una cuestión interesante. Si Java deja los objetos vivos por ahí, ¿qué evita
que se llene la memoria provocando que se detenga la ejecución del programa? Éste es
exactamente el tipo de problema que ocurriría en C++. Es en este punto en el que ocurren un
montón de cosas "mágicas". Java tiene un recolector de basura, que recorre todos los objetos que
fueron creados con new y averigua cuáles no serán referenciados más. Posteriormente, libera la
memoria de los que han dejado de ser referenciados, de forma que la memoria pueda ser utilizada
por otros objetos. Esto quiere decir que no es necesario que uno se preocupe de reivindicar
ninguna memoria. Simplemente se crean objetos, y cuando posteriormente dejan de ser
necesarios, desaparecen por sí mismos. Esto elimina cierta clase de problemas de programación:
el denominado "agujero de memoria", que se da cuando a un programador se le olvida liberar
memoria.
Limpieza: finalización y recolección de basura
Los programadores conocen la importancia de la inicialización, pero a menudo se les olvida la
importancia de la limpieza. Después de todo, ¿quién necesita eliminar un int? Pero con las
bibliotecas, dejar que un objeto simplemente "se vaya" una vez que se ha acabado con él, no es
siempre seguro. Por supuesto, Java tiene el recolector de basura para recuperar la memoria de
los objetos que ya no se usan.
Considere ahora un caso muy inusual. Supóngase que los objetos asignan memoria "especial" sin
utilizar new. El recolector de basura sólo sabe liberar la memoria asignada con new, por lo que
ahora no sabrá cómo liberar esa memoria "especial" del objeto. Para hacer frente a este caso,
Java proporciona un método denominado finalize( ) que se puede definir en cada clase. He aquí
cómo se supone que funciona. Cuando el recolector de basura está preparado para liberar el
espacio de almacenamiento utilizado por el objeto, primero invocará a finalize( ), y sólo
recuperará la memoria del objeto durante la pasada del recolector de basura. Por tanto, si se elige
usar finalize( ), éste te proporciona la habilidad de llevar a cabo alguna limpieza importante a la
vez que la recolección de basura.
Éste es un error potencial de programación porque algunos programadores, especialmente los de
C++, podrían confundir finalize( ) con el destructor de C++, que es una función que siempre se
invoca cuando se destruye un objeto. Pero es importante distinguir entre C++ y Java en este caso,
pues en C++ los objetos siempre se destruyen (en un programa sin errores), mientras que los
objetos de Java no siempre son eliminados por el recolector. 0, dicho de otra forma:
La recolección de basura no es destrucción
Si se recuerda esto, se evitarán los problemas. Lo que significa es que si hay alguna actividad que
debe llevarse a cabo antes de que un objeto deje de ser necesario, hay que llevar a cabo esa
64
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
actividad por uno mismo. Java no tiene un destructor o un concepto similar, por lo que hay que
crear un método ordinario para hacer esta limpieza. Por ejemplo, supóngase que en el proceso de
creación de un objeto, éste se dibuja a sí mismo en la pantalla. Si no se borra explícitamente esta
imagen de la pantalla, podría ser que éste no se elimine nunca. Si se pone algún tipo de
funcionalidad eliminadora dentro de finalize( ), si un objeto es eliminado por el recolector de
basura, la imagen será eliminada en primer lugar de la pantalla, pero si no lo es, la imagen
permanecerá. Por tanto, un segundo punto a recordar es:
Los objetos podrían no ser eliminados por el recolector de basura
Uno podría averiguar que el espacio de almacenamiento de un objeto nunca se libera porque el
programa nunca llega a quedarse sin espacio de almacenamiento. Si el programa se completa y el
recolector de basura nunca llega a ejecutarse para liberar el espacio de almacenamiento de
ningún objeto, éste será devuelto por completo al sistema operativo en el momento en que acaba
el programa.
Esto es bueno, porque el recolector de basura tiene algo de sobrecarga, y si nunca se ejecuta, no
hay que incurrir en ese gasto.
¿Para qué sirve finalize( )?
Uno podría pensar en este punto que no deberíamos utilizar finalize( ) como un método de
limpieza de propósito general. ¿Cómo de bueno es?
Un tercer punto para recordar es:
La recolección de basura sólo tiene que ver con la memoria
Es decir, la única razón para la existencia de un recolector de basura, es recuperar la memoria
que un programa ha dejado de utilizar. Por tanto, cualquier actividad asociada a la recolección de
basura, especialmente el método finalize( ) debe estar relacionada también sólo con la memoria y
su desasignación.
¿Significa esto que si un objeto contiene otros objetos finalize( ) debería liberar explícitamente
esos objetos? Pues no -el recolector de basura cuida de la liberación de toda la memoria de los
objetos independientemente de cómo se creará el objeto. Resulta que la necesidad de finalice( )
se limita a casos especiales, en los que un objeto puede reservar espacio de almacenamiento de
forma distinta a la creación de un objeto. Pero, podríamos pensar: en Java todo es un objeto, así
que ¿cómo puede ser?
Parecería que finalice( ) tiene sentido debido a la posibilidad de que se haga algo de estilo C,
asignando memoria utilizando un mecanismo distinto al normal de Java. Esto puede ocurrir
principalmente a través de métodos nativos, que son la forma de invocar a código no-Java desde
Java. (Los métodos nativos se discuten en el Apéndice B.) C y C++ son los únicos lenguajes
actualmente soportados por los métodos nativos, pues dado que pueden llamar a subprogramas
escritos en otros lenguajes, pueden efectivamente invocar a cualquier cosa. Dentro del código noJava, se podría invocar a la familia de funciones de malloc( ) de C para asignar espacio de
almacenamiento, provocando una pérdida de memoria. Por supuesto, free( ) es una función de C
y C++, por lo que sería necesario invocarla en un método nativo desde el finalice( ).
Después de leer esto, probablemente se tendrá la idea de que no se usará mucho finalice( ). Es
correcto: no es el sitio habitual para que ocurra una limpieza normal. Por tanto, ¿dónde debería
llevarse a cabo la limpieza normal?
65
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Hay que llevar a cabo la limpieza
Para eliminar un objeto, el usuario debe llamar a un método de limpieza en el punto en el que se
desee.
Esto suena bastante directo, pero colisiona un poco con el concepto de destructor de C++. En
este lenguaje, se destruyen todos los objetos. O mejor dicho, deberían eliminarse todos los
objetos.
Si se crea el objeto C++ como local (por ejemplo, en la pila -lo cual no es posible en Java), la
destrucción se da al cerrar la llave del ámbito en el que se ha creado el objeto. Si el objeto se creó
usando new (como en Java) se llama al destructor cuando el programador llame al operador
delete de C++ (que no existe en Java). Si el programador de C++ olvida invocar a delete, no se
llama nunca al destructor, y se tiene un fallo de memoria, y además las otras partes del objeto no
se borran nunca.
Este tipo de fallo suele ser muy difícil de localizar.
Por el contrario, Java no permite crear objetos locales -siempre hay que usar new. Pero en Java,
no hay un "eliminar" al que invocar para liberar el objeto, dado que el recolector de basura se
encarga de liberar el espacio de almacenamiento. Por tanto, desde un punto de vista simplista, se
podría decir que por culpa del recolector de basura, Java no tiene destructor. Se verá a medida
que se vaya avanzando en el libro, que la presencia de un recolector de basura no elimina la
necesidad de, o la utilidad de los destructores (y no se debería invocar a finalize( ) directamente,
pues ésta no es la solución más adecuada). Si se desea llevar a cabo algún tipo de limpieza
distinta a la liberación de espacio de almacenamiento, hay que seguir llamando explícitamente al
método apropiado en Java, que es el equivalente al destructor de C++ , sea o no lo más
conveniente.
Una de las cosas para las que puede ser útil finalize( ) es para observar el proceso de recolección
de basura.
Cómo funciona un recolector de basura
Si se realiza en un lenguaje de programación en el que la asignación de objetos en el montículo
es cara, hay que asumir naturalmente que el esquema de Java de asignar todo (excepto los datos
primitivos) en el montículo es caro.
Sin embargo, resulta que el recolector de basura puede tener un impacto significativo en un
incremento de la velocidad de creación de los objetos. Esto podría sonar un poco extraño al
principio - q u e la liberación de espacio de almacenamiento afecte a la asignación de espaciopero es la manera en que trabajan algunas JVM, y significa que la asignación de espacio para
objetos del montículo en Java pueda ser casi tan rápida como crear espacio de almacenamiento
en la pila en otros lenguajes.
Por ejemplo, se puede pensar que el montículo de C++ es como un terreno en el que cada objeto
toma un fragmento de suelo. Puede ser que este espacio sea abandonado tiempo después, y
haya que reutilizarlo. En algunas JVM, el montículo de Java es bastante distinto; es más como
una cinta transportadora que avanza cada vez que se asigna un nuevo objeto. Esto significa que
la asignación de espacio de almacenamiento de los objetos es notoriamente rápida. El "puntero
del montículo" simplemente se mueve hacia delante en territorio virgen, así que es exactamente lo
mismo que la asignación de pila de C++. (Por supuesto, hay una pequeña sobrecarga por el
mantenimiento de espacios, pero no hay nada como buscar espacio de almacenamiento.)
Ahora uno puede observar que el montículo no es, de hecho, una cinta transportadora, pues si se
trata como tal podría comenzar eventualmente una paginación excesiva de memoria (que
constituye un factor de rendimiento importante), e incluso más tarde la memoria podría agotarse.
El truco es que el recolector de basura va paso a paso, y mientras recolecta la basura, compacta
todos los objetos de la pila de forma que el resultado es que se ha movido el "puntero del
montículo" más cerca del principio de la cinta transportadora y más lejos de un fallo de página. El
recolector de basura reorganiza los elementos y hace posible usar un modelo de montículo de alta
velocidad y árbol infinito, durante la asignación de espacio de almacenamiento.
Para entender cómo funciona esto es necesario tener una idea un poco mejor de la manera en
que funcionan los diferentes esquemas de recolección de basura (GC, Garbage Collector). Una
66
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
técnica simple pero lenta de GC es contar referencias. Esto significa que cada ejemplo tiene un
contador de referencias, y cada vez que se adjunte una referencia a un objeto se incrementa en
uno el contador de referencias. Cada vez que una referencia cae fuera del ámbito o se pone null
se decrementa el contador de referencias. Por consiguiente, la gestión de contadores de
referencias supone una carga constante y pequeña que se va produciendo durante toda la vida
del programa. El recolector de basura va recorriendo toda la lista de objetos y al encontrar alguno
con el contador de referencias a cero, libera el espacio de almacenamiento que tenía asignado. El
inconveniente radica en que si los objetos tienen referencias circulares entre sí es posible no
encontrar contadores de referencias a cero, que, sin embargo, pueden ser basura. La localización
de estos grupos auto-referenciados requiere de una carga de trabajo significativa por parte del
recolector de basura. La cuenta de referencias se usa frecuentemente para explicar un tipo de
recolección de basura, pero parece no estar implementada en ninguna Máquina Virtual de Java.
En esquemas más rápidos, la recolección de basura no se basa en la cuenta de referencias. Se
basa, en cambio, en la idea de que cualquier objeto no muerto podrá recorrerse, realizar una traza
en última instancia, hasta una referencia que resida bien en la pila o bien en espacio de
almacenamiento estático. La cadena podría atravesar varias capas de objetos. Por consiguiente,
si se comienza en la pila y en el área de almacenamiento estático y se van recorriendo todas las
referencias, será posible localizar todos los objetos vivos. Por cada referencia que se encuentre,
es necesario hacer un recorrido traceo hasta localizar el objeto al que apunta y después seguir
todas las referencias a ese objeto, recorriendo todos los objetos a los que apunta, etc., hasta
haber recorrido toda la red que se originó con la referencia de la pila o del almacenamiento
estático. Cada objeto que se recorra debe seguir necesariamente vivo. Fíjese que no hay ningún
problema con los grupos auto-referenciados -simplemente no son localizados en el recorrido,
trazado, por lo que se consideraran basura automáticamente.
En la aproximación descrita, la Máquina Virtual de Java usa un esquema de recolección de basura
adaptativo, y lo que hace con los objetos vivos que encuentra depende de la variante que se haya
implementado.
Una de estas variaciones es la de parar-y-copiar. Esto significa que -por razones que pronto
parecerán evidentes- el programa se detiene en primer lugar (este esquema no implica
recolección en segundo plano). Posteriormente, cada objeto vivo que se encuentre se copia de un
montículo a otro, dejando detrás toda la basura. Además, a medida que se copian los ejemplos al
nuevo montículo, se empaquetan de extremo a extremo, compactando por consiguiente el nuevo
montículo (y permitiendo recorrer rápida y simplemente el nuevo almacenamiento hasta el final,
como se describió previamente).
Por supuesto, cuando se mueve un objeto de un lugar a otro, hay que cambiar todas las
referencias que apuntan a ese objeto. Las referencias que vayan del montículo o del área de
almacenamiento estática a un objeto pueden cambiarse directamente, pero puede haber otras
referencias que apunten a este objeto y que se encuentren más tarde durante la "búsqueda".
Éstas se van recomponiendo a medida que se encuentren (podría imaginarse una tabla que
establezca una relación entre las direcciones viejas y las nuevas).
También hay dos aspectos que hacen ineficientes a estos denominados "recolectores de copias".
El primero es la idea de que son necesarios dos montículos y se maneja por toda la memoria
adelante y atrás entre estos dos montículos separados, manteniendo el doble de memoria de la
que de hecho se necesita. Algunas Máquinas Virtuales de Java siguen este esquema asignando
el montículo por bloques a medida que son necesarios y haciendo simplemente copias de
bloques.
El segundo aspecto es la copia. Una vez que el programa se vuelve estable, debería generar poca
o ninguna basura. Además de esto, un recolector de copias seguiría copiando toda la memoria de
un sitio a otro, lo que es una pérdida de tiempo y recursos. Para evitar esto, algunas Máquinas
Virtuales de Java detectan que no se esté generando nueva basura y pasan a un esquema
distinto (ésta es la parte "adaptativa"). Este otro esquema denominado marcar y barrer(N. Del
traductor: En inglés, mark and sweep.), es el que usaban las primeras versiones de la Máquina
Virtual de Java de Sun. Para uso general, el esquema de marcar y barrer es bastante lento, pero
si se genera poca o ninguna basura es rápido.
El marcar y barrer sigue la misma lógica de empezar rastreando a través de todas las referencias,
a partir de la pila y el almacenamiento estático, para encontrar objetos vivos. Sin embargo, cada
67
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
vez que encuentra un objeto vivo, lo marca poniendo a uno cierto indicador, en vez de
recolectarlo. Sólo cuando acaba el proceso de marcado, se da el barrido. Durante el barrido, se
liberan los objetos muertos. Sin embargo, no se da ninguna copia, de forma que si el recolector
elige recolectar un montículo fragmentado, lo hace reordenando todos los objetos.
El "parar-y-copiar" se refiere a la idea de que este tipo de recolector de basura no se hace en
segundo plano; sino que, por el contrario, se detiene el programa mientras se ejecuta el recolector
de basura. En la documentación de Sun se encuentran muchas referencias a la recolección de
basura como un proceso de segundo plano de baja prioridad, pero resulta que el recolector de
basura no está implementado así, al menos en las primeras versiones de la Máquina Virtual de
Java de Sun.
En vez de esto, el recolector de basura de Sun se ejecutaba cuando quedaba poca memoria.
Además el marcado y barrido requiere la detención del programa.
Como se mencionó previamente, en la Máquina Virtual de Java aquí descrita, la memoria se
asigna por bloques grandes. Si se asigna un objeto grande, éste se hace con un bloque propio. El
parar-y copiar estricto exige copiar todos los objetos vivos del montículo fuente a un montículo
nuevo antes de poder liberar el viejo, lo que se traduce en montones de memoria. Con los objetos,
el recolector de basura puede en ocasiones usar los bloques muertos para copiar los objetos al ir
recolectando.
Cada bloque tiene un contador de generación para mantener información sobre si está o no vivo.
En circunstancias normales, sólo se compactan los bloques creados desde la última recolección.
Así se maneja la gran cantidad de objetos temporales de vida corta. Periódicamente, se hace un
barrido completo -se siguen sin copiar los objetos grandes, y se copian y compactan todos los
bloques que tienen objetos pequeños. La Máquina Virtual de Java monitoriza la eficiencia de la
recolección de basura y si se convierte en una pérdida de tiempo porque todos los objetos tienen
vida larga, pasa al esquema de marcar-y-barrer. De manera análoga, la Máquina Virtual de Java
mantiene un registro del éxito del marcar-y-borrar, y si el montículo comienza a estar fragmentado
vuelve de nuevo al parar-y-copiar. Éste es el momento en que interviene la parte "adaptativa", de
forma que finalmente se tiene un nombre kilométrico: "Marcado-y-borrado con parada-y-copia
adaptativo generacional".
Hay varias técnicas que permiten acelerar la velocidad de la Máquina Virtual de Java. Una
especialmente importante se refiere a la operación del cargador y del compilador "justo-a-tiempo"
UIV.
Cuando hay que cargar una clase (generalmente, la primera vez que se desea crear un objeto de
esa clase), se localiza el fichero .class y se lleva a memoria el "byte code" de esa clase. En ese
momento, un enfoque sería compilar JIT todo el código, pero esto tiene dos inconvenientes: lleva
un poco más de tiempo, lo cual, extrapolado a toda la vida del programa puede ser significativo; y
aumenta el tamaño del ejecutable (los "códigos byte" son bastante más compactos que el código
JIT expandido), lo que podría causar paginación, que definitivamente ralentizaría el programa. Un
enfoque alternativo lo constituye la evaluación perezosa, que quiere decir que el código no se
compila JIT hasta que es necesario. Por tanto, el código que no se ejecute nunca será compilado
por JIT.
68
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
LA CLASE String
Material extraído de la pagina:
Tutorial de Java de Agustin Froufe www.sunsite.dcc.uchile.cl/java/docs/JavaTut
Java posee gran capacidad para el manejo de cadenas dentro de sus clases String y StringBuffer.
Un objeto String representa una cadena alfanumérica de un valor constante que no puede ser
cambiada después de haber sido creada. Un objeto StringBuffer representa una cadena cuyo
tamaño puede variar.
Los Strings son objetos constantes y por lo tanto muy baratos para el sistema. La mayoría de las
funciones relacionadas con cadenas esperan valores String como argumentos y devuelven
valores String.
Hay que tener en cuenta que las funciones estáticas no consumen memoria del objeto, con lo
cual es más conveniente usar Character que char. No obstante, char se usa, por ejemplo, para
leer ficheros que están escritos desde otro lenguaje.
Existen muchos constructores para crear nuevas cadenas:
String();
String( String str );
String( char val[] );
String( char val[], int offset, int count );
String( byte val[], int hibyte );
String( byte val[], int hibyte, int offset, int count );
Tal como uno puede imaginarse, las cadenas pueden ser muy complejas, existiendo muchas
funciones muy útiles para trabajar con ellas y, afortunadamente, la mayoría están codificadas en la
clase String.
Funciones Básicas
La primera devuelve la longitud de la cadena y la segunda devuelve el carácter que se encuentra
en la posición que se indica en indice:
int length();
char charAt( int indice );
Funciones de Comparación de Strings
boolean equals( Object obj );
boolean equalsIgnoreCase( Object obj );
Lo mismo que equals() pero no tiene en cuenta mayúsculas o minúsculas.
int compareTo( String str2 );
Devuelve un entero menor que cero si la cadena es léxicamente menor que str2. Devuelve cero si
las dos cadenas son léxicamente iguales y un entero mayor que cero si la cadena es léxicamente
mayor que str2.
69
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Funciones de Comparación de Subcadenas
boolean regionMatch( int thisoffset, String s2,int s2offset,int len );
boolean regionMatch( boolean ignoreCase, int thisoffset, String s2,
int s2offset,int 1 );
Comprueba si una región de esta cadena es igual a una región de otra cadena.
boolean startsWith( String prefix );
boolean startsWith( String prefix,int offset );
boolean endsWith( String suffix );
Devuelve si esta cadena comienza o termina con un cierto prefijo o sufijo comenzando en un
determinado desplazamiento.
int
int
int
int
int
int
int
int
indexOf( int ch );
indexOf( int ch,int fromindex );
lastIndexOf( int ch );
lastIndexOf( int ch,int fromindex );
indexOf( String str );
indexOf( String str,int fromindex );
lastIndexOf( String str );
lastIndexOf( String str,int fromindex );
Devuelve el primer/último índice de un carácter/cadena empezando la búsqueda a partir
de un determinado desplazamiento.
String
String
String
String
String
String
String
substring( int beginindex );
substring( int beginindex,int endindex );
concat( String str );
replace( char oldchar, char newchar );
toLowerCase();
toUpperCase();
trim();
Ajusta los espacios en blanco al comienzo y al final de la cadena.
void getChars( int srcBegin,int srcEnd,char dst[],int dstBegin );
void getBytes( int srcBegin,int srcEnd,byte dst[],int dstBegin );
String toString();
char toCharArray();
int hashCode();
70
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Funciones ValueOf
La clase String posee numerosas funciones para transformar valores de otros tipos de datos a su
representación como cadena. Todas estas funciones tienen el nombre de valueOf, estando el
método sobrecargado para todos los tipos de datos básicos.
Veamos un ejemplo de su utilización:
String Uno = new String( "Hola Mundo" );
float f = 3.141592;
String PI = Uno.valueOf( f );
String PI = String.valueOf( f );
// Mucho más correcto
Funciones de Conversión
String
String
String
String
String
String
String
String
valueOf(
valueOf(
valueOf(
valueOf(
valueOf(
valueOf(
valueOf(
valueOf(
boolean b );
int i );
long l );
float f );
double d );
Object obj );
char data[] );
char data[],int offset,int count );
Usa arrays de caracteres para la cadena.
String copyValueOf( char data[] );
String copyValueOf( char data[],int offset,int count );
Crea un nuevo array equivalente para la cadena.
71
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
LA CLASE StringBuffer
Java posee gran capacidad para el manejo de cadenas dentro de sus clases String y StringBuffer.
Un objeto String representa una cadena alfanumérica de un valor constante que no puede ser
cambiada después de haber sido creada. Un objeto StringBuffer representa una cadena cuyo
tamaño puede variar.
La clase StringBuffer dispone de muchos métodos para modificar el contenido de los objetos
StringBuffer. Si el contenido de una cadena va a ser modificado en un programa, habrá que
sacrificar el uso de objetos String en beneficio de StringBuffer, que aunque consumen más
recursos del sistema, permiten ese tipo de manipulaciones.
Al estar la mayoría de las características de los StringBuffers basadas en su tamaño variable, se
necesita un nuevo método de creación:
StringBuffer();
StringBuffer( int len );
StringBuffer( String str );
Se puede crear un StringBuffer vacío de cualquier longitud y también se puede utilizar un String
como punto de partida para un StringBuffer.
StringBuffer Dos = new StringBuffer( 20 );
StringBuffer Uno = new StringBuffer( "Hola Mundo" );
Cambio de Tamaño
El cambio de tamaño de un StringBuffer necesita varias funciones específicas para manipular el
tamaño de las cadenas:
int length();
char charAt( int index );
void getChars( int srcBegin,int srcEnd,char dst[],int dstBegin );
String toString();
void setLength( int newlength );
void setCharAt( int index,char ch );
int capacity();
void ensureCapacity( int minimum );
void copyWhenShared();
Observar que una de las funciones devuelve una cadena constante normal de tipo String.
Este objeto se puede usar con cualquier función String, como por ejemplo, en las funciones de
comparación.
72
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Modificación del Contenido
Para cambiar el contenido de un StringBuffer, se pueden utilizar dos métodos: append() e insert().
En el ejemplo CadAppend.java, vemos el uso de estos dos métodos:
class CadAppend {
public static void main( String args[] ) {
StringBuffer str = new StringBuffer( "Hola" );
str.append( " Mundo" );
System.out.println( str );
}
}
En este otro ejemplo, CadInversa.java, mostramos un método muy simple que le da la vuelta a
una cadena:
class CadInversa {
public static String cadenaInversa( String fuente ) {
int longitud = fuente.length();
StringBuffer destino = new StringBuffer( longitud );
for( int i=(longitud-1); i = 0; i-- )
destino.append( fuente.charAt( i ) );
return( destino.toString() );
}
public static void main( String args[] ) {
System.out.println( cadenaInversa( "Hola Mundo" ) );
}
}
Las funciones que cambian el tamaño son pues:
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
StringBuffer
append( Object obj );
append( String str );
append( char str[] );
append( char str[],int offset,int len );
append( boolean b );
append( int i );
append( long l );
append( float f );
append( double d );
append( char ch );
insert( int offset,Object obj );
insert( int offset,String str );
insert( int offset,char str[] );
insert( int offset,boolean b );
insert( int offset,int i );
insert( int offset,long l );
insert( int offset,float f );
insert( int offset,double d );
insert( int offset,char ch );
73
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Operadores de Concatenación
Hay que recordar que los operadores "+" y "+=" también se pueden aplicar a cadenas.
Ambos realizan una concatenación y están implementados con objetos StringBuffer.
Por ejemplo, la sentencia:
String s = "¿Qué" + " tal ?";
es interpretada por el compilador como:
String s = new StringBuffer().append( "¿Qué" ).append( " tal ?" ).toString();
y se marcaría el StringBuffer para borrarlo ya que el contenido pasa al objeto String.
También, la sentencia:
s += " por ahí!";
sería interpretada por el sistema como:
String s = new StringBuffer().append( s ).append( " por ahí!" ).toString();
y volvería a marcar para borrar el nuevo StringBuffer.
74
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Referencias
Las referencias en Java no son punteros ni referencias como en C++. Este hecho crea un poco de
confusión entre los programadores que llegan por primera vez a Java. Las referencias en Java
son identificadores de instancias de las clases Java. Una referencia dirige la atención a un objeto
de un tipo específico. No tenemos por qué saber cómo lo hace ni necesitamos saber qué hace ni,
por supuesto, su implementación.
Pensemos en una referencia como si se tratase de la llave electrónica de la habitación de un
hotel. Vamos a utilizar precisamente este ejemplo del Hotel para demostrar el uso y la utilización
que podemos hacer de las referencias en Java. Primero crearemos la clase Habitacion ,
implementada en el archivo Habitación.java, mediante instancias de la cual construiremos nuestro
Hotel:
public class Habitacion {
private int numHabitacion;
private int numCamas;
public Habitacion() {
habitacion( 0 );
}
public Habitacion( int numeroHab ) {
habitacion( numeroHab );
}
public Habitacion( int numeroHab,int camas ) {
habitacion( numeroHab );
camas( camas );
}
public synchornized int habitacion() {
return( numHabitacion );
}
public synchronized void habitacion( int numeroHab ) {
numHabitacion = numeroHab;
}
public synchronized int camas() {
return( camas );
}
public syncronized void camas( int camas ) {
numCamas = camas;
}
}
El código anterior sería el corazón de la aplicación. Vamos pues a construir nuestro Hotel creando
Habitaciones y asignándole a cada una de ellas su llave electrónica; tal como muestra el código
siguiente, Hotel1.java :
public class Hotel1 {
public static void main( String args[] ) {
Habitacion llaveHab1;
// paso 1
Habitacion llaveHab2;
llaveHab1 = new Habitacion( 222 );
// pasos 2, 3, 4 y 5
llaveHab2 = new Habitacion( 1144,3 );
//
A ByD C
}
}
75
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Para explicar el proceso, dividimos las acciones en los cinco pasos necesarios para poder entrar
en nuestra habitación. Aunque no se incluye, podemos también considerar el caso de que
necesitemos un cerrajero, para que cuando perdamos la llave, nos abra la puerta; y que en
nuestro caso sería el garbage collector , que recicla la habitación una vez que se hayan perdido
todas las llaves.
El primer paso es la creación de la llave, es decir, definir la variable referencia, por defecto nula .
El resto de los pasos se agrupan en una sola sentencia Java. La parte B en el código anterior
indica al gerente del Hotel que ya dispone de una nueva habitación. La parte C llama al decorador
de interiores para que " vista " la habitación según un patrón determinado, para que no
desentonen unas habitaciones con otras y no se pierdan las señas de identidad del hotel. El
código electrónico que nos permitirá acceder a la habitación se genera en la parte D, una vez
conocido el interior de la habitación y se programa en la llave en la parte A.
Si dejamos el ejemplo real a un lado y nos vamos a lo que ocurre en la ejecución del código,
vemos que el operador new busca espacio para una instancia de un objeto de una clase
determinada e inicializa la memoria a los valores adecuados. Luego invoca al método constructor
de la clase, proporcionándole los argumentos adecuados. El operador new devuelve una
referencia a sí mismo, que es inmediatamente asignada a la variable referencia.
Podemos tener múltiples llaves para una misma habitación:
. . . Habitacion llaveHab3,llaveHab4; llaveHab3 = llaveHab1; llaveHab4 =
llavehab2;
De este modo conseguimos copias de las llaves. Las habitaciones en sí mismas no se han tocado
en este proceso. Así que, ya tenemos dos llaves para la habitación 222 y otras dos para la
habitación 1144.
Una llave puede ser programada para que funcione solamente con una habitación en cualquier
momento, pero podemos cambiar su código electrónico para que funcione con alguna otra
habitación; por ejemplo, para cambiar una habitación anteriormente utilizada por un empedernido
fumador por otra limpia de olores y con vistas al mar. Cambiemos pues la llave duplicada de la
habitación del fumador (la 222) por la habitación con olor a sal marina, 1144:
. . . llaveHab3 = llaveHab2;
Ahora tenemos una llave para la habitación 222 y tres para la habitación 1144. Mantendremos una
llave para cada habitación en la conserjería, para poder utilizarla como llave maestra, en el caso
de que alguien pierda su llave propia.
Alguien con la llave de una habitación puede hacer cambios en ella, y los compañeros que tengan
llave de esa misma habitación, no tendrán conocimiento de esos cambios hasta que vuelvan a
entrar en la habitación. Por ejemplo, vamos a quitar una de las camas de la habitación, entrando
en ella con la llave maestra:
. . . llaveHab2.camas( 2 );
Ahora cuando los inquilinos entren en la habitación podrán comprobar el cambio realizado:
. . . llaveHab4.printData();
76
INSTITUTO de TECNOLOGÍA O. R. T.
Instituto Incorporado a la Enseñanza Oficial (A-763)
Yatay 240 - Buenos Aires - República Argentina
Analista de Sistemas de Computación
Taller de Computación VI
Referencias y Arrays
Como en C y C++, Java dispone de arrays de tipos primitivos o de clases. Los arrays en C y C++
son básicamente un acompañante para los punteros. En Java, sin embargo, son ciudadanos de
primera clase.
Vamos a expandir nuestro hotel creando todo un ala de habitaciones, Hotel2.java . Crearemos un
juego de llaves maestras y luego construiremos las habitaciones:
public class Hotel2 {
// Número de habitaciones por ala
public static final int habPorAla = 12;
public static void main( String args[] ) {
Habitacion llavesMaestras[];
// paso 1
llavesMaestras = new Habitacion[ habPorAla ]; // pasos 2-5
//
A
B, C, D y E
int numPiso = 1;
for( int i=0; i < habPorAla; i++ )
// pasos 6-9
llavesMaestras[i]=new Habitacion(numPiso * 100 + i,( 0 == (i%2)) ? 2 : 1 );
for( int i=0; i < habPorAla; i++ )
// pasos 10-11
llavesMaestras[i].printData();
}
}
Cada paso en el ejemplo es semejante al que ya vimos antes. El paso 1 especifica que el juego de
llaves maestras es un grupo de llaves de habitaciones.
Los pasos 2 a 5 son, en este caso, la parte principal. En lugar de crear una habitación, el gerente
ordena construir un grupo contiguo de habitaciones. El número de llaves se especifica entre
corchetes y todas se crean en blanco.
Los pasos 6 a 9 son idénticos a los pasos 2 a 5 del ejemplo anterior, excepto en que en este caso
todas las llaves pasan a formar parte del juego maestro. Los números de piso se dan en miles
para que cuando se creen las habitaciones, todas tengan el mismo formato. También todas las
habitaciones de número par tienen una sola cama, mientras que las habitaciones impares tendrán
dos camas.
Los pasos 10 y 11 nos permiten obtener información de cada una de las habitaciones.
77
Descargar