Anda di halaman 1dari 153

Unidad 1: Lenguaje Java.

Captulo 1: Introduccin.
Java es un lenguaje de programacin orientado a objetos desarrollado por Sun Microsystems a principios de los aos 90. El lenguaje en s mismo toma mucha de su sintaxis de C y C++, pero tiene un modelo de objetos ms simple y elimina herramientas de bajo nivel, que suelen inducir a muchos errores, como la manipulacin directa de punteros o memoria. Las aplicaciones Java estn tpicamente compiladas en un bytecode, aunque la compilacin en cdigo mquina nativo tambin es posible. En el tiempo de ejecucin, el bytecode es normalmente interpretado o compilado a cdigo nativo para la ejecucin, aunque la ejecucin directa por hardware del bytecode por un procesador Java tambin es posible. La implementacin original y de referencia del compilador, la mquina virtual y las libreras de clases de Java fueron desarrolladas por Sun Microsystems en 1995. Desde entonces, Sun ha controlado las especificaciones, el desarrollo y evolucin del lenguaje a travs del Java Community Process, si bien otros han desarrollado tambin implementaciones alternativas de estas tecnologas de Sun, algunas incluso bajo licencias de software libre. Entre noviembre de 2006 y mayo de 2007, Sun Microsystems liber la mayor parte de sus tecnologas Java bajo la licencia GNU GPL, de acuerdo con las especificaciones del Java Community Process, de tal forma que prcticamente todo el Java de Sun es ahora software libre (aunque la biblioteca de clases de Sun que se requiere para ejecutar los programas Java todava no es software libre).

Historia.
Java es un lenguaje de programacin orientado a objetos desarrollado por Sun Microsystems a principio de los aos 90s. En Diciembre de 1950 Patrick Naughton, ingeniero de Sun Microsystems, reclut a varios colegas entre ellos James Gosling y Mike Sheridan para trabajar sobre un nuevo proyecto conocido como "El proyecto verde". Con la ayuda de otros ingenieros, empezaron a trabajar en una pequea oficina en Sand Hill Road en Menlo Park, California. Y as interrumpi todas las comunicaciones regulares con Sun y trabaj sin descanso durante 18 meses. Intentaban desarrollar una nueva tecnologa para programar la siguiente generacin de dispositivos inteligentes, en los que Sun vea un campo nuevo a explorar. Crear un lenguaje de programacin fcil de aprender y de usar. En un principio se consideraba C++ como lenguaje a utilizar, pero tanto Gosling como Bill Joy lo encontraron inadecuado. Gosling intent primero extender y modificar C++ resultando el lenguaje C++ ++ - (++ - porque se aadan y eliminaban caractersticas a C++), pero lo abandon para crear un nuevo lenguaje desde cero al que llamo Oak (roble en ingls, segn la versin ms aceptada, por el roble que vea a travs de la ventana de su despacho). El resultado fue un lenguaje que tena similitudes con C, C++ y Objetive C y que no estaba ligado a un tipo de CPU concreta. Ms tarde, se cambiara el nombre de Oak a Java, por cuestiones de propiedad intelectural, al existir ya un lenguaje con el nombre de Oak. Se supone que le pusieron ese nombre mientras tomaban caf (Java es nombre de un tipo de caf, originario de Asia), aunque otros afirman que el nombre deriva de las siglas de James Gosling, Arthur Van Hoff, y Andy Bechtolsheim. En Agosto de 1991 Oak ya corra sus primeros programas. Para 1992, el equipo ya haba desarrollado un sistema en un prototipo llamado Star7 (*7), dispositivo parecido a una PDA, cuyo nombre vena de la combinacin de teclas del

telfono de la oficina del Proyecto Green que permita a los usuarios responder al telfono desde cualquier lugar. Por su parte, el presidente de la compaa Sun, Scott McNealy, se dio cuenta de forma oportuna y estableci el Proyecto Verde. En 1994, se les hizo una demostracin de HotJava y la plataforma Java a los ejecutivos de Sun. Java 1.0a pudo descargarse por primera vez en 1994, pero hubo que esperar al 23 de mayo de 1995, durante las conferencias de SunWorld, a que vieran la luz pblica Java y HotJava, el navegador Web. El acontecimiento fue anunciado por John Gage, el Director Cientfico de Sun Microsystems. El acto estuvo acompaado por una pequea sorpresa adicional, el anuncio por parte de Marc Andreessen, Vicepresidente Ejecutivo de Netscape, que Java sera soportado en sus navegadores. El 9 de enero del ao siguiente, 1996, Sun fund el grupo empresarial JavaSoft para que se encargase del desarrollo tecnolgico. Dos semanas ms tarde la primera versin de Java fue publicada. La promesa inicial de Gosling era Write Once, Run Anywhere (Escrbelo una vez, ejectalo en cualquier lugar), proporcionando un lenguaje independiente de la plataforma y un entorno de ejecucin (la JVM) ligero y gratuito para las plataformas ms populares de forma que los binarios (bytecode) de las aplicaciones Java pudiesen ejecutarse en cualquier plataforma. El entorno de ejecucin era relativamente seguro y los principales navegadores web pronto incorporaron la posibilidad de ejecutar applets Java incrustadas en las pginas web. Java ha experimentado numerosos cambios desde la versin primigenia, JDK 1.0, as como un enorme incremento en el nmero de clases y paquetes que componen la librera estndar. Desde J2SE 1.4, la evolucin del lenguaje ha sido regulada por el JCP (Java Community Process), que usa Java Specification Requests (JSRs) para proponer y especificar cambios en la plataforma Java. El lenguaje en s mismo est especificado en la Java Language Specification (JLS), o Especificacin del Lenguaje Java. Los cambios en los JLS son gestionados en JSR 901.

Caractersticas de Java.
Las caractersticas principales que nos ofrece Java respecto a cualquier otro lenguaje de programacin, son:

Simple.
Java ofrece toda la funcionalidad de un lenguaje potente, pero sin las caractersticas menos usadas y ms confusas de stos. C++ es un lenguaje que adolece de falta de seguridad, pero C y C++ son lenguajes ms difundidos, por ello Java se dise para ser parecido a C++ y as facilitar un rpido y fcil aprendizaje. Java elimina muchas de las caractersticas de otros lenguajes como C++, para mantener reducidas las especificaciones del lenguaje y aadir caractersticas muy tiles como el garbage collector (reciclador de memoria dinmica). No es necesario preocuparse de liberar memoria, el reciclador se encarga de ello y como es un thread de baja prioridad, cuando entra en accin, permite liberar bloques de memoria muy grandes, lo que reduce la fragmentacin de la memoria. Java reduce en un 50% los errores ms comunes de programacin con lenguajes como C y C++ al eliminar muchas de las caractersticas de stos, entre las que destacan: Aritmtica de punteros No existen referencias Registros (struct) Definicin 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.

Orientado A Objetos.
Java implementa la tecnologa bsica 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 caractersticas propias del paradigma de la orientacin a objetos: encapsulacin, 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 resolucin dinmica de mtodos. Esta caracterstica deriva del lenguaje Objective C, propietario del sistema operativo Next. En C++ se suele trabajar con libreras dinmicas (DLLs) que obligan a recompilar la aplicacin cuando se retocan las funciones que se encuentran en su interior. Este inconveniente es resuelto por Java mediante una interfaz especfica llamada RTTI (RunTime Type Identification) que define la interaccin entre objetos excluyendo variables de instancias o implementacin de mtodos. Las clases en Java tienen una representacin en el runtime que permite a los programadores interrogar por el tipo de clase y enlazar dinmicamente la clase con el resultado de la bsqueda.

Distribuido.
Java se ha construido con extensas capacidades de interconexin TCP/IP. Existen libreras de rutinas para acceder e interactuar con protocolos como http y ftp. Esto permite a los programadores acceder a la informacin a travs de la red con tanta facilidad como a los ficheros locales. La verdad es que Java en s no es distribuido, sino que proporciona las libreras y herramientas para que los programas puedan ser distribuidos, es decir, que se corran en varias mquinas, interactuando.

Robusto.
Java realiza verificaciones en busca de problemas tanto en tiempo de compilacin como en tiempo de ejecucin. La comprobacin de tipos en Java ayuda a detectar errores, lo antes posible, en el ciclo de desarrollo. Java obliga a la declaracin explcita de mtodos, reduciendo as las posibilidades de error. Maneja la memoria para eliminar las preocupaciones por parte del programador de la liberacin o corrupcin de memoria. Tambin implementa los arrays autnticos, en vez de listas enlazadas de punteros, con comprobacin de lmites, para evitar la posibilidad de sobreescribir o corromper memoria resultado de punteros que sealan a zonas equivocadas. Estas caractersticas reducen drsticamente el tiempo de desarrollo de aplicaciones en Java.

Adems, para asegurar el funcionamiento de la aplicacin, realiza una verificacin de los byte-codes, que son el resultado de la compilacin de un programa Java. Es un cdigo de mquina virtual que es interpretado por el intrprete Java. No es el cdigo mquina directamente entendible por el hardware, pero ya ha pasado todas las fases del compilador: anlisis de instrucciones, orden de operadores, etc., y ya tiene generada la pila de ejecucin de rdenes. Java proporciona, pues: Comprobacin de punteros Comprobacin de lmites de arrays Excepciones Verificacin de byte-codes

Arquitectura Neutral.
Para establecer Java como parte integral de la red, el compilador Java compila su cdigo a un fichero objeto de formato independiente de la arquitectura de la mquina en que se ejecutar. Cualquier mquina que tenga el sistema de ejecucin (run-time) puede ejecutar ese cdigo objeto, sin importar en modo alguno la mquina en que ha sido generado. Actualmente existen sistemas run-time para Solaris 2.x, SunOs 4.1.x, Windows 95, Windows NT, Linux, Irix, Aix, Mac, Apple y probablemente haya grupos de desarrollo trabajando en el porting a otras plataformas.

El cdigo fuente Java se "compila" a un cdigo de bytes de alto nivel independiente de la mquina. Este cdigo (byte-codes) est diseado para ejecutarse en una mquina hipottica que es implementada por un sistema run-time, que s es dependiente de la mquina. En una representacin en que tuvisemos que indicar todos los elementos que forman parte de la arquitectura de Java sobre una plataforma genrica, obtendramos una figura como la siguiente:

En ella podemos ver que lo verdaderamente dependiente del sistema es la Mquina Virtual Java (JVM) y las libreras fundamentales, que tambin nos permitiran acceder directamente al hardware de la mquina. Adems, habr APIs de Java que tambin entren en contacto directo con el hardware y sern dependientes de la mquina, como ejemplo de este tipo de APIs podemos citar: Java 2D: grficos 2D y manipulacin de imgenes Java Media Framework : Elementos crticos en el tiempo: audio, video... Java Animation: Animacin de objetos en 2D Java Telephony: Integracin con telefona Java Share: Interaccin entre aplicaciones multiusuario Java 3D: Grficos 3D y su manipulacin

Seguro.
La seguridad en Java tiene dos facetas. En el lenguaje, caractersticas como los punteros o el casting implcito que hacen los compiladores de C y C++ se eliminan para prevenir el acceso ilegal a la memoria. Cuando se usa Java para crear un navegador, se combinan las caractersticas del lenguaje con protecciones de sentido comn aplicadas al propio navegador. El lenguaje C, por ejemplo, tiene lagunas de seguridad importantes, como son los errores de alineacin. Los programadores de C utilizan punteros en conjuncin con operaciones aritmticas. Esto le permite al programador que un puntero referencie a un lugar conocido de la memoria y pueda sumar (o restar) algn valor, para referirse a otro lugar de la memoria. Si otros programadores conocen nuestras estructuras de datos pueden extraer informacin confidencial de nuestro sistema. Con un lenguaje como C, se pueden tomar nmeros enteros aleatorios y convertirlos en punteros para luego acceder a la memoria:

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 cdigo malicioso, aunque el comando siga haciendo la funcionalidad que se le supone, despus de lanzar su carga destructiva. Por ejemplo, despus de que el caballo de Troya haya enviado por correo el /etc/shadow a su creador, ejecuta la funcionalidad de ls persentando el contenido del directorio. Se notar un retardo, pero nada inusual. El cdigo Java pasa muchos tests antes de ejecutarse en una mquina. El cdigo se pasa a travs de un verificador de byte-codes que comprueba el formato de los fragmentos de cdigo y aplica un probador de teoremas para detectar fragmentos de cdigo ilegal,

cdigo que falsea punteros, viola derechos de acceso sobre objetos o intenta cambiar el tipo o clase de un objeto. Si los byte-codes pasan la verificacin sin generar ningn mensaje de error, entonces sabemos que: El cdigo no produce desbordamiento de operandos en la pila El tipo de los parmetros de todos los cdigos de operacin son conocidos y correctos No ha ocurrido ninguna conversin 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 ningn intento de violar las reglas de acceso y seguridad establecidas

El Cargador de Clases tambin 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 aplicacin 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 interaccin de ciertos virus. Java no posee una semntica especfica para modificar la pila de programa, la memoria libre o utilizar objetos y mtodos de un programa sin los privilegios del kernel del sistema operativo. Adems, para evitar modificaciones por parte de los crackers de la red, implementa un mtodo ultra seguro de autentificacin por clave pblica. El Cargador de Clases puede verificar una firma digital antes de realizar una instancia de un objeto. Por tanto, ningn objeto se crea y almacena en memoria, sin que se validen los privilegios

de acceso. Es decir, la seguridad se integra en el momento de compilacin, con el nivel de detalle y de privilegio que sea necesario. Dada, pues la concepcin del lenguaje y si todos los elementos se mantienen dentro del estndar marcado por Sun, no hay peligro. Java imposibilita, tambin, abrir ningn fichero de la mquina local (siempre que se realizan operaciones con archivos, stas trabajan sobre el disco duro de la mquina de donde parti el applet), no permite ejecutar ninguna aplicacin nativa de una plataforma e impide que se utilicen otros ordenadores como puente, es decir, nadie puede utilizar nuestra mquina para hacer peticiones o realizar operaciones con otra. Adems, los intrpretes que incorporan los navegadores de la Web son an ms restrictivos. Bajo estas condiciones (y dentro de la filosofa de que el nico ordenador seguro es el que est apagado, desenchufado, dentro de una cmara acorazada en un bunker y rodeado por mil soldados de los cuerpos especiales del ejrcito), se puede considerar que Java es un lenguaje seguro y que los applets estn libres de virus. Respecto a la seguridad del cdigo fuente, no ya del lenguaje, JDK proporciona un desemsamblador de byte-code, que permite que cualquier programa pueda ser convertido a cdigo fuente, lo que para el programador significa una vulnerabilidad total a su cdigo. Utilizando javap no se obtiene el cdigo fuente original, pero s desmonta el programa mostrando el algoritmo que se utiliza, que es lo realmente interesante. La proteccin de los programadores ante esto es utilizar llamadas a programas nativos, externos (incluso en C o C++) de forma que no sea descompilable todo el cdigo; aunque as se pierda portabilidad. Esta es otra de las cuestiones que Java tiene pendientes.

Portable.
Ms all de la portabilidad bsica por ser de arquitectura independiente, Java implementa otros estndares de portabilidad para facilitar el desarrollo. Los enteros son siempre enteros y adems, enteros de 32 bits en complemento a 2. Adems, Java construye sus interfaces de usuario a travs de un sistema abstracto de ventanas de forma que las ventanas puedan ser implantadas en entornos Unix, Pc o Mac.

Interpretado.
El intrprete Java (sistema run-time) puede ejecutar directamente el cdigo objeto. Enlazar (linkar) un programa, normalmente, consume menos recursos que compilarlo, por

lo que los desarrolladores con Java pasarn ms tiempo desarrollando y menos esperando por el ordenador. No obstante, el compilador actual del JDK es bastante lento. Por ahora, que todava no hay compiladores especficos de Java para las diversas plataformas, Java es ms lento que otros lenguajes de programacin, como C++, ya que debe ser interpretado y no ejecutado como sucede en cualquier programa tradicional. Se dice que Java es de 10 a 30 veces ms lento que C, y que tampoco existen en Java proyectos de gran envergadura como en otros lenguajes. La verdad es que ya hay comparaciones ventajosas entre Java y el resto de los lenguajes de programacin, y una ingente cantidad de folletos electrnicos que supuran fanatismo en favor y en contra de los distintos lenguajes contendientes con Java. Lo que se suele dejar de lado en todo esto, es que primero habra que decidir hasta que punto Java, un lenguaje en pleno desarrollo y todava sin definicin definitiva, est maduro como lenguaje de programacin para ser comparado con otros; como por ejemplo con Smalltalk, que lleva ms de 20 aos en cancha. La verdad es que Java para conseguir ser un lenguaje independiente del sistema operativo y del procesador que incorpore la mquina utilizada, es tanto interpretado como compilado. Y esto no es ningn contrasentido, me explico, el cdigo fuente escrito con cualquier editor se compila generando el byte-code. Este cdigo intermedio es de muy bajo nivel, pero sin alcanzar las instrucciones mquina, propias de cada plataforma y no tiene nada que ver con el p-code de Visual Basic. El byte-code corresponde al 80% de las instrucciones de la aplicacin. Ese mismo cdigo es el que se puede ejecutar sobre cualquier plataforma. Para ello hace falta el run-time, que s es completamente dependiente de la mquina y del sistema operativo, que interpreta dinmicamente el bytecode y aade el 20% de instrucciones que faltaban para su ejecucin. Con este sistema es fcil crear aplicaciones multiplataforma, pero para ejecutarlas es necesario que exista el run-time correspondiente al sistema operativo utilizado.

Multiprocesos.
Al ser multithreaded (multihilvanado, en mala traduccin), Java permite muchas actividades simultneas en un programa. Los threads (a veces llamados, procesos ligeros), son bsicamente pequeos procesos o piezas independientes de un gran

proceso. Al estar los threads contruidos en el lenguaje, son ms fciles de usar y ms robustos que sus homlogos en C o C++. El beneficio de ser miltithreaded 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.), an supera a los entornos de flujo nico de programa (single-threaded) tanto en facilidad de desarrollo como en rendimiento. Cualquiera que haya utilizado la tecnologa de navegacin concurrente, sabe lo frustrante que puede ser esperar por una gran imagen que se est trayendo. En Java, las imgenes se pueden ir trayendo en un thread independiente, permitiendo que el usuario pueda acceder a la informacin en la pgina sin tener que esperar por el navegador.

Dinamico.
Java se beneficia todo lo posible de la tecnologa orientada a objetos. Java no intenta conectar todos los mdulos que comprenden una aplicacin hasta el tiempo de ejecucin. Las libreras nuevas o actualizadas no paralizarn las aplicaciones actuales (siempre que mantengan el API anterior).

Java tambin simplifica el uso de protocolos nuevos o actualizados. Si su sistema ejecuta una aplicacin Java sobre la red y encuentra una pieza de la aplicacin que no sabe manejar, tal como se ha explicado en prrafos anteriores, Java es capaz de traer automticamente cualquiera de esas piezas que el sistema necesita para funcionar.

Java, para evitar que los mdulos de byte-codes o los objetos o nuevas clases, haya que estar trayndolos 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 mquina.

JVM.
El corazn de la Plataforma Java es el concepto comn de un procesador virtual que ejecuta programas escritos en el lenguaje de programacin Java. En concreto, ejecuta el cdigo resultante de la compilacin del cdigo fuente, conocido como bytecode. Este procesador es la mquina virtual de Java o JVM (Java Virtual Machine), que se encarga de traducir (interpretar o compilar al vuelo) el bytecode en instrucciones nativas de la plataforma destino. Esto permite que una misma aplicacin Java pueda ser ejecutada en una gran variedad de sistemas con arquitecturas distintas, siempre que con una implementacin adecuada de la JVM. Este hecho es lo que ha dado lugar a la famosa frase: write once, run anywhere (escribir una vez, ejecutar en cualquier parte). La condicin es que no se utilicen llamadas nativas o funciones especificas de una plataforma y an as no se asegura completamente que se cumpla una verdadera independencia de plataforma. Desde la versin 1.2 de JRE, la implementacin de la mquina virtual de Sun incluye un compilador JIT (Just In Time). De esta forma, en vez de la tradicional interpretacin del cdigo bytecode, que da lugar a una ejecucin lenta de las aplicaciones, el JIT convierte el bytecode a cdigo nativo de la plataforma destino. Esta segunda compilacin del cdigo penaliza en cuanto a tiempo, pero el cdigo nativo resultante se ejecuta de forma ms eficaz y rpida que si fuera interpretado. Otras tcnicas de compilacin dinmica del

cdigo durante el tiempo de ejecucin permiten optimizar ms an el cdigo, dejando atrs la losa que sobre Java caa en cuanto a su lentitud y en sus ltimas versiones la JVM se ha optimizado a tal punto que ya no se considera una plataforma lenta en cuanto a ejecucin de aplicaciones. Sin embargo, no puede decirse que el resultado de la compilacin de Java pueda compilar el cdigo con un mximo de eficiencia, y aprovechar los beneficios en cuanto a velocidad de cdigo mquina nativo. Aunque los compiladores cada vez son ms avanzados, no todas las libreras de Java tienen asociado un cdigo mquina equivalente que aprovechar. Por ejemplo, la librera reflect, que permite a los programadores de Java explorar instrucciones que slo estn disponibles en tiempo de ejecucin, est pobremente representado por cdigo mquina. Java no fue la primera plataforma basada en el concepto de una mquina virtual, aunque es la que de ms amplia difusin ha gozado. El empleo de mquinas virtuales se haba centrado principalmente en el uso de emuladores para ayudar al desarrollo de hardware en construccin o sistemas operativos, pero la JVM fue diseada para ser implementada completamente en software, y al mismo tiempo hacer que fuera portable a todo tipo de hardware.

JDK.
Java Development Kit o (JDK), es un software que provee herramientas de desarrollo para la creacin de programas en java. Puede instalarse en una computadora local o en una unidad de red. Los programas ms importantes que se incluyen son: Appletviewer: es un visor de applet para generar sus vistas previas, ya que un applet carece de mtodo main y no se puede ejecutar con el programa java. Javac: es el compilador de JAVA. java: es el intrprete de JAVA. javadoc: genera la documentacin de las clases java de un programa.

Versiones y distribuciones de Java.


Versiones.
La primera versin fue la 1.0 que se encuentra prcticamente obsoleta y fue reemplazada por la 1.1 En la versin 1.4 se cambia el nombre a Java2, ya que los cambios se consideran suficientes como para ameritar tal cambio. Esta es la versin ms comnmente usada, la mayora de los proyectos actuales han sido diseados para cumplir con este estndar. La versin 1.5 ha ganado la confianza del mercado, y gracias a sus nuevas caractersticas los nuevos proyectos se estn desarrollando en este estndar. Actualmente se encuentra disponible la versin 1.6 aunque el mercado an se encuentra escptico se prev que pronto avance en esta direccin.

Distribuciones
Debemos diferenciar las distribuciones de la JRE y el JDK, Sun Microsystems, Inc. Ha organizado el JDK en diferentes distribuciones de acuerdo a las necesidades del desarrollador. Para aplicaciones estndar (Stand Alone y Applets) ofrece el JDK Java SE (Estandar Edition). Para aplicaciones que se ejecutarn en dispositivos de bajo rendimiento (celulares, pda, etc) ofrece la Java ME (Micro Edition). Para aplicaciones que se ejecutarn en dispositivos sin interfaces de usuario (Routers, Decodificadores, etc) existe la Java CE (Card Edition). Para aplicaciones empresariales con arquitecturas de mltiples capas ofrece la Enterprise Edition o Java EE.

Para cada una de estas distribuciones existen diferentes mquinas virtuales. El siguiente es un esquema de estas distribuciones.

Interfaces de Desarrollo.
La distribucin oficial de Java incluye todas las herramientas necesarias para el desarrollo, pero en una interfaz de comandos, para acelerar el proceso de desarrollo de software es indispensable el uso de alguna interfaz de desarrollo visual. Aqu hay una lista de algunas opciones. BEA Workshop software comercial, desarrollado por BEA Systems, integrado con BEA WebLogic BlueJ libre, desarrollado como un proyecto de investigacin universiatario. BlueJ es tambin un entorno interactivo adecuado para aprender Java Eclipse libre y de cdigo abierto, Eclipse es desarrollado por la Fundacin Eclipse IntelliJ IDEA software comercial, IntelliJ IDEA es desarrollado por JetBrains JGrasp - Software gratuito desarrollado por el Department of Computer Science and Software Engineering en el the Samuel Ginn College of Engineering de la Universidad de Auburn. Es un ambiente de desarrollo muy ligero para Java, C, C++, Objective C, Ada y VHDL. Integra diagramas UML para Java y Diagramas de Estructuras de Control. JBuilder software comercial (existe una versin gratuita). JBuilder es desarrollado por Borland JCreator software comercial(existe una versin gratuita) desarrollado por Xinox JDeveloper IDE gratuito desarrollado por Oracle Corporation e integrado con Oracle Application Server NetBeans IDE y plataforma base para aplicaciones ricas de escritorio (Rich Apps) gratuito de cdigo abierto desarrollado por NetBeans.org Sun Java Studio Enterprise software comercial (gratis para los miembros de Sun Developer Network), desarrollado por Sun Microsystems Rational Application Developer for WebSphere Software software comercial, desarrollado por IBM, integrado con WebSphere Application Server Cabe destacar que eclipse es la herramienta ms usada, gracias a que es de libre distribucin y cdigo abierto que posee un sistema intuitivo de plugins, que lo hacen fcil

de adaptar a las necesidades particulares. En este curso usaremos Eclipse como interfaz de desarrollo. NetBeans es un entorno de desarrollo muy completo, su mejor caracterstica es el asistente para diseo de formularios SWING y AWT, sin embargo necesita muchos recursos de hardware.

Captulo 2: Lenguaje Java.


Tipos de aplicaciones Java.
Consola.
Son los programas ms simples que se desarrollan en Java, consisten de una serie de clases que colaboran para realizar una tarea, donde la interfaz se da a travs de la consola.

Applets.
Un applet Java es un applet escrito en el lenguaje de programacin Java. Los applets de Java pueden correr en un navegador web utilizando la Java virtual machine (JVM), o en el AppletViewer de Sun. Entre sus caractersticas podemos mencionar un esquema de seguridad que permite que los applets que se ejecutan en el equipo no tengan acceso a partes sensibles (por ej. no pueden escribir archivos), a menos que uno mismo le d los permisos necesarios en el sistema; la desventaja de este enfoque es que la entrega de permisos es engorrosa para el usuario comn, lo cual juega en contra de uno de los objetivos de los Java applets: proporcionar una forma fcil de ejecutar aplicaciones desde el navegador web. En Java un applet (Subprograma), es un programa que puede inscrustarse en un documento HTML; es decir en una pgina Web, Cuando un Navegador carga una pgina Web que contiene un Applet, este se descarga en el navegador Web y comienza a

ejecutarse esto nospermite crear programas que cualquier usuario puede ejecutar con tan solo cargar la pagina Web en su navegador. El Navegador que carga y ejecuta el applet se conoce en terminos genericos como el contenedor de Applets. El kit de desarrollo de Software para java 2 (J2SDK) 1.4.1 incluye el contenedor de basura de Applets llamado appletviewer para probar los applets antes de inscrustarlso en una pgina Web.

SWING/AWT.
La mayora de las aplicaciones Swing presentan su GUI principal dentro de un JFrame -un contenedor Swing de alto nivel que proporciona ventanas para applets y aplicaciones. Un frame tiene decoraciones como un borde, un ttulo, y botones para cerrar y minimizar la ventana. Un programa tpico simplemente crea un frame, aade componentes al panel de contenido, y quizs aade una barra de men. Sin embargo, a travs de su panel raz, JFrame proporciona soporte para una mayor personalizacin.

Servlets.
Los servlets son objetos que corren dentro del contexto de un contenedor de servlets (ej: Tomcat) y extienden su funcionalidad. Tambin podran correr dentro de un servidor de aplicaciones que adems de contenedor para servlet tendr contenedor para objetos ms avanzados como son los EJB (Tomcat slo es un contenedor de servlets). La palabra servlet deriva de otra anterior, applet, que se refera a pequeos programas escritos en Java que se ejecutan en el contexto de un navegador web. Por contraposicin, un servlet es un programa que se ejecuta en un servidor.

Tipos de Entidades Java


Clases.
Las clases marcan la estructura bsica de un programa tanto en Java como en la programacin orientada a objetos en general. Una clase es el producto de enfocar la programacin a los datos ms que a las funciones. Por tanto una clase es una coleccin de datos y adems para operar con ellos una serie de funciones propias de la clase. Veamos por ejemplo la clase "Fichas" definida

anteriormente, su nico dato es "el color" y la nica operacin que permite es saber el color de la ficha en cualquier momento. Eso permite un acceso restrictivo a los datos segn la funcin de los mismos. En este caso la clase es as basndose en la vida misma: No creo que nadie haya cambiado el color de una ficha jugando a las "cuatro en raya" y en caso positivo no tendra muy buenas intenciones al hacerlo. Adems de este mtodo bsico de proteccin de los datos, Java permite algunos ms que vemos ahora mismo. Cuando declaramos una clase lo primero que ponemos es la cabecera:

En cuanto al nombre de la clase consideraremos varias cosas. Debe de obedecer al convenio de nombres de Java y coincidir con el nombre del fichero ".java" en el que se guardar la clase. Primero se suelen declarar, al menos, las variables internas de esa clase (atributos) y posteriormente se definen los constructores y los mtodos que dispondr la clase. Lo entenderemos mejor ms adelante.

Clases Abstractas.
Hay ocasiones, cuando se desarrolla una jerarqua de clases en que algn comportamiento est presente en todas ellas pero se materializa de forma distinta para cada una. Por ejemplo, pensemos en una estructura de clases para manipular figuras geomtricas. Podramos pensar en tener una clase genrica, que podra llamarse FiguraGeometrica y una serie de clases que extienden a la anterior que podran ser Crculo, Polgono, etc. Podra haber un mtodo dibujar dado que sobre todas las figuras puede llevarse a cabo esta accin, pero las operaciones concretas para llevarla a cabo dependen del tipo de figura en concreto (de su clase). Por otra parte la accin dibujar no tiene sentido para la clase genrica FiguraGeometrica, porque esta clase representa una abstraccin del conjunto de figuras posibles.

Para resolver esta problemtica Java proporciona las clases y mtodos abstractos. Un mtodo abstracto es un mtodo declarado en una clase para el cual esa clase no proporciona la implementacin (el cdigo). Una clase abstracta es una clase que tiene al menos un mtodo abstracto. Una clase que extiende a una clase abstracta debe implementar los mtodos abstractos (escribir el cdigo) o bien volverlos a declarar como abstractos, con lo que ella misma se convierte tambin en clase abstracta.

Interfaces.
Un interface es una coleccin de declaraciones de mtodos (sin definirlos) y tambin puede incluir constantes. Runnable es un ejemplo de interface en el cual se declara, pero no se implemementa, una funcin miembro run.

Las clases que implementen (implements) el interface Runnable han de definir obligatoriamente la funcin run.

El papel del interface es el de describir algunas de las caractersticas de una clase. Por ejemplo, el hecho de que una persona sea un futbolista no define su personalidad completa, pero hace que tenga ciertas caractersticas que las distinguen de otras. Clases que no estn relacionadas pueden implementar el interface Runnable, por ejemplo, una clase que describa una animacin, y tambin puede implementar el interface Runnable una clase que realice un clculo intensivo. Un interface es simplemente una lista de mtodos no implementados, adems puede incluir la declaracin de constantes. Una clase abstracta puede incluir mtodos implementados y no implementados o abstractos, miembros dato constantes y otros no constantes. Ahora bien, la diferencia es mucho ms profunda. Imaginemos que Runnable fuese una clase abstracta. Un applet descrito por la clase MiApplet que moviese una figura por su rea de trabajo, derivara a la vez de la clase base Applet (que describe la funcionalidad mnima de un applet que se ejecuta en un navegador) y de la clase Runnable. Pero el lenguaje Java no tiene herencia mltiple. En el lenguaje Java la clase MiApplet deriva de la clase base Applet e implementa el interface Runnable.

Enums.
Un enumerated type es un tipo de dato que contiene un conjunto de valores constantes. JDK 5 incluye soporte lingstico para los tipos de datos enumerados. Las caractersticas avanzadas de la OO incluyen la capacidad de agregar los mtodos y campos a los enums. Esto es ms ordenado, ms seguro y ms potente que las alternativas existentes.

Enums son Comparable y Serializables. Las constantes de Enum deberan ser nombradas de manera similar que las constantes.

Organizacin en paquetes.
La palabra clave package permite agrupar clases e interfaces. Los nombres de los paquetes son palabras separadas por puntos y se almacenan en directorios que coinciden con esos nombres.

Por ejemplo, los ficheros siguientes, que contienen cdigo fuente Java: Applet.java, AppletContext.java, AppletStub.java, AudioClip.java contienen en su cdigo la lnea:

Y las clases que se obtienen de la compilacin de los ficheros anteriores, se encuentran con el nombre nombre_de_clase.class, en el directorio: java/applet

Uso de comentarios.
Hay tres tipos de comentarios en Java: 1. // Este es un comentario de una sola lnea 2. /* Este es un comentario de una o ms lneas */ 3. /** Este es un comentario de documentacin */

Variables, identificadores, tipos de datos primitivos.


Identificadores.
Un identificador es un "nombre" que nos permite dirigirnos especficamente a una de las entidades propias del lenguaje, es decir, son los nombres que podemos ponerles a nuestros/as variables, mtodos, clases, interfaces y objetos. La nica restriccin en la formacin de identificadores es que tienen que comenzar por letra, subrayado o por el signo '$', pudindoles seguir despus letras o nmeros. Hay que tener en cuenta que en Java como en otros muchos lenguajes de programacin se distinguen las maysculas y las minsculas. Hay una serie de normas muy recomendables para crear identificadores en Java: En Java es habitual escribir todos los identificadores en minscula teniendo en cuenta las siguientes excepciones:

Si en un identificador queremos incluir un nombre compuesto se pone el primer nombre entero en minscula y el resto con la primera letra en mayscula y el resto en minscula. Por ejemplo: miNuevaVariable = 3;

Los identificadores de clases e interfaces siempre empiezan en mayscula siguiendo la anterior norma en caso de tratarse de un nombre compuesto. Por ejemplo: miNuevaClase

Los nombres de variables finales (las ms habitualmente llamadas "constantes") se escriben ntegramente en mayscula. Por ejemplo: "PI".

Otra restriccin muy importante y evidente a la hora de elegir identificador por ejemplo para una variable es no coincidir con ciertas palabras restringidas que tiene el lenguaje, estas son: Abstract Switch continue for boolean default do double else new goto If null package private

Synchronized break This Threadsafe Throw Transient True Try void byte byvalue case catch char class const

implements protected import public return short static super while

extends instanceof false final finally float int interface long native

Tipos Primitivos.
Como tipos primitivos entendemos aquellos tipos de informacin ms usuales y bsicos. Son los habituales de otros lenguajes de programacin: Boolean: No es un valor numrico, solo admite los valores true o false. Char: Usa el cdigo UNICODE y ocupa cada carcter 16 bits. Enteros: Difieren en las precisiones y pueden ser positivos o negativos. Byte: 1 byte.

Short: 2 bytes. Int: 4 bytes. Long: 8 bytes. Reales en punto flotante: igual que los enteros tambin difieren en las precisiones y pueden ser positivos o negativos. Float: 4 bytes. Double: 8 bytes

Variables
Ahora que tenemos las piezas necesarias (identificadores y tipos) podemos definir variables en Java. Una variable referenciar siempre a un tipo primitivo de Java o a cualquier otro objeto creado en nuestro programa. Veamos algunas declaraciones:

Una vez tenemos un poco de idea de cmo declarar variables en Java, tenemos que tener en cuenta desde que sitios de nuestro programa podemos acceder a ellas, es lo que llamamos mbito de la variable.

Bsicamente la norma es que la variable tiene validez dentro del bloque encerrado entre llaves donde ha sido declarada, ya sea dentro de una funcin o de por ejemplo una sentencia 'if'.

Declaracin de atributos y mtodos concretos.


Atributos
Los atributos de una clase se definen segn esta sintaxis: [modifVisibilidad] [modifAtributo] tipo nombreVariable[=valorInicial]; Donde nombreVariable es el nombre que daremos a la variable, siendo un nombre vlido segn las normas del lenguaje: por convencin, en Java, los nombres de las variables empiezan con una letra minscula (los nombres de las clases empiezan con una letra mayscula). Un nombre de variable Java: debe ser un identificador legal de Java comprendido en una serie de caracteres Unicode. Unicode es un sistema de codificacin que soporta texto escrito en distintos lenguajes humanos. Unicode permite la codificacin de 34.168 caracteres. Esto le permite utilizar en sus programas Java varios alfabetos como el japons, el Griego, el Ruso o el Hebreo. Esto es importante para que los programadores puedan escribir cdigo en su lenguaje nativo. No puede ser el mismo que una palabra clave No deben tener el mismo nombre que otras variables cuyas declaraciones aparezcan en el mismo mbito. Tipo, es el tipo de la variable, pudiendo ser un tipo bsico o un objeto de una clase o de un interfaz. Tambin puede ser una matriz o vector.

Mtodos
Para definir los mtodos se emplea la siguiente sintaxis:

nombreFunc debe de ser un identificador vlido en el lenguaje. Tipo es el tipo del valor devuelto por la funcin, pudiendo ser: Un tipo bsico. Un objeto de una clase o interfaz. En este tipo de objetos se incluyen las matrices o vectores. void, en el caso de no devolver ningn valor.

El mtodo main.
El mtodo, main(), es el cerebro de cualquier aplicacin Java. Cuando se ejecuta una aplicacin Java utilizando el intrprete Java, se debe especificar el nombre de la clase que se desea ejecutar. El intrprete entonces, invoca al mtodo main() definido dentro de esa clase, que debe controlar el flujo del programa, pedir al sistema los recursos que necesite y ejecutar cualquier otro mtodo necesario para completar la funcionalidad de la aplicacin. La definicin del mtodo main() debe estar precedida por tres modificadores: public indica que el mtodo main() puede ser llamado por cualquier objeto. static indica que el mtodo main() es un mtodo esttico, es decir, un mtodo propio de la clase. void indica que el mtodo main() no devolver ningn valor.

El mtodo main() en Java es similar a la funcin main() de C y C++. Cuando se ejecuta un programa escrito en C o C++, arranca llamando en primer lugar a la funcin main(), que llamar a las dems funciones necesarias en la ejecucin del programa. De forma similar, en el lenguaje Java, cuando se ejecuta una clase con el intrprete Java, el sistema comienza llamando al mtodo main() de la clase, que llamar a los dems mtodos necesarios para completar la ejecucin de la aplicacin. Si se intenta ejecutar una clase con el intrprete Java que no contenga el mtodo main(), el intrprete generar un mensaje de error.

El mtodo main() acepta como argumento un array de Strings:

Este array de Strings es el mecanismo a travs del cual el sistema puede pasar informacin a la aplicacin. Cada una de las cadenas String es un argumento de lnea de comandos. Permiten pasar informacin a la aplicacin, para variar su ejecucin, sin necesidad de recompilarla.

Operadores.
Aritmticos.
Realizan las operaciones aritmticas bsicas: suma (+), resta (-), multiplicacin (*), divisin (/) y mdulo (%) para datos de tipo numrico, tanto enteros como reales. Estas son operaciones binarias porque admiten dos operandos.

Ejemplo de utilizacin de estos operadores:

Dentro de los operadores aritmticos tenemos los unarios + y que simplemente operan con el signo de un valor dado. Por ejemplo:

El operador se encarga de cambiar el signo, y el + sencillamente deja el signo como est. Nuevamente no podemos almacenar el resultado en enteros cortos, los tipos byte y short los transforma en int. Dentro del catlogo de operadores tenemos algunos unarios ms. Se trata del auto incremental ++ y del auto decremental --. Respectivamente, suma y resta una unidad al valor. Ambos operadores pueden ser sufijos, es decir se coloca antes del operando o posfijo que se sita detrs. Veamos algunos ejemplos:

En este ejemplo estamos incrementado y decrementando el valor de i. A priori parece que los operadores funcionan igual, tanto como posfijo como sufijo, pero su comportamiento es diferente. Observemos lo que ocurre en este ejemplo:

Partiendo del mismo valor, vemos que j se increment, mientras que la variable i se mostr sin cambios. Si colocamos el operador como sufijo, primero se evala la variable y luego se realiza la operacin. En el caso de la variable i, antes de incrementar su valor se mostr por pantalla. Para la variable j el procedimiento fue inverso. Antes de mostrar su valor se increment.

Ejemplo Nombre ++a Pre-incremento

Efecto Incrementa a en uno, y luego devuelve a.

a++

Post-incremento

Devuelve a, y luego incrementa a en uno.

--a

Pre-decremento

Decrementa a en uno, luego devuelve a.

a--

Post-decremento

Devuelve a, luego decrementa a en uno.

Lgicos.
Como deben suponer, trabajan con operandos booleanos. Realizan las operaciones lgicas de conjuncin (AND), disyuncin (OR), negacin (NOT) y la disyuncin exclusiva (XOR). Operadores volanos Nombre Operador Utilizacin Resultado AND && A && B verdadero cuando A y B son verdaderos. Evaluacin condicional. OR || A || B verdadero cuando A o B son verdaderos. Evaluacin condicional. NOT AND ! & !A A&B verdadero si A es falso. verdadero cuando A y B son verdaderos. Siempre evala ambos operandos. OR | A|B verdadero cuando A o B son verdaderos. Siempre evala ambos operandos. XOR ^ A^B verdadero cuando A y B son diferentes

Cada una de estas operaciones tiene asociada una tabla de verdad. Esto nos permite ver el resultado de un operador aplicado a las distintas combinaciones de valores que pueden tener los operandos. Si probamos de quitar un ampersand ( & ) del operador, vemos que obtenemos los mismos resultados. Existen dos operadores AND, uno con dos smbolos & y el otro con uno solo. Tambin tenemos dos operadores OR.

Parece extrao, sobre todo porque tienen la misma tabla de verdad. Pero internamente tienen un comportamiento diferente. Cuando estamos en presencia de un operador con un solo smbolo, siempre se evalan ambos operandos. En cambio para el operador con el smbolo repetido, su evaluacin cambia segn el valor del primer operando. Por ejemplo tenemos la siguiente operacin.

Comparacin.
Revisando algunas definiciones matemticas, nos enteramos que los nmeros conforman un conjunto ordenado. Cada uno tiene una posicin relativa. Sabemos que el 2 "es menor que" el 4 y que el 6 "es ms grande que" el 1. Al comparar dos nmeros, realizamos una funcin de relacin. En java disponemos de los operadores relacionales para verificar si se cumple una relacin. Por ejemplo el operador de equivalencia ( == ) nos devuelve un valor de verdadero si los operandos son iguales. Estas operaciones comparan dos valores numricos y retorna con un valor booleano.

Operadores relacionales Operador Utilizacin Resultado > >= A>B A >= B verdadero si A es mayor que B verdadero si A es mayor o igual que B < <= A<B A <= B verdadero si A es menor que B verdadero si A es menor o igual que B == != A == B A != B verdadero si A es igual a B verdadero si A es distinto de B

Aqu tenemos un programa para ver el funcionamiento de estos operadores:

Control de flujo.
Asumiremos conocido el uso de cada uno de los bloques de control de flujo, por lo que nos limitaremos a mostrar su sintaxis.

if-else.
La estructura de seleccin simple en Java se realiza mediante la sentencia if (si, en ingles). La sintaxis es la siguiente:

La condicin es una expresin booleana. La sentencia se ejecuta solamente si la expresin booleana es verdadera. Qu ocurre si la condicin no se cumple? En este caso nada. Podemos agregar una serie de instrucciones que se ejecutarn solo si la condicin no se cumple. Para esto tendremos que agregar la sentencia else. La estructura de seleccin quedar as:

Si la condicin es verdadera se ejecuta la sentencia 1 en caso contrario se ejecuta la sentencia 2. Ambas sentencias nunca se ejecutarn al mismo tiempo, son excluyentes. Las buenas prcticas en defensa de un cdigo mantenible han dictaminado que utilicemos las llaves en todo momento, an en el caso que utilicemos una sola sentencia.

Switch Case
Una de las mayores dificultades de los novatos en programacin de JAVA es recordar cuando utilizamos en la programacin mltiples selecciones. EN JAVA la sentencia es Switch con la siguiente estructura, se aplica slo a variables que puedan ser convertidas implcitamente a int.

while.
La sentencia while es la ms sencilla de las estructuras de iteracin. La iteracin continuar hasta que su condicin sea falsa.

La condicin tiene que tomar un valor booleano (verdadero o falso). Si este valor es verdadero, se ejecutar la sentencia. Concluida esta accin se vuelve a evaluar la condicin. Proseguirn los ciclos hasta que la condicin no cambie a falso. Esta es una estructura de iteracin pre prueba, es decir primero se evala la condicin antes de realizar cualquier accin. Si de entrada la condicin es falsa nunca ejecutar el conjunto de sentencias.

Dentro del conjunto de sentencia que controla, debe existir alguna que cambie el valor de la condicin que se est evaluando.

Do while.
La sentencia de iteracin do-while es de tipo pos prueba. Primero realiza las acciones luego pregunta. La sintaxis es la siguiente:

Observamos que es como un while pero al revs. Primeramente se ejecuta la sentencia y luego evala la condicin. Si la expresin de la condicin es verdadera vuelve a dar un ciclo. De lo contrario, termina. Esto nos garantiza que la sentencia se ejecute al menos una vez.

Resulta til para los casos en donde tendremos que realizar ciertas acciones antes de verificar una condicin.

For
La sentencia for me permite repetir un ciclo n veces, en donde se debe determinar el valor inicial y cuantas veces se repetir. Sintaxis:

Bucle infinito: no hay control, entonces no se detiene

Operador coma:

Tipos de datos complejos, basados en tipos primitivos.


Los tipos de datos complejos, basados en primitivos, son bsicamente un encapsulamiento del tipo simple al que representan, le agregan funcionalidad a estos: conversiones, operaciones complejas, etc. Tipo Nativo byte short int long float double char boolean Equivalente Referenciado Byte Short Integer Long Float Double Character Boolean

Instanciacin mediante el operador new.


El operador new reserva memoria dinmicamente para un objeto.

Tambin hace que se llame al constructor de la clase. En este caso se llama al constructor por defecto. Si el constructor recibe parmetros se deben indicar entre los parntesis.

Arreglos.
El tipo llamado arreglo o array, es el tipo ms conocido y en muchos lenguajes, el nico tipo de datos estructurados que se ha implementado. Un tipo arreglo es una lista de datos con un nmero fijo de componentes, todos del mismo tipo denominado tipo base; los que son referenciados o calificados mediante ndices o expresiones ordinales encerradas en corchetes, que actan como prefijo al identificador del arreglo, siendo su tipo denominado tipo ndice. Algunas de sus caractersticas ms importantes de los arrays son las siguientes: Los arrays se crean con el operador new seguido del tipo y nmero de elementos. Se puede acceder al nmero de elementos de un arraycon la variable miembro implcita length (por ejemplo, vect.length). Se accede a los elementos de un array con los corchetes [] y un ndice que vara de 0 a length-1. Se pueden crear arrays de objetos de cualquier tipo. En principio un array de objetos es un array de referencias que hay que completar llamando al operador new. Los elementos de un array se inicializan al valor por defecto del tipo correspondiente (cero para valores numricos, la cadena vaca para Strings, false para boolean, null para referencias). Como todos los objetos, los arrays se pasan como argumentos a los mtodos por referencia. Se pueden crear arrays annimos (por ejemplo, crear un nuevo array como argumento actual en la llamada a un mtodo).

Declaracin de Arreglos
Como otras variables, antes de poder utilizar un array primero se debe declarar. De nuevo, al igual que otras variables, la declaracin de un array tiene dos componentes primarios: el tipo del array y su nombre. Un tipo de array incluye el tipo de dato de los elementos que va contener el array. Por ejemplo, el tipo de dato para un array que slo va a contener elementos enteros es un array de enteros. No puede existir un array de tipo de datos genrico en el que el tipo de sus elementos est indefinido cuando se declara el array. Aqu tienes la declaracin de un array de enteros:

La parte int[] de la declaracin indica que arrayDeEnteros es un array de enteros. La declaracin no asigna ninguna memoria para contener los elementos del array. Si se intenta asignar un valor o acceder a cualquier elemento de arrayDeEnteros antes de haber asignado la memoria para l, el compilador dar un error como este y no compilar el programa: testing.java:64: Variable arrayDeEenteros may not have been initialized. Para asignar memoria a los elementos de un array, primero se debe ejemplarizar el array. Se puede hacer esto utilizando el operador new de Java. (Realmente, los pasos que se deben seguir para crear un array son similares a los se deben seguir para crear un objeto de una clase: declaracin, ejemplificacin e inicializacin. La siguiente sentencia asigna la suficiente memoria para que arrayDeEnteros pueda contener diez enteros.

En general, cuando se crea un array, se utiliza el operador new, ms el tipo de dato de los elementos del array, ms el nmero de elementos deseados encerrado entre corchetes cuadrados ([ y ]).

Ahora que se ha asignado memoria para un array ya se pueden asignar valores a los elementos y recuperar esos valores:

Como se puede ver en el ejemplo anterior, para referirse a un elemento del array, se aade corchetes cuadrados al nombre del array. Entre los corchetes cuadrados se indica (bien con una variable o con una expresin) el ndice del elemento al que se quiere acceder. Observa que en Java, el ndice del array empieza en 0 y termina en la longitud del array menos uno.

Hay otro elemento interesante en el pequeo ejemplo anterior. El bucle for itera sobre cada elemento de arrayDeEnteros asignndole valores e imprimiendo esos valores. Observa el uso de arrayDeEnteros.length para obtener el tamao real del array. length es una propiedad proporcionada para todos los arrays de Java. Los arrays pueden contener cualquier tipo de dato legal en Java incluyendo los tipos de referencia como son los objetos u otros array. Por ejemplo, el siguiente ejemplo declara un array que puede contener diez objetos String.

Los elementos en este array son del tipo referencia, esto es, cada elemento contiene una referencia a un objeto String. En este punto, se ha asignado suficiente memoria para contener las referencias a los Strings, pero no se ha asignado memoria para los propios Strings. Si se intenta acceder a uno de los elementos de arraydeStrings obtendr una excepcin 'NullPointerException' porque el array est vaco y no contiene ni cadenas ni objetos String. Se debe asignar memoria de forma separada para los objetos String:

Las matrices (arreglos de mltiples dimensiones) son arreglos, donde cada uno de sus elementos es a su vez un arreglo. Esto permite que no todos los elementos tengan el mismo tamao, veamos un ejemplo:

Captulo 3: Otras caractersticas del Lenguaje


Modificadores.
Modificadores de Acceso.
Los modificadores de acceso permiten al diseador de una clase determinar quien accede a los datos y mtodos miembros de una clase. Los modificadores de acceso preceden a la declaracin de un elemento de la clase (ya sea dato o mtodo), de la siguiente forma: [modificadores] tipo_variable nombre; [modificadores] tipo_devuelto nombreMetodo (lista_Argumentos); Existen los siguientes modificadores de acceso: public - private - protected - Se explicar en el captulo dedicado a la herencia. Sin modificador - Se puede acceder al elemento desde cualquier clase del package donde se define la clase. Pueden utilizarse estos modificadores para cualquier tipo de miembros de la clase, incluidos los constructores (con lo que se puede limitar quien puede crear instancias de la clase). public. Todo el mundo puede acceder al elemento. Si es un dato miembro, todo el mundo puede ver el elemento, es decir, usarlo y asignarlo. Si es un mtodo todo el mundo puede invocarlo. private. Slo se puede acceder al elemento desde mtodos de la clase, o slo puede invocarse el mtodo desde otro mtodo de la clase. Las clases de tipo private se definen generalmente dentro del archivo de otra clase.

protected. Slo se puede acceder a l desde las clases que se encuentran en el mismo paquete y desde las clases que heredan de l. No se puede declarar una clase de tipo protected. default. Tambin conocido como package, se entiende su uso al no explicitar ninguno de los modificadores anteriores.

Modificadores
final. En un atributo: no modificable En un mtodo: no se puede redefinir en un heredero En una clase: no se puede heredar de ella.

static. Pertenece a la clase (no a una instancia). Se puede acceder a l sin necesidad de crear un objeto concreto. abstract. Permite declarar una clase como abstracta. Si la clase contiene a lo menos un mtodo abstracto, ella se debe declarar como abstracta.

Constructores.
Cuando se crea un objeto (se instancia una clase) es posible definir un proceso de inicializacin que prepare el objeto para ser usado. Esta inicializacin se lleva a cabo invocando un mtodo especial denominado constructor. Esta invocacin es implcita y se realiza automticamente cuando se utiliza el operador new. Los constructores tienen algunas caractersticas especiales: 1. El nombre del constructor tiene que ser igual al de la clase. 2. Puede recibir cualquier nmero de argumentos de cualquier tipo, como cualquier otro mtodo. 3. No devuelve ningn valor (en su declaracin no se declara ni siquiera void). 4. El constructor no es un miembro ms de una clase. Slo es invocado cuando se crea el objeto (con el operador new). No puede invocarse explcitamente en ningn otro momento. 5. Si no se define explcitamente uno, Java crea uno por defecto, sin argumentos.

Herencia: extensin de clases.


Java permite el empleo de la herencia, caracterstica muy potente que permite definir una clase tomando como base a otra clase ya existente. Esto es una de las bases de la reutilizacin de cdigo, en lugar de copiar y pegar. En java, como ya vimos la herencia se especifica agregando la clasula extends despus del nombre de la clase. En la clasula extends indicaremos el nombre de la clase base de la cul queremos heredar. Al heredar de una clase base, heredaremos tanto los atributos como los mtodos, mientras que los constructores son utilizados, pero no heredados. Construyamos la clase Punto3d.java con el siguiente cdigo:

Polimorfismo:
Se refiere a la capacidad del lenguaje de responder a un mismo mensaje de diferentes maneras. Adecundose a la situacin actual. En java se presenta en cuatro formas:

Herencia:
Consiste en que una vez se ha definido una superclase para un grupo de subclases, cualquier instancia de esas subclases puede ser usada en el lugar de la superclase. Significa que podemos referenciar un objeto de una subclase mediante una referencia declarada como una de sus superclases.

Por tanto mediante el polimorfismo podemos asignar a una referencia de un tipo superior en la jerarqua de herencia, una instancia de un tipo inferior (que herede). Ahora bien, que la referencia sea de otro tipo no significa que los mtodos que se ejecuten sean distintos. Siguen siendo los de la instancia. Algunos usos habituales del polimorfismo en Java son: Implementacin de colecciones genricas. Implementacin de mtodos genricos.

(*) Ejercicio: Completar ejemplo.

Sobrecarga de mtodos
El concepto de polimorfismo, en cuanto a cambio de forma, se puede extender a los mtodos. Java permite que varios mtodos dentro de una clase se llamen igual, siempre y cuando su lista de parmetros sea distinta. Por ejemplo, si tuviramos un mtodo que sirviera para sumar nmeros pero sin indicar de qu tipo:

Sobrecarga de constructores
Esto tambin se aplica a los constructores. De hecho, es la aplicacin ms habitual de la sobrecarga:

Sobreescritura de mtodos.
Para entender en su totalidad el cdigo fuente escrito en Java, es imprescindible tener muy claro el concepto de la redefinicin o sobreescritura de mtodos. La sobreescritura de mtodos es una caracterstica ms de la herencia en Java. Es decir, en Java las nuevas clases se pueden definir extendiendo clases ya existentes. Aqu surgen los conceptos de subclase que sera la clase obtenida, y superclase, que sera la clase que est siendo extendida, tal como tambin ya se ha explicado. Cuando una nueva clase se extiende desde otra que ya exista, todas las variables y mtodos que son miembros de la superclase (y todos aquellos miembros de los antecesores de la superclase) sern tambin miembros de la subclase. En el supuesto de que en el entorno en que se va a mover la nueva subclase, alguno de los mtodos de la superclase (o alguno de sus antecesores) no sea adecuado para los objetos originados de la subclase, es posible reescribir el mtodo en la subclase para que se adapte en su funcionamiento a los objetos del tipo de la subclase. La reescritura del mtodo dentro de la subclase es lo que se conoce por sobreescritura de mtodos (overriding methods). Todo lo que se requiere en Java para poder sobeescribir un mtodo es utilizar el mismo nombre del mtodo en la subclase, el mismo tipo de retorno y la misma lista de argumentos de llamada, y en el cuerpo de ese mtodo en la subclase proporcionar un cdigo diferente y especfico para las acciones que vaya a realizar sobre objetos del tipo que origina la nueva subclase. Se puede reemplazar completamente la implementacin de un mtodo heredado indicando el mismo nombre, la misma lista de argumentos y el mismo tipo de retorno; y colocar en el cuerpo del mtodo el cdigo que realice la funcin que sea menester en su nueva situacin. En el caso del mtodo run(), se podra hacer algo como:

En este fragmento de cdigo, el mtodo run() de la clase MiThread sobreescribe al mtodo run() de la clase Thread y proporciona una nueva implementacin. Hay que tener cuidado con la diferencia entre sobrecargar y sobreescribir un mtodo, y entenderla correctamente. Para sobrecargar un mtodo hay que duplicar el nombre el mtodo y el tipo que devuelve, pero utilizar una lista de argumentos diferente al original. Para sobreescribir un mtodo, no solamente el nombre y el tipo de retorno deben ser iguales, sino que ha de serlo tambin la lista de argumentos. Es decir, que hay que estar atentos a la lista de argumentos que se indica para un mtodo, en evitacin de la sobrecarga cuando en realidad se cree que se est sobreescribiendo, o viceversa.

Manejo de strings:
String.
Los String son objetos de java con una sintaxis especialmente cmoda para representar cadenas de caracteres. Los caracteres se codifican usando Unicode. Java permite escribir directamente cadenas entre comillas.

Para incluir el carcter comillas dobles en una cadena, escriba "\"". Sobre cadenas se define la operacin de concatenar:

La clase String define muchos mtodos interesantes para hacer programas: int length() Longitud: nmero de caracteres boolean equals(String b) Determina si la cadena contiene los mismos caracteres que la cadena b. boolean equalsIgnoreCase(String b) Determina si la cadena contiene los mismos caracteres que la cadena b, independientemente de que estn en maysculas o minsculas. int compareTo(String b) Compara contra la cadena b, devolviendo: o o o un valor negativo si la cadena es anterior a b; cero (0) si la cadena es igual a b; un valor positivo si la cadena es posterior a b.

En las comparaciones se usa el cdigo Unicode, lo que no siempre responde al orden lexicogrfico (de diccionario). String trim() Crea un nuevo objeto eliminado el espacio en blanco que pudiera haber al principio o al final. char charAt(int posicion) Extrae en carcter en la posicin indicada. char[] toCharArray() Conviertr la cadena en un array de caracteres. String substring(int a, int z) Extrae la sub-cadena entre las posiciones a y z. String substring(int desde) Extrae la sub-cadena desde la posicin indicada. int indexOf(char carcter) int indexOf(String cadena) Indican en qu posicin se encuentra el carcter (o cadena) indicado por primera vez, buscando desde el principio. int lastIndexOf(char carcter) int lastIndexOf(String cadena) Indica en qu posicin se encuentra el carcter (o cadena) indicado por primera vez, buscando desde el final. boolean startsWith(String prefijo) Dice si la cadena comienza con el prefijo indicado. boolean endsWith(String sufijo) Dice si la cadena termina con el sufijo indicado. String[] split(String patron) Fragmenta la cadena en varias subcadenas utilizando el patrn indicado como separador.

Cdigo Miguel.length() Miguel.equals(Miguel) Miguel.equals(miguel) Miguel.equalsIgnoreCase(miguel) Miguel.compareTo(Saturnino) Miguel.compareTo(Miguel) Miguel.compareTo(Michelin) Miguel.charAt(1) Miguel.charAt(4) Miguel.toCharArray() Miguel.substring(1, 4) Miguel.substring(1) tragaldabas.indexOf('a') tragaldabas.lasIndexOf('a') tragaldabas.startsWith(tragn) tragaldabas.endsWith(dabas) tragaldabas.split(a)

resultado 6 true false false -6 0 4 'i' 'e' { 'M', 'i', 'g', 'u', 'e', 'l' } igu iguel 2 9 false true { tr, g, ld, b, s }

Las comparaciones entre String se limitan a usar el orden numrico de los cdigos Unicode, lo que a veces choca con el orden al que estamos acostumbrados en los diccionarios, el orden lexicogrfico, que depende de cada idioma. Para realizar comparaciones usando el orden lexicogrfico propio de cada idioma, vase Collator.

StringBuffer.
A diferencia de la clase estndar String, StringBuffer permite trabajar con cadenas de caracteres modificables. El siguiente ejemplo muestra dos mtodos para construir un objeto que un listado de N nmeros separados por comas.

La diferencia en tiempos de ejecucin es notoria:


$ java UsandoStringBuffer 100 mtodo 1: 0ms mtodo 2: 0ms $ java UsandoStringBuffer 1000 mtodo 1: 47ms mtodo 2: 0ms $ java UsandoStringBuffer 10000 mtodo 1: 17218ms mtodo 2: 16ms

El tiempo exacto que tarda en ejecutarse el programa depende de cada ordenador y de qu ms programas hay en ejecucin en un momento dado. Lo importante es la proporcin de tiempos, que es claramente favorable al uso de StringBuffer. La diferencia, inapreciable cuando hay pocos objetos que manejar, se torna apabullante cuando el nmero de objetos crece.

StringTokenizer.
Una de las formas para hacerlo en Java es utilizar la clase StringTokenizer, la cual dividir la cadena en Tokens (por defecto dividir la cadena por espacios).

Si se desea dividir la cadena por otro elemento distinto del espacio se puede llamar al constructor StringTokenizer con un parmetro ms. Por ejemplo, si la cadena tuviera los elementos separados por el caracter #, modificaramos esta lnea de cdigo del ejemplo anterior:

*NOTA: Recordamos que para utilizar esta clase es necesario importar el paquete JAVA que la contiene en las primeras lneas del programa: import java.util.StringTokenizer;

Unidad 2: Caractersticas Avanzadas


Captulo 1: Agrupaciones de objetos.
Introduccin.
Las colecciones son una de las herramientas ms poderosas que se pueden poner en manos de un programador. Por ello, las colecciones que incorporaba Java, adolecan de precariedad y de demasiada rapidez en su desarrollo. Por todo ello, para quien escribe esto ha sido una tremenda satisfaccin comprobar las nuevas colecciones que incorpora el JDK 1.2, y ver que incluso las antiguas han sido rediseadas. Probablemente, las colecciones, junto con la librera Swing, son las dos cosas ms importantes que aporta la versin 1.2 del JDK, y ayudarn enormemente a llevar a Java a la primera lnea de los lenguajes de programacin. Hay cambios de diseo que hacen su uso ms simple. Por ejemplo, muchos nombres son ms cortos, ms claros y ms fciles de entender; e incluso algunos de ellos han sido cambiados totalmente para adaptarse a la terminologa habitual. El rediseo tambin incluye la funcionalidad, pudiendo encontrar ahora listas enlazadas y colas. El diseo de una librera de colecciones es complicado y difcil. En C++, la Standard Template Library (STL) cubra la base con muchas clases diferentes. Desde luego, esto es mejor que cuando no hay nada, pero es difcil de trasladar a Java porque el resultado llevara a tal cantidad de clases que podra ser muy confuso. En el otro extremo, hay libreras de colecciones que constan de una sola clase, Collection, que acta como un Vector y una Hashtable al mismo tiempo. Los diseadores de las nuevas colecciones han intentado mantener un difcil equilibrio: por un lado disponer de toda la funcionalidad que el programador espera de una buena librera de colecciones, y, por otro, que sea tan fcil de aprender y utilizar como la STL y otras libreras similares. El resultado puede parecer un poco extrao en ocasiones, pero, al contrario que en las libreras anteriores al JDK 1.2, no son decisiones accidentales, sino que estn tomadas a conciencia en funcin de la complejidad. Es posible que se tarde un poco en sentirse cmodo con algunos de los aspectos de la librera, pero de seguro que el programador intentar adoptar rpidamente

estos nuevos mtodos. Hay que reconocer que Joshua Bloch de Sun, ha hecho un magnfico trabajo en el rediseo de esta librera.

Las Colecciones y los Mapas pueden ser implementados de muy diversas formas, en funcin de las necesidades concretas de programacin, por lo que puede resultar til el siguiente diagrama de herencia de las nuevas colecciones que utiliza la notacin grfica propugnada por la metodologa OMT (Object Modeling Technique). El diagrama est hecho a partir de la versin beta del JDK 1.2, as que puede haber cosas cambiadas con respecto a la versin actual. Quizs tambin, un primer vistazo puede abrumar al lector, pero a lo largo de la seccin se comprobar que es bastante simple, porque solamente hay tres colecciones: Map, List y Set; y solamente dos o tres implementaciones de cada una de ellas. Las cajas punteadas representan interfaces y las slidas representan clases normales, excepto aquellas en que el texto interior comienza por Abstract, que representan clases abstractas. Las flechas indican que una clase puede generar objetos de la clase a la que apunta; por ejemplo, cualquier Collection puede producir un Iterator, mientras que una List puede producir un ListIterator (al igual que un Iterator normal, ya que List hereda de Collection).

Los interfaces que tienen que ver con el almacenamiento de datos son: Collection, Set, List y Map. Normalmente, un programador crear casi todo su cdigo para entenderse con estos interfaces y solamente necesitar indicar especficamente el tipo de datos que se estn usando en el momento de la creacin. Por ejemplo, una Lista se puede crear de la siguiente forma:

Desde luego, tambin se puede decidir qu lista sea una lista enlazada, en vez de una lista genrica, y precisar ms el tipo de informacin de la lista. Lo bueno, y la intencin, del uso de interfaces es que si ahora se decide cambiar la implementacin de la lista, solamente es necesario cambiar el punto de creacin, por ejemplo:

El resto del cdigo permanece invariable. En la jerarqua de clases, se pueden ver algunas clases abstractas que pueden confundir en un principio. Son simplemente herramientas que implementan parcialmente un interfaz. Si el programador quiere hacer su propio Set, por ejemplo, no tendra que empezar con el interfaz Set e implementar todos los mtodos, sino que podra derivar directamente de AbstractSet y ya el trabajo para crear la nueva clase es mnimo. Sin embargo, la nueva librera de colecciones contiene suficiente funcionalidad para satisfacer casi cualquier necesidad, as que en este Tutorial se ignorarn las clases abstractas. Por lo tanto, a la hora de sacar provecho del diagrama es suficiente con lo que respecta a los interfaces y a las clases concretas. Lo normal ser construir un objeto correspondiente a una clase concreta, moldearlo al correspondiente interfaz y ya usas ese interfaz en el resto del cdigo.

El ejemplo es muy simple y consiste en una coleccin de objetos String que se imprimen.

Como las nuevas colecciones forman parte del paquete java.util, no es necesario importar ningn paquete adicional para utilizarlas. A continuacin se comentan los trozos interesantes del cdigo del ejemplo. La primera lnea del mtodo main() crea un objeto ArrayList y lo moldea a una Collection. Como este ejemplo solamente utiliza mtodos de Collection, cualquier objeto de una clase derivada de Collection debera funcionar, pero se ha cogido un ArrayList porque es el caballo de batalla de las colecciones y viene a tomar el relevo al Vector. El mtodo add(), como su nombre sugiere, coloca un nuevo elemento en la coleccin. Sin embargo, la documentacin indica claramente que add() "asegura que la coleccin contiene el elemento indicado". Esto es para que un Set tenga significado, ya que solamente aadir el elemento si no se encuentra en la coleccin. Con un ArrayList, o cualquier otra lista ordenada, add() significa siempre "colocarlo dentro". Todas las colecciones pueden producir un Iterator invocando al mtodo iterator(). Un Iterator viene a ser equivalente a una Enumeration, a la cual reemplaza, excepto en los siguientes puntos: Utiliza un nombre que est histricamente aceptado y es conocido en toda la literatura de programacin orientada a objetos.

Utiliza nombres de mtodos ms cortos que la Enumeration: hasNext() en vez de hasMoreElements(), o next() en lugar de nextElement()

En el ejemplo se utiliza un Iterator para desplazarse por la coleccin e ir imprimiendo cada uno de sus elementos.

Colecciones
A continuacin se indican los mtodos que estn disponibles para las colecciones, es decir, lo que se puede hacer con un Set o una List, aunque las listas tengan funcionalidad aadida que ya se ver, y Map no hereda de Collection, as que se tratar aparte. boolean add( Object ) Asegura que la coleccin contiene el argumento. Devuelve false si no se puede aadir el argumento a la coleccin boolean addAll( Collection ) Aade todos los elementos que se pasan en el argumento. Devuelve true si es capaz de incorporar a la coleccin cualquiera de los elementos del argumento void clear() Elimina todos los elementos que componen la coleccin boolean contains( Object ) Verdadero si la coleccin contiene el argumento que se pasa como parmetro boolean isEmpty() Verdadero si la coleccin est vaca, no contiene elemento alguno Iterator iterator() Devuelve un Iterator que se puede utilizar para desplazamientos a travs de los elementos que componen la coleccin boolean remove( Object ) Si el argumento est en la coleccin, se elimina una instancia de ese elemento y se devuelve true si se ha conseguido boolean removeAll( Collection ) Elimina todos los elementos que estn contenidos en el argumento. Devuelve true si consigue eliminar cualquiera de ellos int size() Devuelve el nmero de elementos que componen la coleccin

Listas
Hay varias implementaciones de List, siendo ArrayList la que debera ser la eleccin por defecto, en caso de no tener que utilizar las caractersticas que proporcionan las dems implementaciones.

List (interfaz)
La ordenacin es la caracterstica ms importante de una Lista, asegurando que los elementos siempre se mantendrn en una secuencia concreta. La Lista incorpora una serie de mtodos a la Coleccin que permiten la insercin y borrar de elementos en medio de la Lista. Adems, en la Lista Enlazada se puede generar un ListIterator para moverse a travs de las lista en ambas direcciones.

ArrayList
Es una Lista volcada en un Array. Se debe utilizar en lugar de Vector como almacenamiento de objetos de propsito general. Permite un acceso aleatorio muy rpido a los elementos, pero realiza con bastante lentitud las operaciones de insertado y borrado de elementos en medio de la Lista. Se puede utilizar un ListIterator para moverse hacia atrs y hacia delante en la Lista, pero no para insertar y eliminar elementos.

LinkedList
Proporciona un ptimo acceso secuencial, permitiendo inserciones y borrado de elementos de en medio de la Lista muy rpidas. Sin embargo es bastante lento el acceso aleatorio, en comparacin con la ArrayList. Dispone adems de los mtodos addLast(), getFirst(), getLast(), removeFirst() y removeLast(), que no estn definidos en ningn interfaz o clase base y que permiten utilizar la Lista Enlazada como una Pila, una Cola o una Cola Doble.

Sets
Set tiene exactamente el mismo interfaz que Collection, y no hay ninguna funcionalidad extra, como en el caso de las Listas. Un Set es exactamente una Coleccin, pero tiene utilizada en un entorno determinado, que es ideal para el uso de la herencia o el polimorfismo. Un Set slo permite que exista una instancia de cada objeto. A continuacin se muestran las diferentes implementaciones de Set, debiendo utilizarse HashSet en general, a no ser que se necesiten las caractersticas proporcionadas por alguna de las otras implementaciones.

Set (interfaz)
Cada elemento que se aada a un Set debe ser nico, ya que el otro caso no se aadir porque el Set no permite almacenar elementos duplicados. Los elementos incorporados al Conjunto deben tener definido el mtodo equals(), en aras de establecer comparaciones para eliminar duplicados. Set tiene el mismo interfaz que Collection, y no garantiza el orden en que se encuentren almacenados los objetos que contenga.

HashSet
Es la eleccin ms habitual, excepto en Sets que sean muy pequeos. Debe tener definido el mtodo hashCode().

ArraySet
Un Set encajonado en un Array. Esto es til para Sets muy pequeos, especialmente aquellos que son creados y destruidos con frecuencia. Para estos pequeos Sets, la creacin e iteracin consume muchos menos recursos que en el caso del HashSet. Sin embargo, el rendimiento es muy malo en el caso de Sets con gran cantidad de elementos.

TreeSet
Es un Set ordenado, almacenado en un rbol balanceado. En este caso es muy fcil extraer una secuencia ordenada a partir de un Set de este tipo. Las definiciones de los mtodos equals() y hashCode() son semejantes a las de ejemplos anteriores. Se debe definir equals() en ambos casos, mientras que hashCode() solamente es necesario si la clase corresponde a un HashSet, que debera ser la primera eleccin a la hora de implementar un Set.

Mapas
Los Mapas almacenan informacin en base a parejas de valores, formados por una clave y el valor que corresponde a esa clave.

Map (interfaz)
Mantiene las asociaciones de pares clave-valor, de forma que se puede encontrar cualquier valor a partir de la clave correspondiente.

HashMap
Es una implementacin basada en una tabla hash. Proporciona un rendimiento muy constante a la hora de insertar y localizar cualquier pareja de valores; aunque este rendimiento se puede ajustar a travs de los constructores que permite fijar la capacidad y el factor de carga de la tabla hash.

ArrayMap
Es un Mapa circunscrito en un Array. Proporciona un control muy preciso sobre el orden de iteracin. Est diseado para su utilizacin con Mapas muy pequeos, especialmente con aquellos que se crean y destruyen muy frecuentemente. En este caso de Mapas muy pequeos, la creacin e iteracin consume muy pocos recursos del sistema, y muchos menos que el HashMap. El rendimiento cae estrepitosamente cuando se intentan manejar Mapas grandes.

TreeMap
Es una implementacin basada en un rbol balanceado. Cuando se observan las claves o los valores, se comprueba que estn colocados en un orden concreto, determinado por Comparable o Comparator, que ya se vern. Lo importante de un TreeMap es que se pueden recuperar los elementos en un determinado orden. TreeMap es el nico mapa que define el mtodo subMap(), que permite recuperar una parte del rbol solamente. El mtodo keySet() genera un Set que contiene las claves que componen el Mapa; en este caso, es tratado como una Coleccin.

Clases Genricas
Observe el uso de un ArrayList -- parte del "Collections Framework" -- sin utilizar clases genricas:

Primeramente observe que en el ArrayList son insertados una serie de String's y al final es colocado un StringBuffer, esto tipo de error no es detectado por el compilador, inclusive la nica manera en que es detectada esta falla es hasta que se intentan accesar los valores del mismo ArrayList, una deteccin simple en esta clase sencilla, pero un proceso que se puede tornar complicado si los valores son accesados en diversas libreras. Adems, note que al momento de iterar sobre la coleccin de objetos tambin es necesario hacer un "cast" explicito hacia String sobre todo valor. Ahora intente compilar esta misma clase utilizando la versin JDK 5, y observar un mensaje como el siguiente: Note: Idiomas.java uses unchecked or unsafe operations. Note: Recompile with Xlint:unchecked for details.

El compilador del JDK 5 detecta que la clase contiene operaciones inseguras, en este caso, no definir el tipo de objetos esperados en la clase del "Collections Framework". Si recompila la clase con la opcin -Xlint, observar una lista detallada de las operaciones consideradas inseguras por Java 5. Ahora observemos la misma clase modificada para utilizar clases genricas:

La nomenclatura utilizada por clases genricas es <Tipo de Clase>, misma que debe ser utilizada en la referencia de la coleccin, al inicializar la clase y al momento de extraerla en el iterador. Al emplear este mecanismo, cualquier intento de colocar un tipo de objeto distinto aquel definido en la clase genrica, resulta en un error al momento de compilar.

El proceso para utilizar clases genricas en listas de valores (key-value lists) interfase Map -- es muy similar al de listas, observemos el siguiente ejemplo:

La nomenclatura de < > permanece idntica, sin embargo, debido a que se trata de listas de valores, es agregado primeramente el tipo de clase para el identificador ("key") y posteriormente el tipo de clase para el valor. Ntese tambin que como parmetro de clase genrica es utilizado la clase universal Object, esto es un indicador de la flexibilidad con que pueden ser empleadas clases genricas en un diseo, pudiendo ser cualquier tipo de clase para restringir el tipo de objetos colocados en una coleccin. Tome en cuenta que al utilizar la clase Object como clase genrica estara perdiendo todas las salvaguardas ofrecidas por esta funcionalidad, lo anterior se debe a que todo objeto es derivado directamente de esta clase universal. Al definir una coleccin con clase genrica Object no recibira ningn tipo de error ya que todo objeto proviene de la jerarqua de herencias en Object.

Captulo 2: Manejo de Excepciones.


Conceptos Generales.
Existe una regla de oro en el mundo de la programacin: en los programas ocurren errores. Esto es sabido. Pero qu sucede realmente despus de que ha ocurrido el error? Cmo se maneja el error? Quin lo maneja?, Puede recuperarlo el programa? El lenguaje Java utiliza excepciones para proporcionar capacidades de manejo de errores. En esta leccin aprenders qu es una excepcin, cmo lanzar y capturar excepciones, qu hacer con una excepcin una vez capturada, y cmo hacer un mejor uso de las excepciones heredadas de las clases proporcionadas por el entorno de desarrollo de Java. El trmino excepcin es un forma corta da la frase "suceso excepcional" y puede definirse de la siguiente forma. Una excepcin es un evento que ocurre durante la ejecucin del programa que interrumpe el flujo normal de las sentencias. Muchas clases de errores pueden utilizar excepciones -- desde serios problemas de hardware, como la avera de un disco duro, a los simples errores de programacin, como tratar de acceder a un elemento de un array fuera de sus lmites. Cuando dicho error ocurre dentro de un mtodo Java, el mtodo crea un objeto 'exception' y lo maneja fuera, en el sistema de ejecucin. Este objeto contiene informacin sobre la excepcin, incluyendo su tipo y el estado del programa cuando ocurri el error. El sistema de ejecucin es el responsable de buscar algn cdigo para manejar el error. En terminologa java, crear una objeto exception y manejarlo por el sistema de ejecucin se llama lanzar una excepcin. Despus de que un mtodo lance una excepcin, el sistema de ejecucin entra en accin para buscar el manejador de la excepcin. El conjunto de "algunos" mtodos posibles para manejar la excepcin es el conjunto de mtodos de la pila de llamadas del mtodo donde ocurri el error. El sistema de ejecucin busca hacia atrs en la pila de llamadas,

empezando por el mtodo en el que ocurri el error, hasta que encuentra un mtodo que contiene el "manejador de excepcin" adecuado. Un manejador de excepcin es considerado adecuado si el tipo de la excepcin lanzada es el mismo que el de la excepcin manejada por el manejador. As la excepcin sube sobre la pila de llamadas hasta que encuentra el manejador apropiado y una de las llamadas a mtodos maneja la excepcin, se dice que el manejador de excepcin elegido captura la excepcin. Si el sistema de ejecucin busca exhaustivamente por todos los mtodos de la pila de llamadas sin encontrar el manejador de excepcin adecuado, el sistema de ejecucin finaliza (y consecuentemente y el programa Java tambin). Mediante el uso de excepciones para manejar errores, los programas Java tienen las siguientes ventajas frente a las tcnicas de manejo de errores tradicionales.

Ventaja 1: Separar el Manejo de Errores del Cdigo "Normal"


En la programacin tradicional, la deteccin, el informe y el manejo de errores se convierten en un cdigo muy liado. Por ejemplo, supongamos que tenemos una funcin que lee un fichero completo dentro de la memoria. En pseudo-cdigo, la funcin se podra parecer a esto.

A primera vista esta funcin parece bastante sencilla, pero ignora todos aquello errores potenciales. Qu sucede si no se puede abrir el fichero? Qu sucede si no se puede determinar la longitud del fichero? Qu sucede si no hay suficiente memoria libre? Qu sucede si la lectura falla? Qu sucede si no se puede cerrar el fichero?

Para responder a estas cuestiones dentro de la funcin, tendramos que aadir mucho cdigo para la deteccin y el manejo de errores. El aspecto final de la funcin se parecera esto.

Con la deteccin de errores, las 7 lneas originales (en negrita) se han convertido en 29 lneas de cdigo-- a aumentado casi un 400 %. Lo peor, existe tanta deteccin y manejo de errores y de retorno que en las 7 lneas originales y el cdigo est totalmente atestado. Y an peor, el flujo lgico del cdigo tambin se pierde, haciendo difcil poder decir si el cdigo hace lo correcto (si se cierra el fichero realmente si falla la asignacin de memoria?) e incluso es difcil asegurar que el cdigo contine haciendo las cosas correctas cuando se modifique la funcin tres meses despus de haberla escrito. Muchos programadores "resuelven" este problema ignorndolo-- se informa de los errores cuando el programa no funciona. Java proporciona una solucin elegante al problema del tratamiento de errores: las excepciones. Las excepciones le permiten escribir el flujo principal de su cdigo y tratar los casos excepcionales en otro lugar. Si la funcin leerFcihero utilizara excepciones en lugar de las tcnicas de manejo de errores tradicionales se podra parecer a esto:

Observa que las excepciones no evitan el esfuerzo de hacer el trabajo de detectar, informar y manejar errores. Lo que proporcionan las excepciones es la posibilidad de separar los detalles oscuros de qu hacer cuando ocurre algo fuera de la normal. Adems, el factor de aumento de cdigo de este es programa es de un 250% -comparado con el 400% del ejemplo anterior.

Ventaja 2: Propagar los Errores sobre la Pila de Llamadas


Una segunda ventaja de las excepciones es la posibilidad del propagar el error encontrado sobre la pila de llamadas a mtodos. Supongamos que el mtodo leerFichero es el cuarto mtodo en una serie de llamadas a mtodos anidadas realizadas por un programa principal: metodo1 llama a metodo2, que llama a metodo3, que finalmente llama a leerFichero.

Supongamos tambin que metodo1 es el nico mtodo interesado en el error que ocurre dentro de leerFichero. Tradicionalmente las tcnicas de notificacin del error forzaran a metodo2 y metodo3 a propagar el cdigo de error devuelto por leerFichero sobre la pila de llamadas hasta que el cdigo de error llegue finalmente a metodo1 -- el nico mtodo que est interesado en l.

Como se aprendi anteriormente, el sistema de ejecucin Java busca hacia atrs en la pila de llamadas para encontrar cualquier mtodo que est interesado en manejar una excepcin particular. Un mtodo Java puede "esquivar" cualquier excepcin lanzada dentro de l, por lo tanto permite a los mtodos que estn por encima de l en la pila de llamadas poder capturarlo. Slo los mtodos interesados en el error deben preocuparse de detectarlo.

Sin embargo, como se puede ver desde este pseudo-cdigo, requiere cierto esfuerzo por parte de los mtodos centrales. Cualquier excepcin chequeada que pueda ser lanzada dentro de un mtodo forma parte del interface de programacin pblico del mtodo y debe ser especificado en la clausula throws del mtodo. As el mtodo informa a su llamador sobre las excepciones que puede lanzar, para que el llamador pueda decidir concienzuda e inteligentemente qu hacer con esa excepcin. Observa de nuevo la diferencia del factor de aumento de cdigo y el factor de ofuscacin entre las dos tcnicas de manejo de errores. El cdigo que utiliza excepciones es ms compacto y ms fcil de entender.

Ventaja 3: Agrupar Errores y Diferenciacin


Frecuentemente las excepciones se dividen en categoras o grupos. Por ejemplo, podramos imaginar un grupo de excepciones, cada una de las cuales representara un tipo de error especfico que pudiera ocurrir durante la manipulacin de un array: el ndice est fuera del rango del tamao del array, el elemento que se quiere insertar en el array no es del tipo correcto, o el elemento que se est buscando no est en el array. Adems, podemos imaginar que algunos mtodos querran manejar todas las excepciones de esa categoria (todas las excepciones de array), y otros mtodos podra manejar slo algunas excepciones especficas (como la excepcin de ndice no vlido).

Como todas las excepciones lanzadas dentro de los programas Java son objetos de primera clase, agrupar o categorizar las excepciones es una salida natural de las clases y las superclases. Las excepciones Java deben ser ejemplares de la clase Throwable, o de cualquier descendiente de sta. Como de las otras clases Java, se pueden crear subclases de la clase Throwable y subclases de estas subclases. Cada clase 'hoja' (una clase sin subclases) representa un tipo especfico de excepcin y cada clase 'nodo' (una clase con una o ms subclases) representa un grupo de excepciones relacionadas. InvalidIndexException, ElementTypeException, y NoSuchElementException son todas clases hojas. Cada una representa un tipo especfico de error que puede ocurrir cuando se manipula un array. Un mtodo puede capturar una excepcin basada en su tipo especfico (su clase inmediata o interface). Por ejemplo, una manejador de excepcin que slo controle la excepcin de ndice no vlido, tiene una sentencia catch como esta.

ArrayException es una clase nodo y representa cualquier error que pueda ocurrir durante la manipulacin de un objeto array, incluyendo aquellos errores representados especficamente por una de sus subclases. Un mtodo puede capturar una excepcin basada en este grupo o tipo general especificando cualquiera de las superclases de la excepcin en la sentencia catch. Por ejemplo, para capturar todas las excepciones de array, sin importar sus tipos especficos, un manejador de excepcin especificara un argumento ArrayException.

Este manejador podra capturar todas las excepciones de array, incluyendo InvalidIndexException, ElementTypeException, y NoSuchElementException. Se puede descubrir el tipo de excepcin preciso que ha ocurrido comprobando el parmetro del manejador e. Incluso podramos seleccionar un manejador de excepciones que controlara cualquier excepcin con este manejador.

Los manejadores de excepciones que son demasiado generales, como el mostrado aqu, pueden hacer que el cdigo sea propenso a errores mediante la captura y manejo de excepciones que no se hubieran anticipado y por lo tanto no son manejadas correctamente dentro de manejador. Como regla no se recomienda escribir manejadores de excepciones generales. Como has visto, se pueden crear grupos de excepciones y manejarlas de una forma general, o se puede especificar un tipo de excepcin especfico para diferenciar excepciones y manejarlas de un modo exacto.

Bloques try-catch-finally.
El Bloque try El primer paso en la escritura de una manejador de excepciones es poner la sentencia Java dentro de la cual se puede producir la excepcin dentro de un bloque try. Se dice que el bloque try gobierna las sentencias encerradas dentro de l y define el mbito de cualquier manejador de excepciones (establecido por el bloque catch subsecuente) asociado con l. El primer paso en la construccin de un manejador de excepciones es encerrar las sentencias que podran lanzar una excepcin dentro de un bloque try. En general, este bloque se parece a esto.

El segmento de cdigo etiquetado sentencias java est compuesto por una o ms sentencias legales de Java que podran lanzar una excepcin. Existe ms de una forma de realizar esta tarea. Podramos poner cada una de las sentencias que potencialmente pudieran lanzar una excepcin dentro de su propio bloque try, y proporcionar manejadores de excepciones separados para cada uno de los bloques try. O podramos poner todas las sentencias dentro de un slo bloque try y asociar varios manejadores con l.

El siguiente listado utiliza un slo bloque try para todo el mtodo porque el cdigo tiende a ser ms fcil de leer.

Se dice que el bloque try gobierna las sentencias encerradas dentro del l y define el mbito de cualquier manejador de excepcin (establecido por su subsecuente bloque catch) asociado con l. En otras palabras, si ocurre una excepcin dentro del bloque try, esta excepcin ser manejada por el manejador de excepcin asociado con esta sentencia try. Una sentencia try debe ir acompaada de al menos un bloque catch o un bloque finally. Los bloques catch Despus se debe asociar un manejador de excepciones con un bloque try proporcionndole uno o ms bloques catch directamente despus del bloque try. No puede haber ningn cdigo entre el final de la sentencia try y el principio de la primera sentencia catch. La forma general de una sentencia catch en Java es esta.

Como puedes ver, la sentencia catch requiere un slo argumento formal. Este argumento parece un argumento de una declaracin de mtodo. El tipo del argumento AlgunObjetoThrowable declara el tipo de excepcin que el manejador puede manejar y debe ser el nombre de una clase heredada de la clase Throwable definida en el paquete java.lang. (Cuando los programas Java lanzan una excepcin realmente estn lanzado un objeto, slo pueden lanzarse los objetos derivados de la clase Throwable. La variable nombreVariable es el nombre por el que el manejador puede referirse a la excepcin capturada. Se puede acceder a las variables y mtodos de las excepciones en la misma forma que accede a los de cualquier otro objeto. getMessage() es un mtodo proporcionado por la clase Throwable que imprime informacin adicional sobre el error ocurrido. La clase Throwable tambin implementa dos mtodos para rellenar e imprimir el contenido de la pila de ejecucin cuando ocurre la excepcin. Las subclases de Throwable pueden aadir otros mtodos o variables de ejemplar, Para buscar qu metodos implementar en una excepcin, se puede comprobar la definicin de la clase y las definiciones de las clases antecesoras. El bloque catch contiene una serie de sentencias Java legales. Estas sentencias se ejecutan cuando se llama al manejador de excepcin. El sistema de ejecucin llama al manejador de excepcin cuando el manejador es el primero en la pila de llamadas cuyo tipo coincide con el de la excepcin lanzada.

Ocurre una IOException Supongamos que ocurre una excepcin IOException dentro del bloque try. El sistema de ejecucin inmediantamente toma posesin e intenta localizar el manejador de excepcin adecuado. El sistema de ejecucin empieza buscando al principio de la pila de llamadas. Sin embargo, el constructor de FileOutputStream no tiene un manejador de excepcin apropiado por eso el sistema de ejecucin comprueba el siguiente mtodo en la pila de llamadas. Este mtodo tiene dos manejadores de excepciones: uno para ArrayIndexOutOfBoundsException y otro para IOException. El sistema de ejecucin comprueba los manejadores por el orden en el que aparecen despus del bloque try. El primer manejador de excepcin cuyo argumento corresponda con el de la excepcin lanzada es el elegido por el sistema de ejecucin. (El orden de los manejadores de excepcin es importante!) El argumento del primer manejador es una ArrayIndexOutOfBoundsException, pero la excepcin que se ha lanzado era una IOException. Una excepcin IOException no puede asignarse legalmente a una ArrayIndexOutOfBoundsException, por eso el sistema de ejecucin contina la bsqueda de un manejador de excepcin apropiado. El argumento del segundo manejador de excepcin es una IOException. La excepcin lanzada por el constructor de FileOutputStream tambin es un una IOException y por eso puede ser asignada al argumento del manejador de excepciones de IOException. As, este manejador parece el apropiado y el sistema de ejecucin ejecuta el manejador, el cual imprime esta sentencia. Caught IOException: OutFile.txt El sistema de ejecucin sigue un proceso similar si ocurre una excepcin ArrayIndexOutOfBoundsException.

Capturar Varios Tipos de Excepciones con Un Manejador Los dos manejadores de excepcin utilizados por el mtodo son muy especializados. Cada uno slo maneja un tipo de excepcin. El lenguaje Java permite escribir manejadores de excepciones generales que pueden manejar varios tipos de excepciones. Como ya sabes, las excepciones Java son objetos de la clase Throwable (son ejemplares de la clase Throwable a de alguna de sus subclases). Los paquetes Java contienen numerosas clases derivadas de la clase Throwable y as construyen un rbol de clases Throwable. El manejador de excepcin puede ser escrito para manejar cualquier clase heredada de Throwable. Si se escribe un manejador para una clase 'hoja? (una clase que no tiene subclases), se habr escrito un manejador especializado: slo maneja excepciones de un tipo especfico. Si se escribe un manejador para una clase 'nodo' (una clase que tiene subclases), se habr escrito un manejador general: se podr manejar cualquier excepcin cuyo tipo sea el de la clase nodo o de cualquiera de sus subclases. Modifiquemos de nuevo el mtodo. Slo esta vez, escribmoslo para que maneje las dos excepciones IOExceptions y ArrayIndexOutOfBoundsExceptions. El antecesor ms cercano de estas dos excepciones es la clase Exception. As un manejador de excepcin que quisiera manejar los dos tipos se parecera a esto.

La clase Exception est bastante arriba en el rbol de herencias de la clase Throwable. Por eso, adems de capturar los tipos de IOException y ArrayIndexOutOfBoundsException este manejador de excepciones, puede capturar otros muchos tipos. Generalmente hablando, los manejadores de excepcin deben ser ms especializados. Los manejadores que pueden capturar la mayora o todas las excepciones son menos utilizados para la recuperacin de errores porque el manejador tiene que determinar qu tipo de excepcin ha ocurrido de todas formas (para determinar la mejor estrategia de recuperacin). Los manejadores de excepciones que son demasiado generales pueden hacer el cdigo ms propenso a errores mediante la captura y manejo de excepciones que no fueron anticipadas por el programador y para las que el manejador no est diseado. El bloque finally El bloque finally de Java proporciona un mecanismo que permite a sus mtodos limpiarse a s mismos sin importar lo que sucede dentro del bloque try. Se utiliza el bloque finally para cerrar ficheros o liberar otros recursos del sistema. El paso final en la creacin de un manejador de excepcin es proporcionar un mecanismo que limpie el estado del mtodo antes (posiblemente) de permitir que el control pase a otra parte diferente del programa. Se puede hacer esto encerrando el cdigo de limpieza dentro de un bloque finally. El bloque try ha estado trabajando con un PrintStream abierto. El programa debera cerrar ese canal antes de permitir que el control salga del mtodo writeList(). Esto plantea un problema complicado, ya que el bloque try tiene tres posibles salidas. La sentencia new FileOutputStream falla y lanza una IOException. La sentencia vector.elementAt(i) falla y lanza una ArrayIndexOutOfBoundsException. Todo tiene xito y el bloque try sale normalmente. El sistema de ejecucin siempre ejecuta las sentencias que hay dentro del bloque finally sin importar lo que suceda dentro del bloque try.

Esto es, sin importar la forma de salida del bloque try debido a los escenarios 1, 2 3 listados arriba, el cdigo que hay dentro del bloque finally ser ejecutado de todas formas. Este es el bloque finally para el mtodo. Limpia y cierra el canal PrintStream.

Es realmente necesaria la sentencia finally? La primera necesidad de la sentencia finally podra no aparecer de forma inmediata. Los programadores se preguntan frecuentemente "Es realmente necesaria la sentencia finally o es slo azcar para mi Java?" En particular los programadores de C++ dudan de la necesidad de esta sentencia porque C++ no la tiene. Esta necesidad de la sentencia finally no aparece hasta que se considera lo siguiente: Cmo se podra cerrar el PrintStream en el mtodo writeList() si no se proporcionara un manejador de excepcin para la ArrayIndexOutOfBoundsException y ocurre una ArrayIndexOutOfBoundsException? (sera sencillo y legal omitir un manejador de excepcin para ArrayIndexOutOfBoundsException porque es una excepcin en tiempo de ejecucin y el compilador no alerta de que contiene una llamada a un mtodo que puede lanzar una). La respuesta es que el PrintStream no se cerrara si ocurriera una excepcin ArrayIndexOutOfBoundsException y writeList() no proporcionara u manejador para ella -a menos que el mtodo proporcionara una sentencia finally. Existen otros beneficios de la utilizacin de la sentencia finally. En el ejemplo es posible proporcionar un cdigo de limpieza sin la intervencin de una sentencia finally.

Por ejemplo, podramos poner el cdigo para cerrar el PrintStream al final del bloque try y de nuevo dentro del manejador de excepcin para ArrayIndexOutOfBoundsException, como se muestra aqu.

Sin embargo, esto duplica el cdigo, hacindolo difcil de leer y propenso a errores si se modifica ms tarde, Por ejemplo, si se aade cdigo al bloque try que pudiera lanzar otro tipo de excepcin, se tendra que recordar el cerrar el PrintStream dentro del nuevo manejador de excepcin (lo que se olvidar seguro si se parece a m). Relanzar excepciones. Algunas veces, es apropiado capturar las excepciones que ocurren pero en otras ocasiones, sin embargo, es mejor dejar que un mtodo superior en la pila de llamadas maneje la excepcin. Por ejemplo, si se est utilizando una clase como parte de un paquete de clases, probablemente no se querr anticipar las necesidades de todos los usuarios de su paquete. En este caso, es mejor no capturar las excepciones y permitir que alguien la capture ms arriba en la pila de llamadas. Si el mtodo no captura las excepciones que pueden ocurrir dentro de l, debe especificar que puede lanzar excepciones. Modifiquemos el mtodo writeList() para especificar que puede lanzar excepciones.

La setencia new FileOutputStream("OutFile.txt") podra lanzar un excepcin IOException (que no es una excepcin en tiempo de ejecucin). La sentencia victor.elementAt(i) puede lanzar una excepcin ArrayIndexOutOfBoundsException (que es una subclase de la clase RuntimeException, y es una excepcin en tiempo de ejecucin). Para especificar que writeList() lanza estas dos excepciones, se aade la clausula throws a la firma del mtodo de writeList(). La clausula throws est compuesta por la palabra clave throws seguida por una lista separada por comas de todas las excepciones lanzadas por el mtodo. Esta clausula va despus del nombre del mtodo y antes de la llave abierta que define el mbito del mtodo. Aqu tienes un ejemplo. public void writeList() throws IOException, ArrayIndexOutOfBoundsException Recuerda que la excepcin ArrayIndexOutOfBoundsException es una excepcin en tiempo de ejecucin, por eso no tiene porque especificarse en la sentencia throws pero puede hacerse si se quiere.

Crear nuevas excepciones.


Slo se pueden lanzar objetos que estn derivados de la clase Throwable. Esto incluye descendientes directos (esto es, objetos de la clase Throwable) y descendiente indirectos (objetos derivados de hijos o nietos de la clase Throwable). La clase Throwable tiene dos descendientes directos: Error y Exception. Error Cuando falla un enlace dinmico, y hay algn fallo "hardware" en la mquina virtual, sta lanza un error. Tpicamente los programas Java no capturan los Errores. Pero siempre lanzarn errores. Exception La mayora de los programas lanzan y capturan objetos derivados de la clase Exception. Una Excepcin indica que ha ocurrido un problema pero que el problema no es demasiado serio. La mayora de los programas que escribirs lanzarn y capturarn excepciones. La clase Exception tiene muchos descendiente definidos en los paquetes Java. Estos descendientes indican varios tipos de excepciones que pueden ocurrir. Por ejemplo, IllegalAccessException seala que no se puede encontrar un mtodo particular, y NegativeArraySizeException indica que un programa intenta crear un array con tamao negativo. Una subclase de Exception tiene un significado especial en el lenguaje Java: RuntimeException. RuntimeException La clase RuntimeException representa las excepciones que ocurren dentro de la mquina virtual Java (durante el tiempo de ejecucin). Un ejemplo de estas excepciones es NullPointerException, que ocurre cuando un mtodo intenta acceder a un miembro de un objeto a travs de una referencia nula. Esta excepcin puede ocurrir en cualquier lugar en que un programa intente des referenciar una referencia a un objeto. Frecuentemente el coste de chequear estas excepciones sobrepasa los beneficios de capturarlas.

Como las excepciones en tiempo de ejecucin estn omnipresentes e intentar capturar o especificarlas todas en todo momento podra ser un ejercicio infructuoso (y un cdigo infructuoso, imposible de leer y de mantener), el compilador permite que estas excepciones no se capturen ni se especifiquen. Los paquetes Java definen varias clases RuntimeException. Se pueden capturar estas excepciones al igual que las otras. Sin embargo, no se requiere que un mtodo especifique que lanza excepciones en tiempo de ejecucin. Adems puedes crear sus propias subclases de RuntimeException. Crear Excepciones Propias Cuando disees un paquete de clases java que colabore para proporcionar alguna funcin til a sus usuarios, debers trabajar duro para asegurarte de que las clases interactan correctamente y que sus interfaces son fciles de entender y utilizar. Deberas estar mucho tiempo pensando sobre ello y disear las excepciones que esas clases pueden lanzar. Supn que ests escribiendo una clase con una lista enlazada que ests pensando en distribuir como freeware. Entre otros mtodos la clase debera soportar estos: objectAt(int n) Devuelve el objeto en la posicin n de la lista. firstObject() Devuelve el primer objeto de la lista. indexOf(Object o) Busca el Objeto especificado en la lista y devuelve su posicin en ella. Qu puede ir mal? Como muchos programadores utilizarn tu clase de lista enlazada, puedes estar seguro de que muchos de ellos la utilizarn mal o abusarn de los mtodos de la clase. Tambin, alguna llamada legtima a los mtodos de la clase podra dar algn resultado indefinido. No importa, con respecto a los errores, querr que tu clase sea lo ms robusta posible, para hacer algo razonable con los errores, y comunicar los errores al programa llamador. Sin embargo, no puedes anticipar como quiere cada usuario de tu clase enlazada que se comporten sus objetos ante la adversidad. Por eso, lo mejor que puedes hacer cuando ocurre un error es lanzar una excepcin.

Cada uno de los mtodos soportados por la lista enlazada podra lanzar una excepcin bajo ciertas condiciones, y cada uno podra lanzar un tipo diferente de excepcin. Por ejemplo. objectAt() Lanzar una excepcin si se pasa un entero al mtodo que sea menor que 0 o mayor que el nmero de objetos que hay realmente en la lista. firstObject() Lanzar una excepcin si la lista no contiene objetos. indexOf() Lanzar una excepcin si el objeto pasado al mtodo no est en la lista.

Pero qu tipo de excepcin debera lanzar cada mtodo? Debera ser una excepcin proporcionada por el entorno de desarrollo de Java? O Deberan ser excepciones propias? Elegir el Tipo de Excepcin Lanzada Tratndose de la eleccin del tipo de excepcin a lanzar, tienes dos opciones. Utilizar una escrita por otra persona. Por ejemplo, el entorno de desarrollo de Java proporciona muchas clases de excepciones que podras utilizar. Escribirlas tu mismo. Necesitars escribir tus propias clases de excepciones si respondes "Si" a alguna de las siguientes preguntas. Si no es as, probablemente podrs utilizar alguna excepcin ya escrita. Necesitas un tipo de excepcin que no est representada por lo existentes en el entorno de desarrollo de Java? Ayudara a sus usuarios si pudieran diferenciar sus excepciones de las otras lanzadas por clases escritas por otros vendedores? Lanza el cdigo ms de una excepcin relacionada? Si utilizas excepciones de otros, Podrn sus usuarios tener acceso a estas excepciones? Una pregunta similar es "Debera tu paquete ser independiente y auto-contenedor?" La clase de lista enlazada puede lanzar varias excepciones, y sera conveniente poder capturar todas las excepciones lanzadas por la lista enlaza con un manejador. Si planeas

distribuir la lista enlazada en un paquete, todo el cdigo relacionado debe empaquetarse junto. As para la lista enlazada, deberas crear tu propio rbol de clases de excepciones. El siguiente diagrama ilustra una posibilidad del rbol de clases para su lista enlazada. LinkedListException es la clase padre de todas las posibles excepciones que pueden ser lanzadas por la clase de la lista enlazada, Los usuarios de esta clase pueden escribir un slo manejador de excepciones para manejarlas todas con una sentencia catch como esta.

O, podra escribir manejadores ms especializados para cada una de las subclases de LinkedListException. Elegir una Superclase El diagrama anterior no indica la superclase de la clase LinkedListException. Como ya sabes, las excepciones de Java deben ser ejemplares de la clase Throwable o de sus subclases. Por eso podra tentarte hacer LinkedListException como una subclase de la clase Throwable. Sin embargo, el paquete java.lang proporciona dos clases Throwable que dividen los tipos de problemas que pueden ocurrir en un programa java: Errores y Excepcin. La mayora de los applets y de las aplicaciones que escribes lanzan objetos que son Excepciones. (Los errores estn reservados para problemas ms serios que pueden ocurrir en el sistema.) Tericamente, cualquier subclase de Exception podra ser utilizada como padre de la clase LinkedListException. Sin embargo, un rpido examen de esas clases muestra que o son demasiado especializadas o no estn relacionadas con LinkedListException para ser apropiadas. As que el padre de la clase LinkedListException debera ser Exception.

Como las excepciones en tiempo de ejecucin no tienen por qu ser especificadas en la clusula throws de un mtodo, muchos desarrolladores de paquetes se preguntan. La lnea inferior dice que no deberas utilizar subclases de RuntimeException en tus clases a menos que tus excepciones sean realmente en tiempo de ejecucin! Para la mayora de nosotros, esto significa "NO, tus excepciones no deben descender de la clase RuntimeException." Convenciones de Nombres Es una buena prctica aadir la palabra "Exception" al final del nombre de todas las clases heredadas (directa o indirectamente) de la clase Exception. De forma similar, los nombres de las clases que se hereden desde la clase Error deberan terminar con la palabra "Error".

Lanzar una Excepcin.


Todos los mtodos Java utilizan la sentencia throw para lanzar una excepcin. Esta sentencia requiere un slo argumento, un objeto Throwable. En el sistema Java, los objetos lanzables son ejemplares de la clase Throwable definida en el paquete java.lang. Aqu tienes un ejemplo de la sentencia throw.

Si se intenta lanzar un objeto que no es 'lanzable', el compilador rehsa la compilacin del programa y muestra un mensaje de error similar a ste. testing.java:10: Cannot throw class java.lang.Integer; it must be a subclass of class java.lang.Throwable. throw new Integer(4); Echemos un vistazo a la sentencia throw en su contexto. El siguiente mtodo est tomado de una clase que implementa un objeto pila normal. El mtodo pop() saca el elemento superior de la pila y lo devuelve.

El mtodo pop() comprueba si hay algn elemento en la pila. Si la pila est vaca (su tamao es igual a cero), ejemplariza un nuevo objeto de la clase EmptyStackException y lo lanza. Esta clase est definida en el paquete java.util. En pginas posteriores podrs ver cmo crear tus propias clases de excepciones. Por ahora, todo lo que necesitas recordar es que se pueden lanzar objetos heredados desde la clase Throwable.

La clausula throws
Habrs observado que la declaracin del mtodo pop() contiene esta clausula.

La clusula throws especifica que el mtodo puede lanzar una excepcin EmptyStackException. Como ya sabes, el lenguaje Java requiere que los mtodos capturen o especifiquen todas las excepciones chequeadas que puedan ser lanzadas dentro de su mbito. Se puede hacer esto con la clusula throws de la declaracin del mtodo.

Captulo 3: JDBC
Introduccin.
JDBC es el acrnimo de Java Database Connectivity, un API que permite la ejecucin de operaciones sobre bases de datos desde el lenguaje de programacin Java independientemente del sistema operativo donde se ejecute o de la base de datos a la cual se accede utilizando el dialecto SQL del modelo de base de datos que se utilice. El API JDBC se presenta como una coleccin de interfaces Java y mtodos de gestin de manejadores de conexin hacia cada modelo especfico de base de datos. Un manejador de conexiones hacia un modelo de base de datos en particular es un conjunto de clases que implementan las interfaces Java y que utilizan los mtodos de registro para declarar los tipos de localizadores a base de datos (URL) que pueden manejar. Para utilizar una base de datos particular, el usuario ejecuta su programa junto con la librera de conexin (Driver) apropiada al modelo de su base de datos, y accede a ella estableciendo una conexin, para ello provee en localizador a la base de datos y los parmetros de conexin especficos. A partir de all puede realizar con cualquier tipo de tareas con la base de datos a las que tenga permiso: consulta, actualizacin, creacin, modificacin y borrado de tablas, ejecucin de procedimientos almacenados en la base de datos, etc. A lo largo de la seccin asumiremos que la base de datos COFFEEBREAK ya existe. (Crear una base de datos no es nada difcil, pero requiere permisos especiales y normalmente lo hace un administrador de bases de datos). Cuando creemos las tablas utilizadas como ejemplos en este tutorial, sern la base de datos por defecto. Hemos mantenido un nmero pequeo de tablas para mantener las cosas manejables. Supongamos que nuestra base de datos est siendo utilizada por el propietario de un pequeo caf llamado "The Coffee Break", donde los granos de caf se venden por kilos y el caf lquido se vende por tazas. Para mantener las cosas sencillas, tambin supondremos que el propietario slo necesita dos tablas, una para los tipos de caf y otra para los suministradores. Primero veremos cmo abrir una conexin con nuestro controlador de base de datos, y luego, ya que JDBC puede enviar cdigo SQL a nuestro controlador, demostraremos

algn cdigo SQL. Despus, veremos lo sencillo que es utilizar JDBC para pasar esas sentencias SQL a nuestro controlador de bases de datos y procesar los resultados devueltos.

Driver, cmo obtenerlo.


Un driver JDBC puede pertenecer a una de cuatro categoras diferentes en cuanto a la forma de operar.

Puente JDBC-ODBC
La primera categora de drivers es la utilizada por Sun inicialmente para popularizar JDBC y consiste en aprovechar todo lo existente, estableciendo un puente entre JDBC y ODBC. Este driver convierte todas las llamadas JDBC a llamadas ODBC y realiza la conversin correspondiente de los resultados.

La ventaja de este driver, que se proporciona con el JDK, es que Java dispone de acceso inmediato a todas las fuentes posibles de bases de datos y no hay que hacer ninguna configuracin adicional aparte de la ya existente. No obstante, tiene dos desventajas muy importantes; por un lado, la mayora de los drivers ODBC a su vez convierten sus llamadas a llamadas a una librera nativa del fabricante DBMS, con lo cual la lentitud del driver JDBC-ODBC puede ser exasperante, al llevar dos capas adicionales que no aaden funcionalidad alguna; y por otra parte, el puente JDBC-ODBC requiere una instalacin ODBC ya existente y configurada.

Lo anterior implica que para distribuir con seguridad una aplicacin Java que use JDBC habra que limitarse en primer lugar a entornos Windows (donde est definido ODBC) y en segundo lugar, proporcionar los drivers ODBC adecuados y configurarlos correctamente. Esto hace que este tipo de drivers est totalmente descartado en el caso de aplicaciones comerciales, e incluso en cualquier otro desarrollo, debe ser considerado como una solucin transitoria, porque el desarrollo de drivers totalmente en Java har innecesario el uso de estos puentes.

Java/Binario

Este driver se salta la capa ODBC y habla directamente con la librera nativa del fabricante del sistema DBMS (como pudiera ser DB-Library para Microsoft SQL Server o CT-Lib para Sybase SQL Server). Este driver es un driver 100% Java pero an as necesita la existencia de un cdigo binario (la librera DBMS) en la mquina del cliente, con las limitaciones y problemas que esto implica.

100% Java/Protocolo nativo


Es un driver realizado completamente en Java que se comunica con el servidor DBMS utilizando el protocolo de red nativo del servidor. De esta forma, el driver no necesita intermediarios para hablar con el servidor y convierte todas las peticiones JDBC en peticiones de red contra el servidor. La ventaja de este tipo de driver es que es una solucin 100% Java y, por lo tanto, independiente de la mquina en la que se va a ejecutar el programa.

Igualmente, dependiendo de la forma en que est programado el driver, puede no necesitar ninguna clase de configuracin por parte del usuario. La nica desventaja de este tipo de drivers es que el cliente est ligado a un servidor DBMS concreto, ya que el protocolo de red que utiliza MS SQL Server por ejemplo no tiene nada que ver con el utilizado por DB2, PostGres u Oracle. La mayora de los fabricantes de bases de datos han incorporado a sus propios drivers JDBC del segundo o tercer tipo, con la ventaja de que no suponen un coste adicional.

100% Java/Protocolo independiente

Esta es la opcin ms flexible, se trata de un driver 100% Java / Protocolo independiente, que requiere la presencia de un intermediario en el servidor. En este caso, el driver JDBC hace las peticiones de datos al intermediario en un protocolo de red independiente del servidor DBMS. El intermediario a su vez, que est ubicado en el lado del servidor, convierte las peticiones JDBC en peticiones nativas del sistema DBMS. La ventaja de este mtodo es inmediata: el programa que se ejecuta en el cliente, y aparte de las ventajas de los drivers 100% Java, tambin presenta la independencia respecto al sistema de bases de datos que se encuentra en el servidor. De esta forma, si una empresa distribuye una aplicacin Java para que sus usuarios puedan acceder a su servidor MS SQL y posteriormente decide cambiar el servidor por Oracle, PostGres o DB2, no necesita volver a distribuir la aplicacin, sino que nicamente debe reconfigurar la aplicacin residente en el servidor que se encarga de transformar las peticiones de red en peticiones nativas. La nica desventaja de este tipo de drivers es que la aplicacin intermediaria es una aplicacin independiente que suele tener un coste adicional por servidor fsico, que hay que aadir al coste del servidor de bases de datos. En el Tutorial todos los ejemplos estarn referidos al puente JDBC-ODBC y a la conectividad JDBC con servidores SQL comerciales Si el lector quiere seguir experimentando sin necesidad de adquirir paquetes comerciales, en el caso de Windows puede utilizar el conocido mSQL (mini SQL), un servidor SQL escrito por David J. Hughes y que es de distribucin shareware, siendo gratuita para fines no comerciales y de investigacin; y en el caso de Linux, aunque tambin se puede utilizar mSQL, el autor recomienda PostGres, que es un sistema de base de datos relacional que une las estructuras clsicas con los conceptos de programacin orientada a objetos. Lgicamente, el lector no debe esperar de mSQL una potencia, rendimiento o compatibilidad con ANSI SQL como la que tienen los servidores SQL comerciales, aunque en el caso de PostGres la funcionalidad es al menos igual a otras bases de datos profesionales existentes en el mercado; y aunque, como casi todos los productos Linux, carece de un interfaz cmodo, s permite realizar las tareas de administracin y explotacin con bastante comodidad.

Cmo obtenerlo
Existen drivers JDBC para casi todos los sistemas de base de datos, en general cada vendedor de sistemas de bases de datos ofrece un driver para JDBC o de lo contrario patrocina algn driver GNU. Para obtener algn driver especfico se debe tener en cuenta la versin del JDK que utilicemos, la versin del motor de BD, generalmente existen varias opciones. Consulta directamente en la pgina oficial del vendedor del motor de BD que tu utilices sobre la mejor alternativa.

Instanciar el driver.
Cargar el driver o drivers que queremos utilizar es muy sencillo y slo implica una lnea de cdigo. Si, por ejemplo, queremos utilizar el puente JDBC-ODBC, se cargara la siguiente lnea de cdigo.

La documentacin del driver nos dar el nombre de la clase a utilizar. Por ejemplo, si el nombre de la clase es jdbc.DriverXYZ, cargaramos el driver con esta lnea de cdigo.

No necesitamos crear un ejemplar de un driver y registrarlo con el DriverManager porque la llamada a Class.forName lo hace automticamente. Si hubiramos creado nuestro propio ejemplar, crearamos un duplicado innecesario, pero no pasara nada. Una vez cargado el driver, es posible hacer una conexin con un controlador de base de datos.

Establecer una conexin: cadena de conexin (URL), clases DriverManager y Connection.


El segundo paso para establecer una conexin es tener el driver apropiado conectado al controlador de base de datos. La siguiente lnea de cdigo ilustra la idea general.

Este paso tambin es sencillo, lo ms duro es saber qu suministrar para url. Si estamos utilizando el puente JDBC-ODBC, el JDBC URL empezar con jdbc:odbc:. el resto de la URL normalmente es la fuente de nuestros datos o el sistema de base de datos. Por eso, si estamos utilizando ODBC para acceder a una fuente de datos ODBC llamada "Fred," por ejemplo, nuestro URL podra ser jdbc:odbc:Fred. En lugar de "myLogin" pondramos el nombre utilizado para entrar en el controlador de la base de datos; en lugar de "myPassword" pondramos nuestra password para el controlador de la base de datos. Por eso si entramos en el controlador con el nombre "miUsuario" y la password "****," estas dos lneas de cdigo establecern una conexin.

Si estamos utilizando un puente JDBC desarrollado por una tercera parte, la documentacin nos dir el subprotocolo a utilizar, es decir, qu poner despues de jdbc: en la URL. Por ejemplo, si el desarrollador ha registrado el nombre "acme" como el subprotocolo, la primera y segunda parte de la URL de JDBC sern jdbc:acme:. La documentacin del driver tambin nos dar las guas para el resto de la URL del JDBC. Esta ltima parte de la URL suministra informacin para la identificacin de los datos fuente. Si uno de los drivers que hemos cargado reconoce la URL suministada por el mtodo DriverManager.getConnection, dicho driver establecer una conexin con el controlador de base de datos especificado en la URL del JDBC. La clase DriverManager, como su nombre indica, maneja todos los detalles del establecimiento de la conexin detrs de la escena. A menos que estemos escribiendo un driver, posiblemente nunca utilizaremos

ningn mtodo del interface Driver, y el nico mtodo de DriverManager que realmente necesitaremos conocer es DriverManager.getConnection. La conexin devuelta por el mtodo DriverManager.getConnection es una conexin abierta que se puede utilizar para crear sentencias JDBC que pasen nuestras sentencias SQL al controlador de la base de datos. En el ejemplo anterior, con es una conexin abierta, y se utilizar en los ejemplos posteriores.

Sentencias SQL.
Statement.
Un objeto Statement es el que enva nuestras sentencias SQL al controlador de la base de datos. Simplemente creamos un objeto Statement y lo ejecutamos, suministrando el mtodo SQL apropiado con la sentencia SQL que queremos enviar. Para una sentencia SELECT, el mtodo a ejecutar es executeQuery. Para sentencias que crean o modifican tablas, el mtodo a utilizar es executeUpdate. Se toma un ejemplar de una conexin activa para crear un objeto Statement. En el siguiente ejemplo, utilizamos nuestro objeto Connection: con para crear el objeto Statement: stmt.

En este momento stmt existe, pero no tiene ninguna sentencia SQL que pasarle al controlador de la base de datos. Necesitamos suministrarle el mtodo que utilizaremos para ejecutar stmt. Por ejemplo, en el siguiente fragmento de cdigo, suministramos executeUpdate con la sentencia SQL que crea la tabla COFFEES.

Podramos haber escrito el cdigo de esta forma alternativa.

Utilizamos el mtodo executeUpdate porque la sentencia SQL contenida en createTableCoffees es una sentencia DDL (data definition language). Las sentencias que crean, modifican o eliminan tablas son todos ejemplos de sentencias DDL y se ejecutan con el mtodo executeUpdate.

Cmo se podra esperar de su nombre, el mtodo executeUpdate tambin se utiliza para ejecutar sentencias SQL que actualizan una tabla. En la prctica executeUpdate se utiliza ms frecuentemente para actualizar tablas que para crearlas porque una tabla se crea slo una vez, pero se puede actualizar muchas veces. El mtodo ms utilizado para ejecutar sentencias SQL es executeQuery. Este mtodo se utiliza para ejecutar sentencias SELECT, que comprenden la amplia mayora de las sentencias SQL. Hemos visto como crear la tabla COFFEES especificando los nombres de columnas y los tipos de datos almacenados en esas columnas, pero esto slo configura la estructura de la tabla. La tabla no contiene datos todava. Introduciremos datos en nuestra tabla una fila cada vez, suministrando la informacin a almacenar en cada columna de la fila. Observa que los valores insertados en las columnas se listan en el mismo orden en que se declararon las columnas cuando se cre la tabla, que es el orden por defecto. El siguiente cdigo inserta una fila de datos con Colombian en la columna COF_NAME, 101 en SUP_ID, 7.99 en PRICE, 0 en SALES, y 0 en TOTAL. (Como acabamos de inaugurar "The Coffee Break", la cantidad vendida durante la semana y la cantidad total son cero para todos los cafs). Al igual que hicimos con el cdigo que creaba la tabla COFFEES, crearemos un objeto Statement y lo ejecutaremos utilizando el mtodo executeUpdate. Como la sentencia SQL es demasiado larga como para entrar en una sla lnea, la hemos dividido en dos strings concatenndolas mediante un signo ms (+) para que puedan compilarse. Presta especial atencin a la necesidad de un espacio entre COFFEES y VALUES. Este espacio debe estar dentro de las comillas y debe estar despus de COFFEES y antes de VALUES; sin un espacio, la sentencia SQL sera leda errneamente como "INSERT INTO COFFEESVALUES" y el controlador de la base de datos buscara la tablaCOFFEESVALUES.

Observa tambin que utilizamos comillas simples alrededor del nombre del caf porque est anidado dentro de las comillas dobles. Para la mayora de controladores de bases de datos, la regla general es alternar comillas dobles y simples para indicar anidacin.

El siguiente cdigo inserta una segunda lnea dentro de la tabla COFFEES. Observa que hemos reutilizado el objeto Statement: stmt en vez de tener que crear uno nuevo para cada ejecucin.

Los valores de las siguientes filas se pueden insertar de esta forma.

JDBC devuelve los resultados en un objeto ResultSet, por eso necesitamos declarar un ejemplar de la clase ResultSet para contener los resultados. El siguiente cdigo presenta el objeto ResultSet: rs y le asigna el resultado de una consulta anterior.

PreparedStatement.
Algunas veces es ms conveniente o eficiente utilizar objetos PreparedStatement para enviar sentencias SQL a la base de datos. Este tipo especial de sentencias se deriva de una clase ms general, Statement, que ya conocemos.

Cundo utilizar un Objeto PreparedStatement?


Si queremos ejecutar muchas veces un objeto Statement, reduciremos el tiempo de ejecucin si utilizamos un objeto PreparedStatement, en su lugar. La caracterstica principal de un objeto PreparedStatement es que, al contrario que un objeto Statement, se le entrega una sentencia SQL cuando se crea. La ventaja de esto es que en la mayora de los casos, esta sentencia SQL se enviar al controlador de la base de datos inmediatamente, donde ser compilado. Como resultado, el objeto PreparedStatement no slo contiene una sentencia SQL, sino una sentencia SQL que ha sido pre compilada. Esto significa que cuando se ejecuta la PreparedStatement, el controlador de base de datos puede ejecutarla sin tener que compilarla primero. Aunque los objetos PreparedStatement se pueden utilizar con sentencias SQL sin parmetros, probablemente nosotros utilizaremos ms frecuentemente sentencias con parmetros. La ventaja de utilizar sentencias SQL que utilizan parmetros es que podemos utilizar la misma sentencia y suministrar distintos valores cada vez que la ejecutemos.

Crear un Objeto PreparedStatement


Al igual que los objetos Statement, creamos un objeto PreparedStatement con un objeto Connection. Utilizando nuestra conexin con abierta en ejemplos anteriores, podramos escribir lo siguiente para crear un objeto PreparedStatement que tome dos parmetros de entrada.

La variable updateSales contiene la sentencia SQL, "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?", que tambin ha sido, en la mayora de los casos, enviada al controlador de la base de datos, y ha sido pre compilado.

Suministrar Valores para los Parmetros de un PreparedStatement


Necesitamos suministrar los valores que se utilizarn en los lugares donde estn las marcas de interrogacin, si hay alguno, antes de ejecutar un objeto PreparedStatement. Podemos hacer esto llamado a uno de los mtodos setXXX definidos en la clase PreparedStatement. Si el valor que queremos sustituir por una marca de interrogacin es un int de Java, podemos llamar al mtodo setInt. Si el valor que queremos sustituir es un String de Java, podemos llamar al mtodo setString, etc. En general, hay un mtodo setXXX para cada tipo Java. Utilizando el objeto updateSales del ejemplo anterior, la siguiente lnea de cdigo selecciona la primera marca de interrogacin para un int de Java, con un valor de 75.

Cmo podramos asumir a partir de este ejemplo, el primer argumento de un mtodo setXXX indica la marca de interrogacin que queremos seleccionar, y el segundo argumento el valor que queremos ponerle. El siguiente ejemplo selecciona la segunda marca de interrogacin con el string "Colombian".

Despus de que estos valores hayan sido asignados para sus dos parmetros, la sentencia SQL de updateSales ser equivalente a la sentencia SQL que hay en string updateString que utilizando en el ejemplo anterior. Por lo tanto, los dos fragmentos de cdigo siguientes consiguen la misma cosa. Cdigo 1.

Cdigo 2.

Utilizamos el mtodo executeUpdate para ejecutar ambas sentencias stmt updateSales. Observa, sin embargo, que no se suministran argumentos a executeUpdate cuando se utiliza para ejecutar updateSales. Esto es cierto porque updateSales ya contiene la sentencia SQL a ejecutar. Mirando esto ejemplos podramos preguntarnos por qu utilizar un objeto PreparedStatement con parmetros en vez de una simple sentencia, ya que la sentencia simple implica menos pasos. Si actualizramos la columna SALES slo una o dos veces, no sera necesario utilizar una sentencia SQL con parmetros. Si por otro lado, tuviramos que actualizarla frecuentemente, podra ser ms fcil utilizar un objeto PreparedStatement, especialmente en situaciones cuando la utilizamos con un bucle while para seleccionar un parmetro a una sucesin de valores. Veremos este ejemplo ms adelante en esta seccin. Una vez que a un parmetro se ha asignado un valor, el valor permanece hasta que lo resetee otro valor o se llame al mtodo clearParameters.

Utilizando el objeto PreparedStatement: updateSales, el siguiente fragmento de cdigo reutiliza una sentencia prepared despus de resetar el valor de uno de sus parmetros, dejando el otro igual.

Utilizar una Bucle para asignar Valores


Normalmente se codifica ms sencillo utilizando un bucle for o while para asignar valores de los parmetros de entrada. El siguiente fragmento de cdigo demuestra la utilizacin de un bucle for para asignar los parmetros en un objeto PreparedStatement: updateSales. El array salesForWeek contiene las cantidades vendidas semanalmente. Estas cantidades corresponden con los nombres de los cafs listados en el array coffees, por eso la primera cantidad de salesForWeek (175) se aplica al primer nombre de caf de coffees ("Colombian"), la segunda cantidad de salesForWeek (150) se aplica al segundo nombre de caf en coffees ("French_Roast"), etc.

Este fragmento de cdigo demuestra la actualizacin de la columna SALES para todos los cafs de la tabla COFFEES

Cuando el propietario quiera actualizar las ventas de la semana siguiente, puede utilizar el mismo cdigo como una plantilla. Todo lo que tiene que haces es introducir las nuevas cantidades en el orden apropiado en el array salesForWeek. Los nombres de cafs del array coffees permanecen constantes, por eso no necesitan cambiarse. (En una aplicacin real, los valores probablemente seran introducidos por el usuario en vez de desde un array inicializado).

CallableStatement.
Procedimientos Almacenados
Un procedimiento almacenado es un grupo de sentencias SQL que forman una unidad lgica y que realizan una tarea particular. Los procedimientos almacenados se utilizan para encapsular un conjunto de operaciones o peticiones para ejecutar en un servidor de base de datos. Por ejemplo, las operaciones sobre una base de datos de empleados (salarios, despidos, promociones, bloqueos) podran ser codificados como procedimientos almacenados ejecutados por el cdigo de la aplicacin. Los procedimientos almacenados pueden compilarse y ejecutarse con diferentes parmetros y resultados, y podran tener cualquier combinacin de parmetros de entrada/salida. Los procedimientos almacenados estn soportados por la mayora de los controladores de bases de datos, pero existe una gran cantidad de variaciones en su sintaxis y capacidades. Por esta razn, slo mostraremos un ejemplo sencillo de lo que podra ser un procedimiento almacenado y cmo llamarlos desde JDBC, pero este ejemplo no est diseado para ejecutarse. Esta pgina muestra un procedimiento almacenado muy sencillo que no tiene parmetros. Aunque la mayora de los procedimientos almacenados hacen cosas ms complejas que este ejemplo, sirve para ilustrar algunos puntos bsicos sobre ellos. Como paso prvio, la sintaxis para definir un procedimiento almacenado es diferente de un controlador de base de datos a otro. Por ejemplo, algunos utilizan begin . . . end u otras palabras clave para indicar el principio y final de la definicin de procedimiento. En algunos controladores, la siguiente sentencia SQL crea un procedimiento almacenado.

El siguiente cdigo pone la sentencia SQL dentro de un string y lo asigna a la variable createProcedure, que utilizaremos ms adelante.

El siguiente fragmento de cdigo utiliza el objeto Connection, con para crear un objeto Statement, que es utilizado para enviar la sentencia SQL que crea el procedimiento almacenado en la base de datos.

El procedimiento SHOW_SUPPLIERS ser compilado y almacenado en la base de datos como un objeto de la propia base y puede ser llamado, como se llamara a cualquier otro mtodo.

Llamar a un Procedimiento Almacenado desde JDBC


JDBC permite llamar a un procedimiento almacenado en la base de datos desde una aplicacin escrita en Java. El primer paso es crear un objeto CallableStatement. Al igual que con los objetos Statement y PreparedStatement, esto se hace con una conexin abierta, Connection. Un objeto CallableStatement contiene una llamada a un procedimiento almacenado; no contiene el propio procedimiento. La primera lnea del cdigo siguiente crea una llamada al procedimiento almacenado SHOW_SUPPLIERS utilizando la conexin con. La parte que est encerrada entre corchetes es la sintaxis de escape para los precedimientos almacenados. Cuando un controlador encuentra "{call SHOW_SUPPLIERS}", traducir esta sintaxis de escape al SQL nativo utilizado en la base de datos para llamar al procedimiento almacenado llamado SHOW_SUPPLIERS.

La hoja de resultados de rs ser similar a esto:

Observa que el mtodo utilizado para ejecutar cs es executeQuery porque cs llama a un procedimiento almacenado que contiene una peticin y esto produce una hoja de resultados. Si el procedimiento hubiera contenido una sentencia de actualizacin o una sentencia DDL, se hubiera utilizado el mtodo executeUpdate. Sin embargo, en algunos casos, cuando el procedimiento almacenado contiene ms de una sentencia SQL producir ms de una hoja de resultados, o cuando contiene ms de una cuenta de actualizacin o alguna combinacin de hojas de resultados y actualizaciones. En estos casos, donde existen mltiples resultados, se debera utilizar el mtodo execute para ejecutar CallableStatement. La clase CallableStatement es una subclase de PreparedStatement, por eso un objeto CallableStatement puede tomar parmetros de entrada como lo hara un objeto PreparedStatement. Adems, un objeto CallableStatement puede tomar parmetros de salida, o parmetros que son tanto de entrada como de salida. Los parmetros INOUT y el mtodo execute se utilizan raramente.

Manejo de Resultados
Valores de retorno del mtodo executeUpdate
Siempre que executeQuery devuelve un objeto ResultSet que contiene los resultados de una peticin al controlador de la base datos, el valor devuelto por executeUpdate es un int que indica cuntas lneas de la tabla fueron actualizadas. Por ejemplo, el siguiente cdigo muestra el valor de retorno de executeUpdate asignado a la variable n.

n = 1 porque ha cambiado 1 fila La tabla COFFEES se ha actualziado poniendo el valor 50 en la columna SALES de la fila correspondiente a Espresso. La actualizacin afecta slo a una lnea de la tabla, por eso n es igual a 1. Cuando el mtodo executeUpdate es utilizado para ejecutar una sentencia DDL, como la creacin de una tabla, devuelve el int: 0. Consecuentemente, en el siguiente fragmento de cdigo, que ejecuta la sentencia DDL utilizada para crear la tabla COFFEES, n tendr el valor 0.

Observa que cuando el valor devuelto por executeUpdate sea 0, puede significar dos cosas: La sentencia ejecutada no ha actualizado ninguna fila. La sentencia ejecutada fue una sentencia DDL.

JDBC devuelve los resultados en un objeto ResultSet, por eso necesitamos declarar un ejemplar de la clase ResultSet para contener los resultados. El siguiente cdigo presenta el objeto ResultSet: rs y le asigna el resultado de una consulta anterior.

Utilizar el Mtodo next


La variable rs, que es un ejemplar de ResultSet, contiene las filas de cafs y sus precios mostrados en el juego de resultados de la pgina anterior. Para acceder a los nombres y los precios, iremos a la fila y recuperaremos los valores de acuerdo con sus tipos. El mtodo next mueve algo llamado cursor a la siguiente fila y hace que esa fila (llamada fila actual) sea con la que podamos operar. Como el cursor inicialmente se posiciona justo encima de la primera fila de un objeto ResultSet, primero debemos llamar al mtodo next para mover el cursor a la primera fila y convertirla en la fila actual. Sucesivas invocaciones del mtodo next movern el cursor de lnea en lnea de arriba a abajo. Observa que con el JDBC 2.0, cubierto en la siguiente seccin, se puede mover el cursor hacia atrs, hacia posiciones especficas y a posiciones relativas a la fila actual adems de mover el cursor hacia adelante.

Utilizar los mtodos getXXX


Los mtodos getXXX del tipo apropiado se utilizan para recuperar el valor de cada columna. Por ejemplo, la primera columna de cada fila de rs es COF_NAME, que almacena un valor del tipo VARCHAR de SQL. El mtodo para recuperar un valor VARCHAR es getString. La segunda columna de cada fila almacena un valor del tipo FLOAT de SQL, y el mtodo para recuperar valores de ese tipo es getFloat. El siguiente cdigo accede a los valores almacenados en la fila actual de rs e imprime una lnea con el nombre seguido por tres espacios y el precio. Cada vez que se llama al mtodo next, la siguiente fila se convierte en la actual, y el bucle contina hasta que no haya ms filas en rs.

Veamos cmo funcionan los mtodos getXXX examinando las dos sentencias getXXX de este cdigo. Primero examinaremos getString.

El mtodo getString es invocado sobre el objeto ResultSet: rs, por eso getString recuperar (obtendr) el valor almacenado en la columna COF_NAME de la fila actual de rs. El valor recuperado por getString se ha convertido desde un VARCHAR de SQL a un String de Java y se ha asignado al objeto String s. Observa que utilizamos la variable s en la expresin println mostrada arriba, de esta forma: println(s + " " + n) La situacin es similar con el mtodo getFloat excepto en que recupera el valor almacenado en la columna PRICE, que es un FLOAT de SQL, y lo convierte a un float de Java antes de asignarlo a la variable n. JDBC ofrece dos formas para identificar la columna de la que un mtodo getXXX obtiene un valor. Una forma es dar el nombre de la columna, como se ha hecho arriba. La segunda forma es dar el ndice de la columna (el nmero de columna), con un 1 significando la primera columna, un 2 para la segunda, etc. Si utilizramos el nmero de columna en vez del nombre de columna el cdigo anterior se podra parecer a esto.

La primera lnea de cdigo obtiene el valor de la primera columna de la fila actual de rs (columna COF_NAME), convirtindolo a un objeto String de Java y asignndolas.

La segunda lnea de cdigo obtiene el valor de la segunda columna de la fila actual de rs, lo convierte a un float de Java y lo asigna a n. Recuerda que el nmero de columna se refiere al nmero de columna en la hoja de resultados no en la tabla original. En suma, JDBC permite utilizar tanto el nombre cmo el nmero de la columna como argumento a un mtodo getXXX. Utilizar el nmero de columna es un poco ms eficiente, y hay algunos casos donde es necesario utilizarlo. JDBC permite muchas lateralidades para utilizar los mtodos getXXX para obtener diferentes tipos de datos SQL. Por ejemplo, el mtodo getInt puede ser utilizado para recuperar cualquier tipo numrico de caracteres. Los datos recuperados sern convertidos a un int; esto es, si el tipo SQL es VARCHAR, JDBC intentar convertirlo en un entero. Se recomienda utilizar el mtodo getInt slo para recuperar INTEGER de SQL, sin embargo, no puede utilizarse con los tipos BINARY, VARBINARY, LONGVARBINARY, DATE, TIME, o TIMESTAMP de SQL. La tabla de ms adelante muestra qu mtodos pueden utilizarse legalmente para recuperar tipos SQL, y ms importante, qu mtodos estn recomendados para recuperar los distintos tipos SQL. Observa que esta tabla utiliza el trmino "JDBC type" en lugar de "SQL type." Ambos trminos se refieren a los tipos genricos de SQL definidos en java.sql.Types, y ambos son intercambiables.

Utilizar el mtodo getString


Aunque el mtodo getString est recomendado para recuperar tipos CHAR y VARCHAR de SQL, es posible recuperar cualquier tipo bsico SQL con l. (Sin embargo, no se pueden recuperar los nuevos tipos de datos del SQL3. Obtener un valor con getString puede ser muy til, pero tiene sus limitaciones. Por ejemplo, si se est utilizando para recuperar un tipo numrico, getString lo convertir en un String de Java, y el valor tendr que ser convertido de nuevo a nmero antes de poder operar con l.

Utilizar los mtodos de ResultSet.getXXX para Recuperar tipos JDBC


TINYINT getByte getShort getInt getLong getFloat getDouble getBigDecimal getBoolean getString getBytes getDate getTime getTimestamp getAsciiStream getUnicodeStream getBinaryStream getObject x x x x x x x x x x x x x x x x X x x x x x x x x SMALLIN T x X x x x x x x x INTEGE R x x X x x x x x x BIGIN T x x x X x x x x x REAL x x x x X x x x x FLOAT x x x x x X x x x DOUBL E X X x x x X x x x DECIMA L x x x x x x X x x NUMERI C x x x x x x X x x BIT x x x x x x x X x CHAR x x x x x x x x X

LONGVARCHAR

BINARY

VARBINARY

LONGVARBINARY

DATE

TIME

TIMESTAMP

VARCHAR

getByte getShort getInt getLong getFloat getDouble getBigDecimal getBoolean getString getBytes getDate getTime getTimestamp getAsciiStream getUnicodeStream getBinaryStream getObject

x x x x x x x x X

x x x x x x x x x x X x X x x X X x x x x x x x x x x X x x x x x x x X x x x

x x x x x

x x x X X

Una "x" indica que el mtodo getXXX se puede utilizar legalmente para recuperar el tipo JDBC dado. Una "X" indica que el mtodo getXXX est recomendado para recuperar el tipo JDBC dado.

Captulo 4: Threads.
Definiciones bsicas.
La Mquina Virtual Java (JVM) es un sistema multi-thread. Es decir, es capaz de ejecutar varias secuencias de ejecucin (programas) simultneamente. La JVM gestiona todos los detalles, asignacin de tiempos de ejecucin, prioridades, etc, de forma similar a como gestiona un Sistema Operativo mltiples procesos. La diferencia bsica entre un proceso de Sistema Operativo y un Thread Java es que los Threads corren dentro de la JVM, que es un proceso del Sistema Operativo y por tanto comparten todos los recursos, incluida la memoria y las variables y objetos all definidos. A este tipo de procesos donde se comparte los recursos se les llama a veces 'procesos ligeros' (lightweight process). Java da soporte al concepto de Thread desde el mismo lenguaje, con algunas clases e interfaces definidas en el package java.lang y con mtodos especficos para la manipulacin de Threads en la clase Object. Desde el punto de vista de las aplicaciones los threads son tiles porque permiten que el flujo del programa sea divido en dos o ms partes, cada una ocupndose de alguna tarea. Por ejemplo un Thread puede encargarse de la comunicacin con el usuario, mientras otros actuan en segundo plano, realizando la transmisin de un fichero, accediendo a recursos del sistema (cargar sonidos, leer ficheros...), etc. De hecho todos los programas con interface grfico (AWT o Swing) son multithread porque los eventos y las rutinas de dibujado de las ventanas corren en un thread distinto al principal.

Clase Thread
La forma ms directa para hacer un programa multi-thread es extender la clase Thread, y redefinir el mtodo run(). Este mtodo es invocado cuando se inicia el thread (mediante una llamada al mtodo start() de la clase thread). El thread se inicia con la llamada al mtodo run y termina cuando termina ste.

El ejemplo ilustra estas ideas:

Interfaz Runneable
En el caso anterior, solamente se puede extender o derivar una vez de la clase padre. Esta limitacin de Java puede ser superada a travs de la implementacin de Runnable:

En este caso necesitamos crear una instancia de Thread antes de que el sistema pueda ejecutar el proceso como un thread. Adems, el mtodo abstracto run() est definido en la interface Runnable tiene que ser implementado. La nica diferencia entre los dos mtodos es que este ltimo es mucho ms flexible. En el ejemplo anterior, todava tenemos oportunidad de extender la clase MiThread, si fuese necesario. La mayora de las clases creadas que necesiten ejecutarse como un thread, implementarn la interface Runnable, ya que probablemente extendern alguna de su funcionalidad a otras clases. No pensar que la interface Runnable est haciendo alguna cosa cuando la tarea se est ejecutando. Solamente contiene mtodos abstractos, con lo cual es una clase para dar idea sobre el diseo de la clase Thread. De hecho, si vemos los fuentes de Java, podremos comprobar que solamente contiene un mtodo abstracto:

Y esto es todo lo que hay sobre la interface Runnable. Como se ve, una interface slo proporciona un diseo para las clases que vayan a ser implementadas. En el caso de Runnable, fuerza a la definicin del mtodo run(), por lo tanto, la mayor parte del trabajo se hace en la clase Thread.

Un vistazo un poco ms profundo a la definicin de la clase Thread nos da idea de lo que realmente est pasando:

De este trocito de cdigo se desprende que la clase Thread tambin implemente la interface Runnable. tarea.run() se asegura de que la clase con que trabaja (la clase que va a ejecutarse como un thread) no sea nula y ejecuta el mtodo run() de esa clase. Cuando esto suceda, el mtodo run() de la clase har que corra como un thread.

Arranque de un Thread
Las aplicaciones ejecutan main() tras arrancar. Esta es la razn de que main() sea el lugar natural para crear y arrancar otros threads. La lnea de cdigo:

El ejemplo crea un nuevo thread. Los dos argumentos pasados representan el nombre del thread y el tiempo que queremos que espere antes de imprimir el mensaje. Al tener control directo sobre los threads, tenemos que arrancarlos explcitamente. En nuestro ejemplo con:

start(), en realidad es un mtodo oculto en el thread que llama al mtodo run().

Manipulacin de un Thread
Si todo fue bien en la creacin del thread, t1 debera contener un thread vlido, que controlaremos en el mtodo run(). Una vez dentro de run(), podemos comenzar las sentencias de ejecucin como en otros programas. run() sirve como rutina main() para los threads; cuando run() termina, tambin lo hace el thread. Todo lo que queramos que haga el thread ha de estar dentro de run(), por eso cuando decimos que un mtodo es Runnable, nos obliga a escribir un mtodo run(). En este ejemplo, intentamos inmediatamente esperar durante una cantidad de tiempo aleatoria:

El mtodo sleep() simplemente le dice al thread que duerma durante los milisegundos especificados. Se debera utilizar sleep() cuando se pretenda retrasar la ejecucin del thread. sleep() no consume recursos del sistema mientras el thread duerme. De esta forma otros threads pueden seguir funcionando. Una vez hecho el retardo, se imprime el mensaje "Hola Mundo!" con el nombre del thread y el retardo.

Suspensin de un Thread
Puede resultar til suspender la ejecucin de un thread sin marcar un lmite de tiempo. Si, por ejemplo, est construyendo un applet con un thread de animacin, querr permitir al usuario la opcin de detener la animacin hasta que quiera continuar. No se trata de terminar la animacin, sino desactivarla. Para este tipo de control de thread se puede utilizar el mtodo suspend().

Este mtodo no detiene la ejecucin permanentemente. El thread es suspendido indefinidamente y para volver a activarlo de nuevo necesitamos realizar una invocacin al mtodo resume():

Detencin de un Thread
El ltimo elemento de control que se necesita sobre threads es el mtodo stop(). Se utiliza para terminar la ejecucin de un thread:

Esta llamada no destruye el thread, sino que detiene su ejecucin. La ejecucin no se puede reanudar ya con t1.start(). Cuando se desasignen las variables que se usan en el thread, el objeto thread (creado con new) quedar marcado para eliminarlo y el garbage collector se encargar de liberar la memoria que utilizaba. En nuestro ejemplo, no necesitamos detener explcitamente el thread. Simplemente se le deja terminar. Los programas ms complejos necesitarn un control sobre cada uno de los threads que lancen, el mtodo stop() puede utilizarse en esas situaciones. Si se necesita, se puede comprobar si un thread est vivo o no; considerando vivo un thread que ha comenzado y no ha sido detenido.

Este mtodo devolver true en caso de que el thread t1 est vivo, es decir, ya se haya llamado a su mtodo run() y no haya sido parado con un stop() ni haya terminado el mtodo run() en su ejecucin.

Estado de un Thread
Durante el ciclo de vida de un thread, ste se puede encontrar en diferentes estados. La figura siguiente muestra estos estados y los mtodos que provocan el paso de un estado a otro. Este diagrama no es una mquina de estados finita, pero es lo que ms se aproxima al funcionamiento real de un thread.

Nuevo Thread
La siguiente sentencia crea un nuevo thread pero no lo arranca, lo deja en el estado de "Nuevo Thread":

Cuando un thread est en este estado, es simplemente un objeto Thread vaco. El sistema no ha destinado ningn recurso para l. Desde este estado solamente puede arrancarse llamando al mtodo start(), o detenerse definitivamente, llamando al mtodo stop(); la llamada a cualquier otro mtodo carece de sentido y lo nico que provocar ser la generacin de una excepcin de tipo IllegalThreadStateException.

Ejecutable
Ahora veamos las dos lneas de cdigo que se presentan a continuacin:

La llamada al mtodo start() crear los recursos del sistema necesarios para que el thread puede ejecutarse, lo incorpora a la lista de procesos disponibles para ejecucin del sistema y llama al mtodo run() del thread. En este momento nos encontramos en el estado "Ejecutable" del diagrama. Y este estado es Ejecutable y no En Ejecucin, porque cuando el thread est aqu no est corriendo. Muchos ordenadores tienen solamente un procesador lo que hace imposible que todos los threads estn corriendo al mismo tiempo. Java implementa un tipo de scheduling o lista de procesos, que permite que el procesador sea compartido entre todos los procesos o threads que se encuentran en la lista. Sin embargo, para nuestros propsitos, y en la mayora de los casos, se puede considerar que este estado es realmente un estado "En Ejecucin", porque la impresin que produce ante nosotros es que todos los procesos se ejecutan al mismo tiempo. Cuando el thread se encuentra en este estado, todas las instrucciones de cdigo que se encuentren dentro del bloque declarado para el mtodo run(), se ejecutarn secuencialmente.

Detenido
El thread entra en estado "Parado" cuando alguien llama al mtodo suspend(), cuando se llama al mtodo sleep(), cuando el thread est bloqueado en un proceso de entrada/salida o cuando el thread utiliza su mtodo wait() para esperar a que se cumpla una determinada condicin. Cuando ocurra cualquiera de las cuatro cosas anteriores, el thread estar Parado. Por ejemplo, en el trozo de cdigo siguiente:

la lnea de cdigo que llama al mtodo sleep():

Hace que el thread se duerma durante 10 segundos. Durante ese tiempo, incluso aunque el procesador estuviese totalmente libre, MiThread no correra. Despus de esos 10 segundos. MiThread volvera a estar en estado "Ejecutable" y ahora s que el procesador podra hacerle caso cuando se encuentre disponible. Para cada una de los cuatro modos de entrada en estado Parado, hay una forma especfica de volver a estado Ejecutable. Cada forma de recuperar ese estado es exclusiva; por ejemplo, si el thread ha sido puesto a dormir, una vez transcurridos los milisegundos que se especifiquen, l solo se despierta y vuelve a estar en estado Ejecutable. Llamar al mtodo resume() mientras est el thread durmiendo no servira para nada. Los mtodos de recuperacin del estado Ejecutable, en funcin de la forma de llegar al estado Parado del thread, son los siguientes: Si un thread est dormido, pasado el lapso de tiempo Si un thread est suspendido, luego de una llamada al mtodo resume() Si un thread est bloqueado en una entrada/salida, una vez que el comando E/S concluya su ejecucin Si un thread est esperando por una condicin, cada vez que la variable que controla esa condicin vare debe llamarse a notify() o notifyAll()

Muerto
Un thread se puede morir de dos formas: por causas naturales o porque lo maten (con stop()). Un thread muere normalmente cuando concluye de forma habitual su mtodo run().

Por ejemplo, en el siguiente trozo de cdigo, el bucle while es un bucle finito -realiza la iteracin 20 veces y termina:

Un thread que contenga a este mtodo run(), morir naturalmente despus de que se complete el bucle y run() concluya. Tambin se puede matar en cualquier momento un thread, invocando a su mtodo stop(). En el trozo de cdigo siguiente:

Se crea y arranca el thread MiThread, lo dormimos durante 10 segundos y en el momento de despertarse, la llamada a su mtodo stop(), lo mata. El mtodo stop() enva un objeto ThreadDeath al thread que quiere detener. As, cuando un thread es parado de este modo, muere asncronamente. El thread morir en el momento en que reciba la excepcin ThreadDeath. Los applets utilizarn el mtodo stop() para matar a todos sus threads cuando el navegador con soporte Java en el que se estn ejecutando le indica al applet que se detengan, por ejemplo, cuando se minimiza la ventana del navegador o cuando se cambia de pgina.

El mtodo isAlive()
La interface de programacin de la clase Thread incluye el mtodo isAlive(), que devuelve true si el thread ha sido arrancado (con start()) y no ha sido detenido (con stop()). Por ello, si el mtodo isAlive() devuelve false, sabemos que estamos ante un "Nuevo Thread" o ante un thread "Muerto". Si nos devuelve true, sabemos que el thread se encuentra en estado "Ejecutable" o "Parado". No se puede diferenciar entre "Nuevo Thread" y "Muerto", ni entre un thread "Ejecutable" o "Parado".

Sincronizacin
Otra clave para el xito y la ventaja de la utilizacin de mltiples threads en una aplicacin, o aplicacin multithreaded, es que pueden comunicarse entre s. Se pueden disear threads para utilizar objetos comunes, que cada thread puede manipular independientemente de los otros threads. El ejemplo clsico de comunicacin de threads es un modelo productor y consumidor. Un thread produce una salida, que otro thread usa (consume), sea lo que sea esa salida. Vamos entonces a crear un productor, que ser un thread que ir sacando caracteres por su salida; crearemos tambin un consumidor que ira recogiendo los caracteres que vaya sacando el productor y un monitor que controlar el proceso de sincronizacin entre los threads. Funcionar como una tubera, insertando el productor caracteres en un extremo y leyndolos el consumidor en el otro, con el monitor siendo la propia tubera.

Productor
El productor extender la clase Thread, y su cdigo es el siguiente:

Notar que creamos una instancia de la clase Tubera, y que se utiliza el mtodo tuberia.lanzar() para que se vaya construyendo la tubera, en principio de 10 caracteres.

Consumidor
Veamos ahora el cdigo del consumidor, que tambin extender la clase Thread:

En este caso, como en el del productor, contamos con un mtodo en la clase Tubera, tuberia.recoger(), para manejar la informacin.

Monitor
Una vez vistos el productor de la informacin y el consumidor, nos queda por ver qu es lo que hace la clase Tubera. Lo que realiza la clase Tubera, es una funcin de supervisin de las transacciones entre los dos threads, el productor y el consumidor. Los monitores, en general, son piezas muy importantes de las aplicaciones multithreaded, porque mantienen el flujo de comunicacin entre los threads.

En la clase Tuberia vemos dos caractersticas importantes: los miembros dato (buffer[]) son privados, y los mtodos de acceso (lanzar() y recoger()) son sincronizados. Aqu vemos que la variable estaVacia es un semforo, como los de toda la vida. La naturaleza privada de los datos evita que el productor y el consumidor accedan directamente a stos. Si se permitiese el acceso directo de ambos threads a los datos, se podran producir problemas; por ejemplo, si el consumidor intenta retirar datos de un buffer vaco, obtendr excepciones innecesarias, o se bloquear el proceso. Los mtodos sincronizados de acceso impiden que los productores y consumidores corrompan un objeto compartido. Mientras el productor est aadiendo una letra a la tubera, el consumidor no la puede retirar y viceversa. Esta sincronizacin es vital para mantener la integridad de cualquier objeto compartido. No sera lo mismo sincronizar la clase en vez de los mtodos, porque esto significara que nadie puede acceder a las variables de la clase en paralelo, mientras que al sincronizar los mtodos, s pueden acceder a todas las variables que estn fuera de los mtodos que pertenecen a la clase.

Se pueden sincronizar incluso variables, para realizar alguna accin determinada sobre ellas, por ejemplo:

El mtodo notify() al final de cada mtodo de acceso avisa a cualquier proceso que est esperando por el objeto, entonces el proceso que ha estado esperando intentar acceder de nuevo al objeto. En el mtodo wait() hacemos que el thread se quede a la espera de que le llegue un notify(), ya sea enviado por el thread o por el sistema. Ahora que ya tenemos un productor, un consumidor y un objeto compartido, necesitamos una aplicacin que arranque los threads y que consiga que todos hablen con el mismo objeto que estn compartiendo. Esto es lo que hace el siguiente trozo de cdigo.

Compilando y ejecutando esta aplicacin, podremos observar nuestro modelo el pleno funcionamiento.

Monitorizacin del Productor


Los programas productor/consumidor a menudo emplean monitorizacin remota, que permite al consumidor observar el thread del productor interaccionando con un usuario o con otra parte del sistema. Por ejemplo, en una red, un grupo de threads productores podran trabajar cada uno en una workstation. Los productores imprimiran documentos, almacenando una entrada en un registro (log). Un consumidor (o mltiples consumidores) podra procesar el registro y realizar durante la noche un informe de la actividad de impresin del da anterior. Otro ejemplo, a pequea escala podra ser el uso de varias ventanas en una workstation. Una ventana se puede usar para la entrada de informacin (el productor), y otra ventana reaccionara a esa informacin (el consumidor).

Captulo 5: Diseo de GUI


SWING y AWT
El paquete Swing es parte de la JFC (Java Foundation Classes) en la plataforma Java. La JFC provee facilidades para ayudar a la gente a construir GUIs. Swing abarca componentes como botones, tablas, marcos, etc... Las componentes Swing se identifican porque pertenecen al paquete javax.swing. Swing existe desde la JDK 1.1 (como un agregado). Antes de la existencia de Swing, las interfaces grficas con el usuario se realizaban a travs de AWT (Abstract Window Toolkit), de quien Swing hereda todo el manejo de eventos. Usualmente, para toda componente AWT existe una componente Swing que la reemplaza, por ejemplo, la clase Button de AWT es reemplazada por la clase JButton de Swing (el nombre de todas las componentes Swing comienza con "J"). Las componentes de Swing utilizan la infraestructura de AWT, incluyendo el modelo de eventos AWT, el cual rige cmo una componente reacciona a eventos tales como, eventos de teclado, mouse, etc... Es por esto, que la mayora de los programas Swing necesitan importar dos paquetes AWT: java.awt.* y java.awt.event.*. Como regla, los programas no deben usar componenetes pesados de AWT junto a componentes Swing, ya que los componentes de AWT son siempre pintados sobre los de Swing. (Por componentes pesadas de AWT se entiende Menu, ScrollPane y todas las componentes que heredan de las clases Canvas y Panel de AWT).

Estructura bsica de una aplicacin Swing.


Una aplicacin Swing se construye mezclando componentes con las siguientes reglas. Debe existir, al menos, un contenedor de alto nivel (Top-Level Container), que provee el soporte que las componentes Swing necesitan para el pintado y el manejo de eventos. Otras componentes colgando del contenedor de alto nivel (stas pueden ser contenedores o componentes simples).

Ejemplo 1:

En las primeras lneas se importan los paquetes necesarios.

Luego se declara la clase HolaMundoSwing y en el mtodo main se setea el top level container:

En el ejemplo, slo hay un contenedor de alto nivel, un JFrame. Un frame implementado como una instancia de la clase JFrame es una ventana con decoraciones, tales como, borde, ttulo y botones como conos y para cerrar la ventana. Aplicaciones con un GUI tpicamente usan, al menos, un frame. Adems, el ejemplo tiene un componente, una etiqueta que dice "Hola Mundo".

Para que el botn de cerrar cierre la ventana, hay dos opciones:

Principales aspectos de una aplicacin Swing


Como ya se dijo antes, cada aplicacin Swing debe tener al menos un top-level container que contendr toda la aplicacin, estos pueden ser: javax.swing.JFrame: Una ventana independiente. javax.swing.JApplet: Un applet. Dilogos: ventanas de interaccin sencilla con el usuario como por ejemplo: java.swing.JOptionPane: Ventana de dilogo tipo SI_NO, SI_NO_CANCELAR, ACEPTAR, etc... java.swing.JFileChooser: Ventana para elejir un archivo. java.swing.JColorChooser etc. A un contenedor se le pueden agregar otros contenedores o componentes simples, para ver una muestra visual de cada componente y sus respectivas descripciones. Configurando el "Look & Feel" de una aplicacin Swing permite setear dinmicamente el aspecto y la forma de interaccin de una aplicacin, por ejemplo el siguiente cdigo setea el L&F al estilo Java

Existen los siguientes L&F: Java look & feel CDE/Motif look & feel Windows look & feel

Configurando el "Layout" de un contenedor


Varias componentes pueden contener otras componentes dentro, para determinar de qu modo esas componentes se organizarn visualmente se utiliza el concepto de Layout. Por ejemplo, el siguiente cdigo crea un frame y setea el layout del pao de contenidos (porcin central de la ventana) con BorderLayout y finalmente agrega una etiqueta al sur de la ventana.

A continuacin se muestran los diferentes layout estndares de swing.

Manejando eventos
Cada vez que el usuario interacta con la aplicacin se gatilla un evento, para que una componente determinada reaccione frente a un evento, debe poseer un "escuchador" con, al menos, un mtodo determinado que se ejecutar al escuchar un evento en particular, por ejemplo, en el siguiente cdigo se crea un botn que al ser presionado imprime en la salida estndar un mensaje.

Swing puede generar un variado set de eventos, en la siguiente tabla se resumen los ms comunes con sus respectivos "escuchadores".
Ejemplos de eventos y sus escuchadores Accin que gatilla un evento El usario hace un click, presiona Return en un rea de texto o selecciona un men El usuario escoje un frame (ventana principal) El usuario hace un click sobre una componente El usuario pasa el mouse sobre una componente Una componente se hace visible Una componente adquiere el foco del teclado Cambia la seleccin en una lista o tabla WindowListener MouseListener MouseMotionListener ComponentListener FocusListener ListSelectionListener Tipo de escuchador ActionListener

Threads y Swing
Como regla general slo un thread debe accesar una componente Swing, para lograr esto, la receta es que slo el thread que atiende los eventos invoque los mtodos de las componentes. El siguiente cdigo sigue el patrn "The Single-Thread Rule". //Ejemplo Thread-safe

Algunos mtodos dentro de la API de Swing estn marcados como "thread safe", stos pueden ser invocados concurrentemente por cualquier thread, el texto que indica esto es: "This method is thread safe, although most Swing methods are not."

Patrones de Diseo usados por SWING


Los patrones de diseo (design patterns) son la base para la bsqueda de soluciones a problemas comunes en el desarrollo de software y otros mbitos referentes al diseo de interaccin o interfaces. Un patrn de diseo es una solucin a un problema de diseo. Para que una solucin sea considerada un patrn debe poseer ciertas caractersticas. Una de ellas es que debe haber comprobado su efectividad resolviendo problemas similares en ocasiones anteriores. Otra es que debe ser reusable, lo que significa que es aplicable a diferentes problemas de diseo en distintas circunstancias. El esquema de SWING y AWT usa fundamentalmente 2 patrones de diseo, vamos a tomarnos un tiempo para hablar de ellos.

Patrn Decorador (Diseo de GUI)


El patrn Decorator responde a la necesidad de aadir dinmicamente funcionalidad a un Objeto. Esto nos permite no tener que crear sucesivas clases que hereden de la primera incorporando la nueva funcionalidad, sino otras que la implementan y se asocian a la primera. Problema que soluciona Supongamos que tenemos una clase existente Ventana y queremos aadirle funcionalidad para que muestre un borde alrededor. Podemos crear una subclase VentanaConBorde que herede de Ventana. Hasta aqu todo bien, pero supongamos que surge la necesidad de crear una ventana que muestre un pequeo botn de ayuda con un signo de interrogacin (?) en su parte superior.

Entonces tenemos las siguientes opciones: Crear otra subclase de Ventana: VentanaConBotnDeAyuda. Problema: No cubre la necesidad de tener ventanas con bordes y botn de ayuda a la vez. Crear una subclase de VentanaConBorde: VentanaConBordeYBotonDeAyuda. Problema: No tenemos una ventana con botn de ayuda y sin borde. Crear clases para todas las combinaciones posibles de funcionalidades. Problema: Con este ejemplo tendramos cuatro clases: Ventana, VentanaConBorde, VentanaConBotonDeAyuda y VentanaConBordeYBotonDeAyuda; con tres funcionalidades tendramos ocho clases y con cuatro, diecisis!

Aplicabilidad Aadir objetos individuales de forma dinmica y transparente Responsabilidades de un objeto pueden ser retiradas Cuando la extensin mediante la herencia no es viable Hay una necesidad de extender la funcionalidad de una clase, pero no hay razones para extenderlo a travs de la herencia. Hay la necesidad de extender dinmicamente la funcionalidad de un objeto y quizs quitar la funcionalidad extendida.

Implementacin
El patrn Decorator soluciona este problema de una manera mucho ms sencilla y extensible. Se crea a partir de Ventana la subclase abstracta VentanaDecorator y, heredando de ella, BordeDecorator y BotonDeAyudaDecorator. VentanaDecorator encapsula el comportamiento de Ventana y utiliza composicin recursiva para que sea posible aadir tantas "capas" de Decorators como se desee. Podemos crear tantos Decorators como queramos heredando de VentanaDecorator.

Patrn Observador (Manejo de Eventos)


El patrn Observador tambin conocido como "spider" define una dependencia del tipo uno-a-muchos entre objetos, de manera que cuando uno de los objetos cambia su estado, el observador se encarga de notificar este cambio a todos los otros dependientes. El objetivo de este patrn es desacoplar la clase de los objetos clientes del objeto, aumentando la modularidad del lenguaje, as como evitar bucles de actualizacin (espera activa o polling). Este patrn tambin se conoce como el patrn de publicacin-inscripcin o modelopatrn. Estos nombres sugieren las ideas bsicas del patrn, que son bien sencillas: el objeto de datos, llammoslo "Objeto" a partir de ahora, contiene atributos mediante los cuales cualquier objeto observador o vista se puede suscribir a l pasndole una referencia a s mismo. El Sujeto mantiene as una lista de las referencias a sus observadores. Los observadores a su vez estn obligados a implementar unos mtodos determinados mediante los cuales el Sujeto es capaz de notificar a sus observadores "suscritos" los cambios que sufre para que todos ellos tengan la oportunidad de refrescar el contenido representado. De manera que cuando se produce un cambio en el Sujeto, ejecutado, por ejemplo, por alguno de los observadores, el objeto de datos puede recorrer la lista de observadores avisando a cada uno. Este patrn suele observarse en los marcos de interfaces grficas orientados a objetos, en los que la forma de capturar los eventos es suscribir 'listeners' a los objetos que pueden disparar eventos. En Java se puede heredar la funcionalidad del patrn Observer de la clase Observable y los observadores pueden implementar la interfaz Observer y por lo tanto redefinir el mtodo update().

Jerarqua JComponent

Listeners
El modelo de componentes JavaBeans (y por tanto el conjunto de componentes Swing) est construido en base a propiedades y eventos. Las propiedades tienen mtodos setter y getter para trabajar con sus valores. Los eventos requieren que usted use listeners e implemente interfaces para recibir notificacin de sus ocurrencias. Aunque trabajar con propiedades es simple, los objetos listener requieren algo ms de discusin para entender cmo funcionan, generalmente, en el mundo de la interfaz grfica de usuario. (GUI). En especial, este artculo describe el AWT y las clases relacionadas con los eventos Swing que ofrecen una interfaz listener.

La clase ActionListener tiene un nico mtodo actionPerformed. Usando una clase interna annima, usted usar, generalmente, una clase ActionListener de la siguiente manera:

Se puede usar tambin el mtodo actionPerformed implementando la interfaz ActionListener en una clase de nivel superior:

La interfaz ActionListener tiene un nico mtodo y los implementadores de la interfaz deben proporcionar una implementacin de ese nico mtodo para que sta realice cualquier accin. Otras interfaces listener no son tan simplistas. Por ejemplo, la interfaz MouseMotionListener tiene dos mtodos: mouseDragged y mouseMoved. Cuando se implementa una interfaz, se deben implementar todas las operaciones definidas por la interfaz:

Existen situaciones en las que su aplicacin no necesita rastrear todos los eventos para una interfaz listener particular. Tal vez su cdigo slo necesite responder a uno o dos de los mtodos en la interfaz listener. Por ejemplo, Usted realmente quiere saber cundo el ratn se mueve o slo cuando este se mueve con un botn presionado? No se puede implementar slo uno de los mtodos MouseMotionListener y dejar a los otros fuera:

Esta implementacin listener resultar en un error de tiempo de compilacin ya que la interfaz no est completamente implementada. Con una interfaz como MouseMotionListener, esto no es un gran problema, usted slo tiene que agregar un stub para el mtodo en el que no est interesado:

No todas las interfaces listener son tan pequeas. Aunque MouseMotionListener tiene slo dos mtodos, la interfaz MouseListener tiene cinco:

Si quiere agregar un MouseListener a un componente, la implementacin de su interfaz deber tener cinco mtodos:

Si su aplicacin slo necesita saber si el ratn est presionado o liberado sobre un componente, los otros tres mtodos estarn vacos y sern ignorados. Estos mtodos son cdigo innecesario. Las clases adapter pueden ayudar a reducir la cantidad de cdigo que se debe escribir cuando su aplicacin necesita slo un pequeo subconjunto de todos los mtodos de interfaz. Cada clase adapter implementa completamente su interfaz (o interfaces) asociadas. Luego, si usted quiere un oyente para un subconjunto de mtodos asociados, slo tiene que agregar ese subconjunto. No se requieren stubs vacos.

A continuacin se muestra un adaptador similar para el MouseListener requerido que ha sido descrito previamente.

Este cdigo todava sigue creando un MouseListener. Sin embargo, en lugar de implementar todos los mtodos de la interfaz que usted no necesita, con la ayuda del MouseAdapter, slo debe implementar aquellos mtodos MouseListener en los que est realmente interesado. No todo listener tiene un adaptador. Sin duda alguna, usted puede crear el suyo propio haciendo stubs de todos los mtodos de la interfaz. Note que los adapters son verdaderas clases, no interfaces. Si usted quiere que su subclase de JButton implemente tambin un MouseListener, no puede hacer que tambin sea subclase de MouseAdapter, ya que slo est permitida la herencia nica. Por ejemplo, el cdigo siguiente causa un error de tiempo de compilacin porque intenta definir una subclase tanto para JButton como para MouseAdapter:

Si realmente se quiere que la subclase de JButton sea un MouseListener, esto se debe explicitar y asegurarse de que todos los mtodos de la interfaz se estn implementados:

Por supuesto, usted no tiene que hacer que su clase de nivel superior implemente la interfaz por s misma. ste puede ser un buen ejemplo de cundo se debe crear el oyente como una clase interna o annima en su lugar. Si usa un entorno integrado de desarrollo (IDE) para crear su interfaz de usuario, el IDE, con frecuencia, generar el framework de la interfaz por usted. Usted necesitar codificar la lgica de negocio dentro de los mtodos de interfaz necesarios. Un IDE puede simplificar la implementacin de una interfaz grande.

Los adapters no se limitan a la escucha del ratn. Sin embargo, el MouseAdapter es un ejemplo frecuente porque la interfaz MouseListener tiene muchos mtodos. La interfaz WindowListener es tambin otra interfaz grande y tiene una clase WindowAdapter asociada.

Captulo 6: Distribucin de aplicaciones


Archivos JAR
Una archivo JAR es simplemente un archivo comprimido que incluye una estructura de directorios con Clases, lo anterior permite: Distribuir/Utilizar Clases de una manera eficiente a travs de un solo archivo. Declarar dichas Clases de una manera ms eficiente en la variable CLASSPATH. En todo JDK/J2SE se incluye el comando jar el cual permite generar, observar y descomprimir archivos JAR; a continuacin se describen estos tres casos.

Generacin de Archivo JAR


Para generar un archivo JAR es necesario colocarse bajo el directorio raz de la estructura de directorios donde residen las Clases: jar cvf curso.jar * Al ejecutar el comando anterior se genera una archivo JAR llamado curso.jar con todos los archivos .class que residen en la estructura de directorios.

Observar contenido de Archivo JAR


Para observar el contenido de un archivo JAR, se utiliza un comando similar: jar tvf curso.jar El comando anterior despliega el contenido del archivo JAR curso.jar Este comando nicamente despliega el contenido, la extraccin de un archivo JAR se describe a continuacin.

Extraccin de Archivo JAR


En ocasiones es conveniente extraer el contenido de un archivo JAR para llevar acabo modificaciones, esto se realiza a travs del siguiente comando: jar xvf curso.jar

El comando anterior genera una estructura de directorios con el contenido del archivo JAR curso.jar.

Anda mungkin juga menyukai